Exemplo n.º 1
0
class GtkTimeTicker(TaskBaseWindow):
    """ plot against time a specific item / set of items
    Only works on arrays - so no singles!
    """
    def __init__(self, tick_cb, title=None, dt=1.0, len=100, limits=None):
        super(GtkTimeTicker, self).__init__(tick_cb=tick_cb, title=title, dt=dt)
        self._no_given_limits = limits is None
        self._len = len
        self._fig = fig = Figure()
        self._axis = axis = fig.add_subplot(111)
        self._times = []
        self._values = []
        self._lines = []
        self._gtkfig = FigureCanvasGTK(fig)
        self._w.add(self._gtkfig)
        self._w.set_size_request(300, 300)
        self._w.show_all()
        self._min_y, self._max_y = 0.0, 0.0
        self._limits = limits
        if limits:
            self.setYLimits(*limits)
        self._startTaskFirstTime()

    def _update(self, result):
        if len(result) == 0:
            print "GtkTimeTicker: empty length result, nothing to do\r\n"
            return
        if len(result) > len(self._lines):
            print "updating GtkTimeTicker to %s lines" % len(result)
            for i in xrange(len(result) - len(self._lines)):
                self._lines.append(self._axis.plot([],[])[0])
            if len(self._values) != len(result):
                # strange feature - if a new plot is added erase the old ones.
                self._values = [[] for i in xrange(len(result))]
            if self._limits:
                self.setYLimits(*self._limits)

        self._min_y, self._max_y = min(self._min_y, *result), max(self._max_y, *result)
        self._times.append(time.time() - self._start)
        for i, v in enumerate(result):
            self._values[i].append(v)
        if len(self._values[0]) > self._len:
            for values in self._values:
                del values[:(len(values) - self._len)]
            del self._times[:(len(self._times) - self._len)]
        self.updatePlot()

    def updatePlot(self):
        # TODO - better way then resetting the whole number of points.
        for line, values in zip(self._lines, self._values):
            line.set_data(self._times, values)
            if len(line._x) != len(line._y):
                import pdb; pdb.set_trace()
        self._axis.set_xlim(self._times[0], self._times[-1])
        if self._no_given_limits:
            self.setYLimits(self._min_y, self._max_y)
        self._gtkfig.draw()

    def setYLimits(self, lim_min, lim_max):
        self._axis.set_ylim(lim_min, lim_max)
Exemplo n.º 2
0
class DataManager(gtk.Window):
    numRows, numCols = 20,10
    data = random((numRows, numCols))
    def __init__(self):
        gtk.Window.__init__(self)
        self.set_default_size(600, 600)
        self.connect('destroy', lambda win: gtk.main_quit())
        self.set_title('GtkListStore demo')
        self.set_border_width(8)
        vbox = gtk.VBox(False, 8)
        self.add(vbox)
        label = gtk.Label('Double click a row to plot the data')
        vbox.pack_start(label, False, False)
        sw = gtk.ScrolledWindow()
        sw.set_shadow_type(gtk.SHADOW_ETCHED_IN)
        sw.set_policy(gtk.POLICY_NEVER,
                      gtk.POLICY_AUTOMATIC)
        vbox.pack_start(sw, True, True)
        model = self.create_model()
        self.treeview = gtk.TreeView(model)
        self.treeview.set_rules_hint(True)
        fig = Figure(figsize=(6,4))
        self.canvas = FigureCanvas(fig)  # a gtk.DrawingArea
        vbox.pack_start(self.canvas, True, True)
        ax = fig.add_subplot(111)
        self.line, = ax.plot(self.data[0,:], 'go')  # plot the first row
        self.treeview.connect('row-activated', self.plot_row)
        sw.add(self.treeview)
        self.add_columns()
        self.add_events(gdk.BUTTON_PRESS_MASK |
                        gdk.KEY_PRESS_MASK|
                        gdk.KEY_RELEASE_MASK)
    def plot_row(self, treeview, path, view_column):
        ind, = path  # get the index into data
        points = self.data[ind,:]
        self.line.set_ydata(points)
        self.canvas.draw()
    def add_columns(self):
        for i in range(self.numCols):
            column = gtk.TreeViewColumn('%d'%i, gtk.CellRendererText(), text=i)
            self.treeview.append_column(column)
    def create_model(self):
        types = [float]*self.numCols
        store = gtk.ListStore(*types)
        for row in self.data:
            store.append(row)
        return store
Exemplo n.º 3
0
class Graph(gtk.Frame):
    def __init__(self, label):
        self.plots = dict()
        gtk.Frame.__init__(self)
        self.set_label(label)
        self.fig = Figure(figsize=(6, 4))
        self.canvas = FigureCanvas(self.fig)  # a gtk.DrawingArea
        #self.add(self.canvas)
        vbox = gtk.VBox()
        vbox.pack_start(self.canvas)
        toolbar = NavigationToolbar(self.canvas, self)
        vbox.pack_start(toolbar, False, False)
        self.add(vbox)

    def clear(self):
        self.fig.clear()
        self.plots.clear()

    def draw(self, symbol, dates, values):
        years = YearLocator()  # every year
        months = MonthLocator()  # every month
        yearsFmt = DateFormatter('%Y')
        #monthFmt = DateFormatter('%m')

        #        coeffs = polyfit(dates, values, 3)
        #        besty = polyval(coeffs, dates)

        ax = self.fig.add_subplot(111)
        ax.plot(dates, values, label=symbol)
        ax.legend(loc='best', prop=FontProperties(size='9'))
        ax.grid(True)
        ax.xaxis.set_major_locator(years)
        ax.xaxis.set_major_formatter(yearsFmt)
        #ax.xaxis.set_minor_formatter(monthFmt)
        ax.xaxis.set_minor_locator(months)
        ax.autoscale_view()
        self.plots[symbol] = ax
        #self.fig1.autofmt_xdate()
        self.canvas.draw()

    def insert_annotations(self, symbol, cursor):
        ax = self.plots[symbol]
        for row in cursor:
            ax.annotate(row[0], xy=(row[1], row[2]))
        self.canvas.draw()
class JwsFileChooserDialog(gtk.FileChooserDialog):
    def __init__(self,
                 parent,
                 current_folder=None,
                 title=_("Open spectra...")):
        gtk.FileChooserDialog.__init__(
            self,
            title=title,
            parent=parent,
            action=gtk.FILE_CHOOSER_ACTION_OPEN,
            buttons=(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, gtk.STOCK_ADD,
                     gtk.RESPONSE_OK))
        self.figure = Figure(figsize=(5, 4))
        self.canvas = FigureCanvas(self.figure)
        self.canvas.set_size_request(200, 200)  #tamaño mínimo del widget
        self.add_filter(ff_jws)
        self.set_select_multiple(True)
        if current_folder:
            self.set_current_folder(current_folder)
        self.set_preview_widget(self.canvas)
        self.connect("selection-changed", self._update_preview_cb)
        self.show_all()

    def _update_preview_cb(self, widget):
        input_fn = self.get_preview_filename()
        error = True
        if input_fn is not None:
            results = jwslib.read_file(input_fn)
            if results[0] == jwslib.JWS_ERROR_SUCCESS:
                header = results[1]
                channels = results[2]
                if len(channels) > 0:
                    error = False
            if not error:
                xdata = arange(
                    header.x_for_first_point,  #start
                    header.x_for_last_point + header.x_increment,  #end+incr.
                    header.x_increment)  #increment
                ellipticity = array(channels[0], float32)
                self.figure.clear()
                p = self.figure.add_subplot(111)
                p.plot(xdata, ellipticity)
                self.canvas.draw()
        self.set_preview_widget_active(not error)
Exemplo n.º 5
0
class JwsFileChooserDialog(gtk.FileChooserDialog):
    def __init__(self, parent, current_folder=None, title=_("Open spectra...")):
        gtk.FileChooserDialog.__init__(
            self,
            title=title,
            parent=parent,
            action=gtk.FILE_CHOOSER_ACTION_OPEN,
            buttons=(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, gtk.STOCK_ADD, gtk.RESPONSE_OK),
        )
        self.figure = Figure(figsize=(5, 4))
        self.canvas = FigureCanvas(self.figure)
        self.canvas.set_size_request(200, 200)  # tamaño mínimo del widget
        self.add_filter(ff_jws)
        self.set_select_multiple(True)
        if current_folder:
            self.set_current_folder(current_folder)
        self.set_preview_widget(self.canvas)
        self.connect("selection-changed", self._update_preview_cb)
        self.show_all()

    def _update_preview_cb(self, widget):
        input_fn = self.get_preview_filename()
        error = True
        if input_fn is not None:
            results = jwslib.read_file(input_fn)
            if results[0] == jwslib.JWS_ERROR_SUCCESS:
                header = results[1]
                channels = results[2]
                if len(channels) > 0:
                    error = False
            if not error:
                xdata = arange(
                    header.x_for_first_point,  # start
                    header.x_for_last_point + header.x_increment,  # end+incr.
                    header.x_increment,
                )  # increment
                ellipticity = array(channels[0], float32)
                self.figure.clear()
                p = self.figure.add_subplot(111)
                p.plot(xdata, ellipticity)
                self.canvas.draw()
        self.set_preview_widget_active(not error)
Exemplo n.º 6
0
class GuiSessionViewer:
    def __init__(self, config, querylist, mainwin, owner, debug=True):
        self.debug = debug
        self.conf = config
        self.sql = querylist
        self.window = mainwin
        self.owner = owner

        self.liststore = None

        self.MYSQL_INNODB = 2
        self.PGSQL = 3
        self.SQLITE = 4

        self.fig = None
        self.canvas = None
        self.ax = None
        self.graphBox = None

        # create new db connection to avoid conflicts with other threads
        self.db = Database.Database(self.conf, sql=self.sql)
        self.cursor = self.db.cursor

        settings = {}
        settings.update(self.conf.get_db_parameters())
        settings.update(self.conf.get_import_parameters())
        settings.update(self.conf.get_default_paths())

        # text used on screen stored here so that it can be configured
        self.filterText = {
            'handhead': _('Hand Breakdown for all levels listed above')
        }

        filters_display = {
            "Heroes": True,
            "Sites": True,
            "Games": True,
            "Currencies": True,
            "Limits": True,
            "LimitSep": True,
            "LimitType": True,
            "Type": False,
            "Seats": True,
            "SeatSep": False,
            "Dates": True,
            "Groups": False,
            "GroupsAll": False,
            "Button1": True,
            "Button2": False
        }

        self.filters = Filters.Filters(self.db,
                                       self.conf,
                                       self.sql,
                                       display=filters_display)
        self.filters.registerButton1Name("_Refresh")
        self.filters.registerButton1Callback(self.refreshStats)

        # ToDo: store in config
        # ToDo: create popup to adjust column config
        # columns to display, keys match column name returned by sql, values in tuple are:
        #     is column displayed, column heading, xalignment, formatting
        self.columns = [(1.0, "SID"), (1.0, "Hands"), (0.5, "Start"),
                        (0.5, "End"), (1.0, "Rate"), (1.0, "Open"),
                        (1.0, "Close"), (1.0, "Low"), (1.0, "High"),
                        (1.0, "Range"), (1.0, "Profit")]

        self.detailFilters = []  # the data used to enhance the sql select

        self.main_hbox = gtk.HPaned()

        self.stats_frame = gtk.Frame()
        self.stats_frame.show()

        main_vbox = gtk.VPaned()
        main_vbox.show()
        self.graphBox = gtk.VBox(False, 0)
        self.graphBox.set_size_request(400, 400)
        self.graphBox.show()
        self.stats_vbox = gtk.VBox(False, 0)
        self.stats_vbox.show()
        self.stats_frame.add(self.stats_vbox)

        self.main_hbox.pack1(self.filters.get_vbox())
        self.main_hbox.pack2(main_vbox)
        main_vbox.pack1(self.graphBox)
        main_vbox.pack2(self.stats_frame)
        self.main_hbox.show()

        # make sure Hand column is not displayed
        #[x for x in self.columns if x[0] == 'hand'][0][1] = False
        # if DEBUG == False:
        #     warning_string = _("Session Viewer is proof of concept code only, and contains many bugs.\n")
        #     warning_string += _("Feel free to use the viewer, but there is no guarantee that the data is accurate.\n")
        #     warning_string += _("If you are interested in developing the code further please contact us via the usual channels.\n")
        #     warning_string += _("Thank you")
        #     self.warning_box(warning_string)

    def warning_box(self, str, diatitle=_("FPDB WARNING")):
        diaWarning = gtk.Dialog(title=diatitle,
                                parent=self.window,
                                flags=gtk.DIALOG_DESTROY_WITH_PARENT,
                                buttons=(gtk.STOCK_OK, gtk.RESPONSE_OK))

        label = gtk.Label(str)
        diaWarning.vbox.add(label)
        label.show()

        response = diaWarning.run()
        diaWarning.destroy()
        return response

    def get_vbox(self):
        """returns the vbox of this thread"""
        return self.main_hbox

    def refreshStats(self, widget, data):
        try:
            self.stats_vbox.destroy()
        except AttributeError:
            pass
        self.stats_vbox = gtk.VBox(False, 0)
        self.stats_vbox.show()
        self.stats_frame.add(self.stats_vbox)
        self.fillStatsFrame(self.stats_vbox)

    def fillStatsFrame(self, vbox):
        sites = self.filters.getSites()
        heroes = self.filters.getHeroes()
        siteids = self.filters.getSiteIds()
        games = self.filters.getGames()
        currencies = self.filters.getCurrencies()
        limits = self.filters.getLimits()
        seats = self.filters.getSeats()
        sitenos = []
        playerids = []

        for i in ('show', 'none'):
            if i in limits:
                limits.remove(i)

        # Which sites are selected?
        for site in sites:
            if sites[site] == True:
                sitenos.append(siteids[site])
                _hname = Charset.to_utf8(heroes[site])
                result = self.db.get_player_id(self.conf, site, _hname)
                if result is not None:
                    playerids.append(result)

        if not sitenos:
            #Should probably pop up here.
            print _("No sites selected - defaulting to PokerStars")
            sitenos = [2]
        if not games:
            print _("No games found")
            return
        if not currencies:
            print _("No currencies found")
            return
        if not playerids:
            print _("No player ids found")
            return
        if not limits:
            print _("No limits found")
            return

        self.createStatsPane(vbox, playerids, sitenos, games, currencies,
                             limits, seats)

    def createStatsPane(self, vbox, playerids, sitenos, games, currencies,
                        limits, seats):
        starttime = time()

        (results, quotes) = self.generateDatasets(playerids, sitenos, games,
                                                  currencies, limits, seats)

        if DEBUG:
            for x in quotes:
                print "start %s\tend %s  \thigh %s\tlow %s" % (x[1], x[2],
                                                               x[3], x[4])

        self.generateGraph(quotes)

        heading = gtk.Label(self.filterText['handhead'])
        heading.show()
        vbox.pack_start(heading, expand=False, padding=3)

        # Scrolled window for detailed table (display by hand)
        swin = gtk.ScrolledWindow(hadjustment=None, vadjustment=None)
        swin.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
        swin.show()
        vbox.pack_start(swin, expand=True, padding=3)

        vbox1 = gtk.VBox(False, 0)
        vbox1.show()
        swin.add_with_viewport(vbox1)

        self.addTable(vbox1, results)

        self.db.rollback()
        print _("Stats page displayed in %4.2f seconds") % (time() - starttime)

    #end def fillStatsFrame(self, vbox):

    def generateDatasets(self, playerids, sitenos, games, currencies, limits,
                         seats):
        if (DEBUG): print "DEBUG: Starting generateDatasets"
        THRESHOLD = 1800  # Min # of secs between consecutive hands before being considered a new session
        PADDING = 5  # Additional time in minutes to add to a session, session startup, shutdown etc

        # Get a list of timestamps and profits

        q = self.sql.query['sessionStats']
        start_date, end_date = self.filters.getDates()
        q = q.replace("<datestest>",
                      " BETWEEN '" + start_date + "' AND '" + end_date + "'")

        l = []
        for m in self.filters.display.items():
            if m[0] == 'Games' and m[1]:
                for n in games:
                    if games[n]:
                        l.append(n)
                if len(l) > 0:
                    gametest = str(tuple(l))
                    gametest = gametest.replace("L", "")
                    gametest = gametest.replace(",)", ")")
                    gametest = gametest.replace("u'", "'")
                    gametest = "AND gt.category in %s" % gametest
                else:
                    gametest = "AND gt.category IS NULL"
        q = q.replace("<game_test>", gametest)

        limittest = self.filters.get_limits_where_clause(limits)
        q = q.replace("<limit_test>", limittest)

        l = []
        for n in currencies:
            if currencies[n]:
                l.append(n)
        currencytest = str(tuple(l))
        currencytest = currencytest.replace(",)", ")")
        currencytest = currencytest.replace("u'", "'")
        currencytest = "AND gt.currency in %s" % currencytest
        q = q.replace("<currency_test>", currencytest)

        if seats:
            q = q.replace(
                '<seats_test>', 'AND h.seats BETWEEN ' + str(seats['from']) +
                ' AND ' + str(seats['to']))
        else:
            q = q.replace('<seats_test>', 'AND h.seats BETWEEN 0 AND 100')

        nametest = str(tuple(playerids))
        nametest = nametest.replace("L", "")
        nametest = nametest.replace(",)", ")")
        q = q.replace("<player_test>", nametest)
        q = q.replace("<ampersand_s>", "%s")

        if DEBUG:
            hands = [
                (u'10000', 10),
                (u'10000', 20),
                (u'10000', 30),
                (u'20000', -10),
                (u'20000', -20),
                (u'20000', -30),
                (u'30000', 40),
                (u'40000', 0),
                (u'50000', -40),
                (u'60000', 10),
                (u'60000', 30),
                (u'60000', -20),
                (u'70000', -20),
                (u'70000', 10),
                (u'70000', 30),
                (u'80000', -10),
                (u'80000', -30),
                (u'80000', 20),
                (u'90000', 20),
                (u'90000', -10),
                (u'90000', -30),
                (u'100000', 30),
                (u'100000', -50),
                (u'100000', 30),
                (u'110000', -20),
                (u'110000', 50),
                (u'110000', -20),
                (u'120000', -30),
                (u'120000', 50),
                (u'120000', -30),
                (u'130000', 20),
                (u'130000', -50),
                (u'130000', 20),
                (u'140000', 40),
                (u'140000', -40),
                (u'150000', -40),
                (u'150000', 40),
                (u'160000', -40),
                (u'160000', 80),
                (u'160000', -40),
            ]
        else:
            self.db.cursor.execute(q)
            hands = self.db.cursor.fetchall()

        #fixme - nasty hack to ensure that the hands.insert() works
        # for mysql data.  mysql returns tuples which can't be inserted
        # into so convert explicity to list.
        hands = list(hands)

        if (not hands):
            return ([], [])

        hands.insert(0, (hands[0][0], 0))

        # Take that list and create an array of the time between hands
        times = map(lambda x: long(x[0]), hands)
        profits = map(lambda x: float(x[1]), hands)
        #print "DEBUG: times   : %s" % times
        #print "DEBUG: profits: %s" % profits
        #print "DEBUG: len(times) %s" %(len(times))
        diffs = diff(
            times
        )  # This array is the difference in starttime between consecutive hands
        diffs2 = append(
            diffs, THRESHOLD + 1
        )  # Append an additional session to the end of the diffs, so the next line
        # includes an index into the last 'session'
        index = nonzero(
            diffs2 > THRESHOLD
        )  # This array represents the indexes into 'times' for start/end times of sessions
        # times[index[0][0]] is the end of the first session,
        #print "DEBUG: len(index[0]) %s" %(len(index[0]))
        if len(index[0]) > 0:
            #print "DEBUG: index[0][0] %s" %(index[0][0])
            #print "DEBUG: index %s" %(index)
            pass
        else:
            index = [[0]]
            #print "DEBUG: index %s" %(index)
            #print "DEBUG: index[0][0] %s" %(index[0][0])
            pass

        first_idx = 1
        quotes = []
        results = []
        cum_sum = cumsum(profits) / 100
        sid = 1

        total_hands = 0
        total_time = 0
        global_open = None
        global_lwm = None
        global_hwm = None

        self.times = []
        # Take all results and format them into a list for feeding into gui model.
        #print "DEBUG: range(len(index[0]): %s" % range(len(index[0]))
        for i in range(len(index[0])):
            last_idx = index[0][i]
            hds = last_idx - first_idx + 1  # Number of hands in session
            if hds > 0:
                stime = strftime("%d/%m/%Y %H:%M", localtime(
                    times[first_idx]))  # Formatted start time
                etime = strftime("%d/%m/%Y %H:%M", localtime(
                    times[last_idx]))  # Formatted end time
                self.times.append((times[first_idx], times[last_idx]))
                minutesplayed = (times[last_idx] - times[first_idx]) / 60
                minutesplayed = minutesplayed + PADDING
                if minutesplayed == 0:
                    minutesplayed = 1
                hph = hds * 60 / minutesplayed  # Hands per hour
                end_idx = last_idx + 1
                won = sum(profits[first_idx:end_idx]) / 100.0
                #print "DEBUG: profits[%s:%s]: %s" % (first_idx, end_idx, profits[first_idx:end_idx])
                hwm = max(cum_sum[first_idx -
                                  1:end_idx])  # include the opening balance,
                lwm = min(cum_sum[first_idx -
                                  1:end_idx])  # before we win/lose first hand
                open = (sum(profits[:first_idx])) / 100
                close = (sum(profits[:end_idx])) / 100
                #print "DEBUG: range: (%s, %s) - (min, max): (%s, %s) - (open,close): (%s, %s)" %(first_idx, end_idx, lwm, hwm, open, close)

                total_hands = total_hands + hds
                total_time = total_time + minutesplayed
                if (global_lwm == None or global_lwm > lwm):
                    global_lwm = lwm
                if (global_hwm == None or global_hwm < hwm):
                    global_hwm = hwm
                if (global_open == None):
                    global_open = open
                    global_stime = stime

                results.append([
                    sid, hds, stime, etime, hph,
                    "%.2f" % open,
                    "%.2f" % close,
                    "%.2f" % lwm,
                    "%.2f" % hwm,
                    "%.2f" % (hwm - lwm),
                    "%.2f" % won
                ])
                quotes.append((sid, open, close, hwm, lwm))
                #print "DEBUG: Hands in session %4s: %4s  Start: %s End: %s HPH: %s Profit: %s" %(sid, hds, stime, etime, hph, won)
                first_idx = end_idx
                sid = sid + 1
            else:
                print "hds <= 0"
        global_close = close
        global_etime = etime
        results.append([''] * 11)
        results.append([
            _("all"), total_hands, global_stime, global_etime,
            total_hands * 60 / total_time,
            "%.2f" % global_open,
            "%.2f" % global_close,
            "%.2f" % global_lwm,
            "%.2f" % global_hwm,
            "%.2f" % (global_hwm - global_lwm),
            "%.2f" % (global_close - global_open)
        ])

        return (results, quotes)

    def clearGraphData(self):

        try:
            try:
                if self.canvas:
                    self.graphBox.remove(self.canvas)
            except:
                pass

            if self.fig is not None:
                self.fig.clear()
            self.fig = Figure(figsize=(5, 4), dpi=100)
            if self.canvas is not None:
                self.canvas.destroy()

            self.canvas = FigureCanvas(self.fig)  # a gtk.DrawingArea
        except:
            err = traceback.extract_tb(sys.exc_info()[2])[-1]
            print _("Error:") + " " + err[2] + "(" + str(err[1]) + "): " + str(
                sys.exc_info()[1])
            raise

    def generateGraph(self, quotes):
        self.clearGraphData()

        #print "DEBUG:"
        #print "\tquotes = %s" % quotes

        #for i in range(len(highs)):
        #    print "DEBUG: (%s, %s, %s, %s)" %(lows[i], opens[i], closes[i], highs[i])
        #    print "DEBUG: diffs h/l: %s o/c: %s" %(lows[i] - highs[i], opens[i] - closes[i])

        self.ax = self.fig.add_subplot(111)

        self.ax.set_title(_("Session candlestick graph"))

        #Set axis labels and grid overlay properites
        self.ax.set_xlabel(_("Sessions"), fontsize=12)
        self.ax.set_ylabel("$", fontsize=12)
        self.ax.grid(color='g', linestyle=':', linewidth=0.2)

        candlestick(self.ax,
                    quotes,
                    width=0.50,
                    colordown='r',
                    colorup='g',
                    alpha=1.00)
        self.graphBox.add(self.canvas)
        self.canvas.show()
        self.canvas.draw()

    def addTable(self, vbox, results):
        row = 0
        sqlrow = 0
        colxalign, colheading = range(2)

        self.liststore = gtk.ListStore(*([str] * len(self.columns)))
        for row in results:
            iter = self.liststore.append(row)

        view = gtk.TreeView(model=self.liststore)
        view.set_grid_lines(gtk.TREE_VIEW_GRID_LINES_BOTH)
        vbox.add(view)
        print view.connect("row-activated", self.row_activated)
        cell05 = gtk.CellRendererText()
        cell05.set_property('xalign', 0.5)
        cell10 = gtk.CellRendererText()
        cell10.set_property('xalign', 1.0)
        listcols = []

        # Create header row   eg column: ("game",     True, "Game",     0.0, "%s")
        for col, column in enumerate(self.columns):
            treeviewcolumn = gtk.TreeViewColumn(column[colheading])
            listcols.append(treeviewcolumn)
            treeviewcolumn.set_alignment(column[colxalign])
            view.append_column(listcols[col])
            if (column[colxalign] == 0.5):
                cell = cell05
            else:
                cell = cell10
            listcols[col].pack_start(cell, expand=True)
            listcols[col].add_attribute(cell, 'text', col)
            listcols[col].set_expand(True)

        vbox.show_all()

    def row_activated(self, view, path, column):
        if path[0] < len(self.times):
            replayer = None
            for tabobject in self.owner.threads:
                if isinstance(tabobject, GuiHandViewer.GuiHandViewer):
                    replayer = tabobject
                    self.owner.tab_hand_viewer(None)
                    break
            if replayer is None:
                self.owner.tab_hand_viewer(None)
                for tabobject in self.owner.threads:
                    if isinstance(tabobject, GuiHandViewer.GuiHandViewer):
                        replayer = tabobject
                        break
            # added the timezone offset ('+00:00') to make the db query work. Otherwise the hands
            # at the edges of the date range are not included. A better solution may be possible.
            # Optionally the end date in the call below, which is a Long gets a '+1'.
            reformat = lambda t: strftime("%Y-%m-%d %H:%M:%S+00:00", gmtime(t))
            handids = replayer.get_hand_ids_from_date_range(
                reformat(self.times[path[0]][0]),
                reformat(self.times[path[0]][1]),
                save_date=True)
            replayer.reload_hands(handids)
Exemplo n.º 7
0
class GuiGraphViewer (threading.Thread):

    def __init__(self, querylist, config, parent, debug=True):
        """Constructor for GraphViewer"""
        self.sql = querylist
        self.conf = config
        self.debug = debug
        self.parent = parent
        #print "start of GraphViewer constructor"
        self.db = Database.Database(self.conf, sql=self.sql)


        filters_display = { "Heroes"    : True,
                            "Sites"     : True,
                            "Games"     : True,
                            "Limits"    : True,
                            "LimitSep"  : True,
                            "LimitType" : True,
                            "Type"      : False,
                            "UseType"   : 'ring',
                            "Seats"     : False,
                            "SeatSep"   : False,
                            "Dates"     : True,
                            "GraphOps"  : True,
                            "Groups"    : False,
                            "Button1"   : True,
                            "Button2"   : True
                          }

        self.filters = Filters.Filters(self.db, self.conf, self.sql, display = filters_display)
        self.filters.registerButton1Name(_("Refresh _Graph"))
        self.filters.registerButton1Callback(self.generateGraph)
        self.filters.registerButton2Name(_("_Export to File"))
        self.filters.registerButton2Callback(self.exportGraph)

        self.mainHBox = gtk.HBox(False, 0)
        self.mainHBox.show()

        self.leftPanelBox = self.filters.get_vbox()

        self.hpane = gtk.HPaned()
        self.hpane.pack1(self.leftPanelBox)
        self.mainHBox.add(self.hpane)
        # hierarchy:  self.mainHBox / self.hpane / self.graphBox / self.canvas / self.fig / self.ax

        self.graphBox = gtk.VBox(False, 0)
        self.graphBox.show()
        self.hpane.pack2(self.graphBox)
        self.hpane.show()

        self.fig = None
        #self.exportButton.set_sensitive(False)
        self.canvas = None


        self.db.rollback()

    def get_vbox(self):
        """returns the vbox of this thread"""
        return self.mainHBox
    #end def get_vbox

    def clearGraphData(self):

        try:
            try:
                if self.canvas:
                    self.graphBox.remove(self.canvas)
            except:
                pass

            if self.fig != None:
                self.fig.clear()
            self.fig = Figure(figsize=(5,4), dpi=100)
            if self.canvas is not None:
                self.canvas.destroy()

            self.canvas = FigureCanvas(self.fig)  # a gtk.DrawingArea
        except:
            err = traceback.extract_tb(sys.exc_info()[2])[-1]
            print _("Error:")+" "+err[2]+"("+str(err[1])+"): "+str(sys.exc_info()[1])
            raise

    def generateGraph(self, widget, data):
        try:
            self.clearGraphData()

            sitenos = []
            playerids = []

            sites   = self.filters.getSites()
            heroes  = self.filters.getHeroes()
            siteids = self.filters.getSiteIds()
            limits  = self.filters.getLimits()
            games   = self.filters.getGames()
            graphops = self.filters.getGraphOps()
            names   = ""
            
            for i in ('show', 'none'):
                if i in limits:
                    limits.remove(i)
            # Which sites are selected?
            for site in sites:
                if sites[site] == True:
                    sitenos.append(siteids[site])
                    _hname = Charset.to_utf8(heroes[site])
                    result = self.db.get_player_id(self.conf, site, _hname)
                    if result is not None:
                        playerids.append(int(result))
                        names = names + "\n"+_hname + " on "+site

            if not sitenos:
                #Should probably pop up here.
                print _("No sites selected - defaulting to PokerStars")
                self.db.rollback()
                return

            if not playerids:
                print _("No player ids found")
                self.db.rollback()
                return

            if not limits:
                print _("No limits found")
                self.db.rollback()
                return

            #Set graph properties
            self.ax = self.fig.add_subplot(111)

            #Get graph data from DB
            starttime = time()
            (green, blue, red) = self.getRingProfitGraph(playerids, sitenos, limits, games, graphops['dspin'])
            print _("Graph generated in: %s") %(time() - starttime)



            #Set axis labels and grid overlay properites
            self.ax.set_xlabel(_("Hands"), fontsize = 12)
            # SET LABEL FOR X AXIS
            self.ax.set_ylabel(graphops['dspin'], fontsize = 12)
            self.ax.grid(color='g', linestyle=':', linewidth=0.2)
            if green == None or green == []:
                self.ax.set_title(_("No Data for Player(s) Found"))
                green = ([    0.,     0.,     0.,     0.,   500.,  1000.,   900.,   800.,
                            700.,   600.,   500.,   400.,   300.,   200.,   100.,     0.,
                            500.,  1000.,  1000.,  1000.,  1000.,  1000.,  1000.,  1000.,
                            1000., 1000.,  1000.,  1000.,  1000.,  1000.,   875.,   750.,
                            625.,   500.,   375.,   250.,   125.,     0.,     0.,     0.,
                            0.,   500.,  1000.,   900.,   800.,   700.,   600.,   500.,
                            400.,   300.,   200.,   100.,     0.,   500.,  1000.,  1000.])
                red   =  ([    0.,     0.,     0.,     0.,   500.,  1000.,   900.,   800.,
                            700.,   600.,   500.,   400.,   300.,   200.,   100.,     0.,
                            0.,   0.,     0.,     0.,     0.,     0.,   125.,   250.,
                            375.,   500.,   500.,   500.,   500.,   500.,   500.,   500.,
                            500.,   500.,   375.,   250.,   125.,     0.,     0.,     0.,
                            0.,   500.,  1000.,   900.,   800.,   700.,   600.,   500.,
                            400.,   300.,   200.,   100.,     0.,   500.,  1000.,  1000.])
                blue =    ([    0.,     0.,     0.,     0.,   500.,  1000.,   900.,   800.,
                              700.,   600.,   500.,   400.,   300.,   200.,   100.,     0.,
                              0.,     0.,     0.,     0.,     0.,     0.,   125.,   250.,
                              375.,   500.,   625.,   750.,   875.,  1000.,   875.,   750.,
                              625.,   500.,   375.,   250.,   125.,     0.,     0.,     0.,
                            0.,   500.,  1000.,   900.,   800.,   700.,   600.,   500.,
                            400.,   300.,   200.,   100.,     0.,   500.,  1000.,  1000.])

                self.ax.plot(green, color='green', label=_('Hands: %d\nProfit: (%s): %.2f') %(len(green), green[-1]))
                self.ax.plot(blue, color='blue', label=_('Showdown') + ': $%.2f' %(blue[-1]))
                self.ax.plot(red, color='red', label=_('Non-showdown') + ': $%.2f' %(red[-1]))
                self.graphBox.add(self.canvas)
                self.canvas.show()
                self.canvas.draw()

                #TODO: Do something useful like alert user
                #print "No hands returned by graph query"
            else:
                self.ax.set_title((_("Profit graph for ring games")+names),fontsize=12)

                #Draw plot
                self.ax.plot(green, color='green', label=_('Hands: %d\nProfit: (%s): %.2f') %(len(green),graphops['dspin'], green[-1]))
                if graphops['showdown'] == 'ON':
                    self.ax.plot(blue, color='blue', label=_('Showdown') + ' (%s): %.2f' %(graphops['dspin'], blue[-1]))
                if graphops['nonshowdown'] == 'ON':
                    self.ax.plot(red, color='red', label=_('Non-showdown') + ' (%s): %.2f' %(graphops['dspin'], red[-1]))

                if sys.version[0:3] == '2.5':
                    self.ax.legend(loc='upper left', shadow=True, prop=FontProperties(size='smaller'))
                else:
                    self.ax.legend(loc='upper left', fancybox=True, shadow=True, prop=FontProperties(size='smaller'))

                self.graphBox.add(self.canvas)
                self.canvas.show()
                self.canvas.draw()
                #self.exportButton.set_sensitive(True)
        except:
            err = traceback.extract_tb(sys.exc_info()[2])[-1]
            print _("Error:")+" "+err[2]+"("+str(err[1])+"): "+str(sys.exc_info()[1])

    #end of def showClicked


    def getRingProfitGraph(self, names, sites, limits, games, units):
#        tmp = self.sql.query['getRingProfitAllHandsPlayerIdSite']
#        print "DEBUG: getRingProfitGraph"

        if units == '$':
            tmp = self.sql.query['getRingProfitAllHandsPlayerIdSiteInDollars']
        elif units == 'BB':
            tmp = self.sql.query['getRingProfitAllHandsPlayerIdSiteInBB']


        start_date, end_date = self.filters.getDates()

        #Buggered if I can find a way to do this 'nicely' take a list of integers and longs
        # and turn it into a tuple readale by sql.
        # [5L] into (5) not (5,) and [5L, 2829L] into (5, 2829)
        nametest = str(tuple(names))
        sitetest = str(tuple(sites))
        #nametest = nametest.replace("L", "")

        q = []
        for m in self.filters.display.items():
            if m[0] == 'Games' and m[1]:
                for n in games:
                    if games[n]:
                        q.append(n)
                if len(q) > 0:
                    gametest = str(tuple(q))
                    gametest = gametest.replace("L", "")
                    gametest = gametest.replace(",)",")")
                    gametest = gametest.replace("u'","'")
                    gametest = "and gt.category in %s" % gametest
                else:
                    gametest = "and gt.category IS NULL"
        tmp = tmp.replace("<game_test>", gametest)
        
        lims = [int(x) for x in limits if x.isdigit()]
        potlims = [int(x[0:-2]) for x in limits if len(x) > 2 and x[-2:] == 'pl']
        nolims = [int(x[0:-2]) for x in limits if len(x) > 2 and x[-2:] == 'nl']
        capnolims = [int(x[0:-2]) for x in limits if len(x) > 2 and x[-2:] == 'cn']
        limittest = "and ( (gt.limitType = 'fl' and gt.bigBlind in "
                 # and ( (limit and bb in()) or (nolimit and bb in ()) )
        if lims:
            blindtest = str(tuple(lims))
            blindtest = blindtest.replace("L", "")
            blindtest = blindtest.replace(",)",")")
            limittest = limittest + blindtest + ' ) '
        else:
            limittest = limittest + '(-1) ) '
        limittest = limittest + " or (gt.limitType = 'pl' and gt.bigBlind in "
        if potlims:
            blindtest = str(tuple(potlims))
            blindtest = blindtest.replace("L", "")
            blindtest = blindtest.replace(",)",")")
            limittest = limittest + blindtest + ' ) '
        else:
            limittest = limittest + '(-1) ) '
        limittest = limittest + " or (gt.limitType = 'nl' and gt.bigBlind in "
        if nolims:
            blindtest = str(tuple(nolims))
            blindtest = blindtest.replace("L", "")
            blindtest = blindtest.replace(",)",")")
            limittest = limittest + blindtest + ' ) '
        else:
            limittest = limittest + '(-1) ) '
        limittest = limittest + " or (gt.limitType = 'cn' and gt.bigBlind in "
        if capnolims:
            blindtest = str(tuple(capnolims))
            blindtest = blindtest.replace("L", "")
            blindtest = blindtest.replace(",)",")")
            limittest = limittest + blindtest + ' ) )'
        else:
            limittest = limittest + '(-1) ) )'

        if type == 'ring':
            limittest = limittest + " and gt.type = 'ring' "
        elif type == 'tour':
            limittest = limittest + " and gt.type = 'tour' "

        #Must be a nicer way to deal with tuples of size 1 ie. (2,) - which makes sql barf
        tmp = tmp.replace("<player_test>", nametest)
        tmp = tmp.replace("<site_test>", sitetest)
        tmp = tmp.replace("<startdate_test>", start_date)
        tmp = tmp.replace("<enddate_test>", end_date)
        tmp = tmp.replace("<limit_test>", limittest)
        tmp = tmp.replace(",)", ")")

        #print "DEBUG: sql query:"
        #print tmp
        self.db.cursor.execute(tmp)
        #returns (HandId,Winnings,Costs,Profit)
        winnings = self.db.cursor.fetchall()
        self.db.rollback()

        if len(winnings) == 0:
            return (None, None, None)

        green = map(lambda x:float(x[1]), winnings)
        blue  = map(lambda x: float(x[1]) if x[2] == True  else 0.0, winnings)
        red   = map(lambda x: float(x[1]) if x[2] == False else 0.0, winnings)
        greenline = cumsum(green)
        blueline  = cumsum(blue)
        redline   = cumsum(red)
        return (greenline/100, blueline/100, redline/100)
        #end of def getRingProfitGraph

    def exportGraph (self, widget, data):
        if self.fig is None:
            return # Might want to disable export button until something has been generated.

        dia_chooser = gtk.FileChooserDialog(title=_("Please choose the directory you wish to export to:"),
                                            action=gtk.FILE_CHOOSER_ACTION_SELECT_FOLDER,
                                            buttons=(gtk.STOCK_CANCEL,gtk.RESPONSE_CANCEL,gtk.STOCK_OK,gtk.RESPONSE_OK))
        dia_chooser.set_destroy_with_parent(True)
        dia_chooser.set_transient_for(self.parent)
        try: 
            dia_chooser.set_filename(self.exportFile) # use previously chosen export path as default
        except:
            pass

        response = dia_chooser.run()
        
        if response <> gtk.RESPONSE_OK:
            print _('Closed, no graph exported')
            dia_chooser.destroy()
            return
            
        # generate a unique filename for export
        now = datetime.now()
        now_formatted = now.strftime("%Y%m%d%H%M%S")
        self.exportFile = dia_chooser.get_filename() + "/fpdb" + now_formatted + ".png"
        dia_chooser.destroy()
        
        #print "DEBUG: self.exportFile = %s" %(self.exportFile)
        self.fig.savefig(self.exportFile, format="png")

        #display info box to confirm graph created
        diainfo = gtk.MessageDialog(parent=self.parent,
                                flags=gtk.DIALOG_DESTROY_WITH_PARENT,
                                type=gtk.MESSAGE_INFO,
                                buttons=gtk.BUTTONS_OK,
                                message_format=_("Graph created"))
        diainfo.format_secondary_text(self.exportFile)          
        diainfo.run()
        diainfo.destroy()
Exemplo n.º 8
0
class GuiGraphViewer(threading.Thread):
    def __init__(self, querylist, config, parent, debug=True):
        """Constructor for GraphViewer"""
        self.sql = querylist
        self.conf = config
        self.debug = debug
        self.parent = parent
        # print "start of GraphViewer constructor"
        self.db = Database.Database(self.conf, sql=self.sql)

        filters_display = {
            "Heroes": True,
            "Sites": True,
            "Games": True,
            "Currencies": True,
            "Limits": True,
            "LimitSep": True,
            "LimitType": True,
            "Type": False,
            "UseType": "ring",
            "Seats": False,
            "SeatSep": False,
            "Dates": True,
            "GraphOps": True,
            "Groups": False,
            "Button1": True,
            "Button2": True,
        }

        self.filters = Filters.Filters(self.db, self.conf, self.sql, display=filters_display)
        self.filters.registerButton1Name(_("Refresh _Graph"))
        self.filters.registerButton1Callback(self.generateGraph)
        self.filters.registerButton2Name(_("_Export to File"))
        self.filters.registerButton2Callback(self.exportGraph)

        self.mainHBox = gtk.HBox(False, 0)
        self.mainHBox.show()

        self.leftPanelBox = self.filters.get_vbox()

        self.hpane = gtk.HPaned()
        self.hpane.pack1(self.leftPanelBox)
        self.mainHBox.add(self.hpane)
        # hierarchy:  self.mainHBox / self.hpane / self.graphBox / self.canvas / self.fig / self.ax

        self.graphBox = gtk.VBox(False, 0)
        self.graphBox.show()
        self.hpane.pack2(self.graphBox)
        self.hpane.show()

        self.fig = None
        # self.exportButton.set_sensitive(False)
        self.canvas = None

        self.exportFile = None

        self.db.rollback()

    def get_vbox(self):
        """returns the vbox of this thread"""
        return self.mainHBox

    # end def get_vbox

    def clearGraphData(self):
        try:
            if self.canvas:
                self.graphBox.remove(self.canvas)
        except:
            pass

        if self.fig != None:
            self.fig.clear()
        self.fig = Figure(figsize=(5, 4), dpi=100)
        if self.canvas is not None:
            self.canvas.destroy()

        self.canvas = FigureCanvas(self.fig)  # a gtk.DrawingArea

    def generateGraph(self, widget, data):
        self.clearGraphData()

        sitenos = []
        playerids = []

        sites = self.filters.getSites()
        heroes = self.filters.getHeroes()
        siteids = self.filters.getSiteIds()
        limits = self.filters.getLimits()
        games = self.filters.getGames()
        currencies = self.filters.getCurrencies()
        graphops = self.filters.getGraphOps()
        names = ""

        for i in ("show", "none"):
            if i in limits:
                limits.remove(i)
        # Which sites are selected?
        for site in sites:
            if sites[site] == True:
                sitenos.append(siteids[site])
                _hname = Charset.to_utf8(heroes[site])
                result = self.db.get_player_id(self.conf, site, _hname)
                if result is not None:
                    playerids.append(int(result))
                    names = names + "\n" + _hname + " on " + site

        if not sitenos:
            # Should probably pop up here.
            print _("No sites selected - defaulting to PokerStars")
            self.db.rollback()
            return

        if not playerids:
            print _("No player ids found")
            self.db.rollback()
            return

        if not limits:
            print _("No limits found")
            self.db.rollback()
            return

        # Set graph properties
        self.ax = self.fig.add_subplot(111)

        # Get graph data from DB
        starttime = time()
        (green, blue, red, orange) = self.getRingProfitGraph(
            playerids, sitenos, limits, games, currencies, graphops["dspin"]
        )
        print _("Graph generated in: %s") % (time() - starttime)

        # Set axis labels and grid overlay properites
        self.ax.set_xlabel(_("Hands"))
        # SET LABEL FOR X AXIS
        self.ax.set_ylabel(graphops["dspin"])
        self.ax.grid(color="g", linestyle=":", linewidth=0.2)
        if green == None or green == []:
            self.ax.set_title(_("No Data for Player(s) Found"))
            green = [
                0.0,
                0.0,
                0.0,
                0.0,
                500.0,
                1000.0,
                900.0,
                800.0,
                700.0,
                600.0,
                500.0,
                400.0,
                300.0,
                200.0,
                100.0,
                0.0,
                500.0,
                1000.0,
                1000.0,
                1000.0,
                1000.0,
                1000.0,
                1000.0,
                1000.0,
                1000.0,
                1000.0,
                1000.0,
                1000.0,
                1000.0,
                1000.0,
                875.0,
                750.0,
                625.0,
                500.0,
                375.0,
                250.0,
                125.0,
                0.0,
                0.0,
                0.0,
                0.0,
                500.0,
                1000.0,
                900.0,
                800.0,
                700.0,
                600.0,
                500.0,
                400.0,
                300.0,
                200.0,
                100.0,
                0.0,
                500.0,
                1000.0,
                1000.0,
            ]
            red = [
                0.0,
                0.0,
                0.0,
                0.0,
                500.0,
                1000.0,
                900.0,
                800.0,
                700.0,
                600.0,
                500.0,
                400.0,
                300.0,
                200.0,
                100.0,
                0.0,
                0.0,
                0.0,
                0.0,
                0.0,
                0.0,
                0.0,
                125.0,
                250.0,
                375.0,
                500.0,
                500.0,
                500.0,
                500.0,
                500.0,
                500.0,
                500.0,
                500.0,
                500.0,
                375.0,
                250.0,
                125.0,
                0.0,
                0.0,
                0.0,
                0.0,
                500.0,
                1000.0,
                900.0,
                800.0,
                700.0,
                600.0,
                500.0,
                400.0,
                300.0,
                200.0,
                100.0,
                0.0,
                500.0,
                1000.0,
                1000.0,
            ]
            blue = [
                0.0,
                0.0,
                0.0,
                0.0,
                500.0,
                1000.0,
                900.0,
                800.0,
                700.0,
                600.0,
                500.0,
                400.0,
                300.0,
                200.0,
                100.0,
                0.0,
                0.0,
                0.0,
                0.0,
                0.0,
                0.0,
                0.0,
                125.0,
                250.0,
                375.0,
                500.0,
                625.0,
                750.0,
                875.0,
                1000.0,
                875.0,
                750.0,
                625.0,
                500.0,
                375.0,
                250.0,
                125.0,
                0.0,
                0.0,
                0.0,
                0.0,
                500.0,
                1000.0,
                900.0,
                800.0,
                700.0,
                600.0,
                500.0,
                400.0,
                300.0,
                200.0,
                100.0,
                0.0,
                500.0,
                1000.0,
                1000.0,
            ]

            self.ax.plot(
                green, color="green", label=_("Hands") + ": %d\n" % len(green) + _("Profit") + ": %.2f" % green[-1]
            )
            self.ax.plot(blue, color="blue", label=_("Showdown") + ": $%.2f" % (blue[-1]))
            self.ax.plot(red, color="red", label=_("Non-showdown") + ": $%.2f" % (red[-1]))
            self.graphBox.add(self.canvas)
            self.canvas.show()
            self.canvas.draw()
        else:
            self.ax.set_title((_("Profit graph for ring games") + names))

            # Draw plot
            if graphops["showdown"] == "ON":
                self.ax.plot(blue, color="blue", label=_("Showdown") + " (%s): %.2f" % (graphops["dspin"], blue[-1]))
            if graphops["nonshowdown"] == "ON":
                self.ax.plot(red, color="red", label=_("Non-showdown") + " (%s): %.2f" % (graphops["dspin"], red[-1]))
            if graphops["ev"] == "ON":
                self.ax.plot(
                    orange, color="orange", label=_("All-in EV") + " (%s): %.2f" % (graphops["dspin"], orange[-1])
                )
            self.ax.plot(
                green,
                color="green",
                label=_("Hands")
                + ": %d\n" % len(green)
                + _("Profit")
                + ": (%s): %.2f" % (graphops["dspin"], green[-1]),
            )

            # order legend, greenline on top
            handles, labels = self.ax.get_legend_handles_labels()
            handles = handles[-1:] + handles[:-1]
            labels = labels[-1:] + labels[:-1]

            legend = self.ax.legend(
                handles, labels, loc="upper left", fancybox=True, shadow=True, prop=FontProperties(size="smaller")
            )
            legend.draggable(True)

            self.graphBox.add(self.canvas)
            self.canvas.show()
            self.canvas.draw()
            # self.exportButton.set_sensitive(True)

    # end of def showClicked

    def getRingProfitGraph(self, names, sites, limits, games, currencies, units):
        #        tmp = self.sql.query['getRingProfitAllHandsPlayerIdSite']
        #        print "DEBUG: getRingProfitGraph"

        if units == "$":
            tmp = self.sql.query["getRingProfitAllHandsPlayerIdSiteInDollars"]
        elif units == "BB":
            tmp = self.sql.query["getRingProfitAllHandsPlayerIdSiteInBB"]

        start_date, end_date = self.filters.getDates()

        # Buggered if I can find a way to do this 'nicely' take a list of integers and longs
        # and turn it into a tuple readale by sql.
        # [5L] into (5) not (5,) and [5L, 2829L] into (5, 2829)
        nametest = str(tuple(names))
        sitetest = str(tuple(sites))
        # nametest = nametest.replace("L", "")

        q = []
        for m in self.filters.display.items():
            if m[0] == "Games" and m[1]:
                for n in games:
                    if games[n]:
                        q.append(n)
                if len(q) > 0:
                    gametest = str(tuple(q))
                    gametest = gametest.replace("L", "")
                    gametest = gametest.replace(",)", ")")
                    gametest = gametest.replace("u'", "'")
                    gametest = "and gt.category in %s" % gametest
                else:
                    gametest = "and gt.category IS NULL"
        tmp = tmp.replace("<game_test>", gametest)

        limittest = self.filters.get_limits_where_clause(limits)

        q = []
        for n in currencies:
            if currencies[n]:
                q.append(n)
        currencytest = str(tuple(q))
        currencytest = currencytest.replace(",)", ")")
        currencytest = currencytest.replace("u'", "'")
        currencytest = "AND gt.currency in %s" % currencytest

        if type == "ring":
            limittest = limittest + " and gt.type = 'ring' "
        elif type == "tour":
            limittest = limittest + " and gt.type = 'tour' "

        # Must be a nicer way to deal with tuples of size 1 ie. (2,) - which makes sql barf
        tmp = tmp.replace("<player_test>", nametest)
        tmp = tmp.replace("<site_test>", sitetest)
        tmp = tmp.replace("<startdate_test>", start_date)
        tmp = tmp.replace("<enddate_test>", end_date)
        tmp = tmp.replace("<limit_test>", limittest)
        tmp = tmp.replace("<currency_test>", currencytest)
        tmp = tmp.replace(",)", ")")

        # print "DEBUG: sql query:"
        # print tmp
        self.db.cursor.execute(tmp)
        # returns (HandId,Winnings,Costs,Profit)
        winnings = self.db.cursor.fetchall()
        self.db.rollback()

        if len(winnings) == 0:
            return (None, None, None)

        green = map(lambda x: float(x[1]), winnings)
        blue = map(lambda x: float(x[1]) if x[2] == True else 0.0, winnings)
        red = map(lambda x: float(x[1]) if x[2] == False else 0.0, winnings)
        orange = map(lambda x: float(x[3]), winnings)
        greenline = cumsum(green)
        blueline = cumsum(blue)
        redline = cumsum(red)
        orangeline = cumsum(orange)
        return (greenline / 100, blueline / 100, redline / 100, orangeline / 100)
        # end of def getRingProfitGraph

    def exportGraph(self, widget, data):
        if self.fig is None:
            return  # Might want to disable export button until something has been generated.

        png_filter = gtk.FileFilter()
        png_filter.add_pattern("*.png")
        dia_chooser = gtk.FileChooserDialog(
            title=_("Please choose the directory you wish to export to:"),
            action=gtk.FILE_CHOOSER_ACTION_SAVE,
            buttons=(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, gtk.STOCK_OK, gtk.RESPONSE_OK),
        )
        dia_chooser.set_filter(png_filter)
        dia_chooser.set_destroy_with_parent(True)
        dia_chooser.set_transient_for(self.parent)
        if self.exportFile is not None:
            dia_chooser.set_filename(self.exportFile)  # use previously chosen export path as default
        else:
            dia_chooser.set_current_name("fpdbgraph.png")

        response = dia_chooser.run()

        if response <> gtk.RESPONSE_OK:
            print _("Closed, no graph exported")
            dia_chooser.destroy()
            return

        self.exportFile = dia_chooser.get_filename()
        dia_chooser.destroy()

        self.fig.savefig(self.exportFile, format="png")

        # Display info box to confirm graph created.
        diainfo = gtk.MessageDialog(
            parent=self.parent,
            flags=gtk.DIALOG_DESTROY_WITH_PARENT,
            type=gtk.MESSAGE_INFO,
            buttons=gtk.BUTTONS_OK,
            message_format=_("Graph created"),
        )
        diainfo.format_secondary_text(self.exportFile)
        diainfo.run()
        diainfo.destroy()
Exemplo n.º 9
0
class DataManager(gtk.Window):
    numRows, numCols = 20, 10

    data = random((numRows, numCols))

    def __init__(self):
        gtk.Window.__init__(self)
        self.set_default_size(600, 600)
        self.connect('destroy', lambda win: gtk.main_quit())

        self.set_title('GtkListStore demo')
        self.set_border_width(8)

        vbox = gtk.VBox(False, 8)
        self.add(vbox)

        label = gtk.Label('Double click a row to plot the data')

        vbox.pack_start(label, False, False)

        sw = gtk.ScrolledWindow()
        sw.set_shadow_type(gtk.SHADOW_ETCHED_IN)
        sw.set_policy(gtk.POLICY_NEVER, gtk.POLICY_AUTOMATIC)
        vbox.pack_start(sw, True, True)

        model = self.create_model()

        self.treeview = gtk.TreeView(model)
        self.treeview.set_rules_hint(True)

        # matplotlib stuff
        fig = Figure(figsize=(6, 4))

        self.canvas = FigureCanvas(fig)  # a gtk.DrawingArea
        vbox.pack_start(self.canvas, True, True)
        ax = fig.add_subplot(111)
        self.line, = ax.plot(self.data[0, :], 'go')  # plot the first row

        self.treeview.connect('row-activated', self.plot_row)
        sw.add(self.treeview)

        self.add_columns()

        self.add_events(gdk.BUTTON_PRESS_MASK | gdk.KEY_PRESS_MASK
                        | gdk.KEY_RELEASE_MASK)

    def plot_row(self, treeview, path, view_column):
        ind, = path  # get the index into data
        points = self.data[ind, :]
        self.line.set_ydata(points)
        self.canvas.draw()

    def add_columns(self):
        for i in range(self.numCols):
            column = gtk.TreeViewColumn('%d' % i,
                                        gtk.CellRendererText(),
                                        text=i)
            self.treeview.append_column(column)

    def create_model(self):
        types = [float] * self.numCols
        store = gtk.ListStore(*types)

        for row in self.data:
            store.append(row)
        return store
Exemplo n.º 10
0
class GuiTourneyGraphViewer:
    def __init__(self, querylist, config, parent, debug=True):
        """Constructor for GraphViewer"""
        self.sql = querylist
        self.conf = config
        self.debug = debug
        self.parent = parent
        #print "start of GraphViewer constructor"
        self.db = Database.Database(self.conf, sql=self.sql)

        filters_display = {
            "Heroes": True,
            "Sites": True,
            "Games": False,
            "Currencies": True,
            "Limits": False,
            "LimitSep": False,
            "LimitType": False,
            "Type": False,
            "UseType": 'tour',
            "Seats": False,
            "SeatSep": False,
            "Dates": True,
            "GraphOpsTour": True,
            "Groups": False,
            "Button1": True,
            "Button2": True
        }

        self.filters = Filters.Filters(self.db,
                                       self.conf,
                                       self.sql,
                                       display=filters_display)
        self.filters.registerButton1Name(_("Refresh _Graph"))
        self.filters.registerButton1Callback(self.generateGraph)
        self.filters.registerButton2Name(_("_Export to File"))
        self.filters.registerButton2Callback(self.exportGraph)

        self.mainHBox = gtk.HBox(False, 0)
        self.mainHBox.show()

        self.leftPanelBox = self.filters.get_vbox()

        self.hpane = gtk.HPaned()
        self.hpane.pack1(self.leftPanelBox)
        self.mainHBox.add(self.hpane)
        # hierarchy:  self.mainHBox / self.hpane / self.graphBox / self.canvas / self.fig / self.ax

        self.graphBox = gtk.VBox(False, 0)
        self.graphBox.show()
        self.hpane.pack2(self.graphBox)
        self.hpane.show()

        self.fig = None
        #self.exportButton.set_sensitive(False)
        self.canvas = None

        self.db.rollback()

        #update the graph at entry (simulate a "Refresh Graph" click)
        gobject.GObject.emit(self.filters.Button1, "clicked")

    def get_vbox(self):
        """returns the vbox of this thread"""
        return self.mainHBox

    #end def get_vbox

    def clearGraphData(self):
        try:
            if self.canvas:
                self.graphBox.remove(self.canvas)
        except:
            pass

        if self.fig != None:
            self.fig.clear()
        self.fig = Figure(figsize=(5, 4), dpi=100)
        if self.canvas is not None:
            self.canvas.destroy()

        self.canvas = FigureCanvas(self.fig)  # a gtk.DrawingArea

    def generateGraph(self, widget, data):
        self.clearGraphData()

        sitenos = []
        playerids = []

        sites = self.filters.getSites()
        heroes = self.filters.getHeroes()
        siteids = self.filters.getSiteIds()
        currencies = self.filters.getCurrencies()

        # Which sites are selected?
        for site in sites:
            if sites[site] == True:
                sitenos.append(siteids[site])
                _hname = Charset.to_utf8(heroes[site])
                result = self.db.get_player_id(self.conf, site, _hname)
                if result is not None:
                    playerids.append(int(result))

        if not sitenos:
            #Should probably pop up here.
            print _("No sites selected - defaulting to PokerStars")
            self.db.rollback()
            return

        if not playerids:
            print _("No player ids found")
            self.db.rollback()
            return

        #Set graph properties
        self.ax = self.fig.add_subplot(111)

        #Get graph data from DB
        starttime = time()
        (green, datesXAbs) = self.getData(playerids, sitenos, currencies)
        print _("Graph generated in: %s") % (time() - starttime)

        currencyLabel = ','.join(['%s' % key for key in currencies.keys()])

        #Set axis labels and grid overlay properites
        self.ax.set_ylabel(currencyLabel, fontsize=12)
        self.ax.grid(color='g', linestyle=':', linewidth=0.2)
        if green == None or green == []:
            self.ax.set_title(_("No Data for Player(s) Found"))
            green = ([
                0., 0., 0., 0., 500., 1000., 900., 800., 700., 600., 500.,
                400., 300., 200., 100., 0., 500., 1000., 1000., 1000., 1000.,
                1000., 1000., 1000., 1000., 1000., 1000., 1000., 1000., 1000.,
                875., 750., 625., 500., 375., 250., 125., 0., 0., 0., 0., 500.,
                1000., 900., 800., 700., 600., 500., 400., 300., 200., 100.,
                0., 500., 1000., 1000.
            ])
            red = ([
                0., 0., 0., 0., 500., 1000., 900., 800., 700., 600., 500.,
                400., 300., 200., 100., 0., 0., 0., 0., 0., 0., 0., 125., 250.,
                375., 500., 500., 500., 500., 500., 500., 500., 500., 500.,
                375., 250., 125., 0., 0., 0., 0., 500., 1000., 900., 800.,
                700., 600., 500., 400., 300., 200., 100., 0., 500., 1000.,
                1000.
            ])
            blue = ([
                0., 0., 0., 0., 500., 1000., 900., 800., 700., 600., 500.,
                400., 300., 200., 100., 0., 0., 0., 0., 0., 0., 0., 125., 250.,
                375., 500., 625., 750., 875., 1000., 875., 750., 625., 500.,
                375., 250., 125., 0., 0., 0., 0., 500., 1000., 900., 800.,
                700., 600., 500., 400., 300., 200., 100., 0., 500., 1000.,
                1000.
            ])

            self.ax.plot(green,
                         color='green',
                         label=_('Tournaments') + ': %d\n' % len(green) +
                         _('Profit') + '(' + currencyLabel +
                         '): %.2f' % green[-1])
            self.graphBox.add(self.canvas)
            self.canvas.show()
            self.canvas.draw()

            #TODO: Do something useful like alert user
        else:
            self.ax.set_title(_("Tournament Results"))
            useDates = True

            #nothing to draw
            if (len(green) == 0):
                return
            #Get the dates of tourneys
            #if first tourney has no date, get the most ancient date and assume it's his one
            if datesXAbs[0] is None:
                i = 1
                while i < len(datesXAbs) and type(datesXAbs[i]) is None:
                    i = i + 1
                if i == len(datesXAbs):
                    print "Wow wow wow : no dates in your whole tourneys"
                    useDates = False
                else:
                    datesXAbs[0] = datesXAbs[i]

            #now convert date to dateTime format
            if useDates:
                for i in range(0, len(datesXAbs)):
                    if datesXAbs[i] is None:
                        datesXAbs[i] = datesXAbs[i - 1]
                    else:
                        datesXAbs[i] = datetime.datetime.strptime(
                            datesXAbs[i], "%Y-%m-%d %H:%M:%S")

                    datesXAbs[i] = datesXAbs[i].strftime('%d/%m')

            mycolor = 'red'
            if green[0] > 0:
                mycolor = 'green'

            self.ax.plot([0, 1], [0, green[0]],
                         color=mycolor,
                         label=_('Tournaments') + ': %d\n' % len(green) +
                         _('Profit') + '(' + currencyLabel +
                         '): %.2f' % green[-1])
            for i in range(1, len(green)):
                final = green[i] - green[i - 1]
                mycolor = 'red'
                if (green[i] > 0):
                    mycolor = 'green'

                self.ax.plot([i, i + 1], [green[i - 1], green[i]],
                             color=mycolor)
                if (i % (len(green) / 5) == 0):
                    gain = ""
                    if (green[i] == 0):
                        gain = "="
                    else:
                        if (green[i] > 0):
                            gain = "+"
                        gain += str(green[i])

                    self.ax.annotate(gain,
                                     xy=(i, 0),
                                     color=mycolor,
                                     xycoords=('data', 'axes fraction'),
                                     xytext=(0, 18),
                                     textcoords='offset points',
                                     va='top',
                                     ha='left')

                    if useDates:
                        self.ax.annotate(datesXAbs[i],
                                         xy=(i, 0),
                                         xycoords=('data', 'axes fraction'),
                                         xytext=(0, -18),
                                         textcoords='offset points',
                                         va='top',
                                         ha='left')

            #~self.ax.axhline(0, color='black', lw=2)

            legend = self.ax.legend(loc='upper left',
                                    fancybox=True,
                                    shadow=True,
                                    prop=FontProperties(size='smaller'))
            legend.draggable(True)

            self.graphBox.add(self.canvas)
            self.canvas.show()
            self.canvas.draw()
            #self.exportButton.set_sensitive(True)

    #end of def showClicked

    def getData(self, names, sites, currencies):
        tmp = self.sql.query['tourneyGraph']
        # print "DEBUG: getData. :"
        start_date, end_date = self.filters.getDates()

        #Buggered if I can find a way to do this 'nicely' take a list of integers and longs
        # and turn it into a tuple readale by sql.
        # [5L] into (5) not (5,) and [5L, 2829L] into (5, 2829)
        nametest = str(tuple(names))
        sitetest = str(tuple(sites))
        currencytest = str(tuple())

        #Must be a nicer way to deal with tuples of size 1 ie. (2,) - which makes sql barf
        tmp = tmp.replace("<player_test>", nametest)
        tmp = tmp.replace("<site_test>", sitetest)

        currencytest = str(tuple(currencies))
        currencytest = currencytest.replace(",)", ")")
        currencytest = currencytest.replace("u'", "'")
        currencytest = "AND tt.currency in %s" % currencytest
        tmp = tmp.replace("<currency_test>", currencytest)

        tmp = tmp.replace("<startdate_test>", start_date)
        tmp = tmp.replace("<enddate_test>", end_date)
        tmp = tmp.replace(",)", ")")

        # print "DEBUG: sql query:", tmp

        self.db.cursor.execute(tmp)
        #returns (HandId,Winnings,Costs,Profit)
        winnings = self.db.cursor.fetchall()
        self.db.rollback()

        if len(winnings) == 0:
            return (None, None)

        green = map(lambda x: float(x[1]), winnings)

        datesXAbs = map(lambda x: x[8], winnings)
        #blue  = map(lambda x: float(x[1]) if x[2] == True  else 0.0, winnings)
        #red   = map(lambda x: float(x[1]) if x[2] == False else 0.0, winnings)
        greenline = cumsum(green)
        #blueline  = cumsum(blue)
        #redline   = cumsum(red)

        return (greenline / 100, datesXAbs)

    def exportGraph(self, widget, data):
        if self.fig is None:
            return  # Might want to disable export button until something has been generated.

        dia_chooser = gtk.FileChooserDialog(
            title=_("Please choose the directory you wish to export to:"),
            action=gtk.FILE_CHOOSER_ACTION_SELECT_FOLDER,
            buttons=(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, gtk.STOCK_OK,
                     gtk.RESPONSE_OK))
        dia_chooser.set_destroy_with_parent(True)
        dia_chooser.set_transient_for(self.parent)
        try:
            dia_chooser.set_filename(
                self.exportFile
            )  # use previously chosen export path as default
        except:
            pass

        response = dia_chooser.run()

        if response <> gtk.RESPONSE_OK:
            print _('Closed, no graph exported')
            dia_chooser.destroy()
            return

        # generate a unique filename for export
        now = datetime.now()
        now_formatted = now.strftime("%Y%m%d%H%M%S")
        self.exportFile = dia_chooser.get_filename(
        ) + "/fpdb" + now_formatted + ".png"
        dia_chooser.destroy()

        #print "DEBUG: self.exportFile = %s" %(self.exportFile)
        self.fig.savefig(self.exportFile, format="png")

        #display info box to confirm graph created
        diainfo = gtk.MessageDialog(parent=self.parent,
                                    flags=gtk.DIALOG_DESTROY_WITH_PARENT,
                                    type=gtk.MESSAGE_INFO,
                                    buttons=gtk.BUTTONS_OK,
                                    message_format=_("Graph created"))
        diainfo.format_secondary_text(self.exportFile)
        diainfo.run()
        diainfo.destroy()
Exemplo n.º 11
0
class Backend( backend.Plotter ):

    def init(self):
        # line_cache: key = id(Curve), value=mpl line object
        self.line_cache = dict()
        
        self.layer_to_axes = dict()
        self.axes_to_layer = dict()
        self.layers_cache = list() # copy of self.plot.layers
        
    def connect(self):
        logger.debug("Opening matplotlib session.")        

        self.figure = Figure(dpi=100, facecolor="white")  # figsize=(5,4), dpi=100)        
        self.canvas = FigureCanvas(self.figure)
        self.canvas.show()

        self.line_cache.clear()
        self.layer_to_axes.clear()
        self.axes_to_layer.clear()

        backend.Plotter.connect(self)
        logger.debug("Init finished")


    def disconnect(self):
        logger.debug("Closing matplotlib session.")

        if not self.canvas is None:
            self.canvas.destroy()
            self.canvas = None
        if not self.figure is None:
            self.figure = None
        
        backend.Plotter.disconnect(self)


    #----------------------------------------------------------------------

    def arrange(self, rows=1, cols=1):

        layers = self.plot.layers
        n = len(layers)

        if n > (rows*cols):
            rows = int((rows*cols) / n) + 1
            cols = rows * n
            #raise ValueError("Not enough rows and cols for all layers!")

        self.figure.clear()
        self.figure.axes = []
        
        self.layer_to_axes.clear()
        self.axes_to_layer.clear()
        self.layers_cache = list()
        j = 1
        for layer in layers:
            print "Setting up layer", layer
            axes = self.figure.add_subplot("%d%d%d" % (rows,cols,j))
            self.layer_to_axes[layer] = axes
            self.axes_to_layer[axes] = layer
            self.layers_cache.append(layer)
            j += 1
        

        
    def draw_layer(self, layer, group_info):

        ax = self.layer_to_axes[layer]

        print "DRAWING AXES ", ax
        ax.lines = []

        line_cache = []
        line_count = 0
        last_cx = -1

        # Default values come in two flavors:
        # group-wise and single default values        
        group_colors = uwrap.get(layer, 'group_colors')
        group_styles = uwrap.get(layer, 'group_styles')
        group_markers = uwrap.get(layer, 'group_markers')

        #default_color = 'r'
        default_color = None
        default_style = 'solid'
        default_marker = 'None'
        

        #:layer.visible
        if uwrap.get(layer, 'visible') is False:
            return

        #:layer.title
        title = uwrap.get(layer, 'title', None)
        if title is not None:
            ax.set_title(title)        

        #:layer.grid
        grid = uwrap.get(layer, 'grid')
        ax.grid(grid)                         

        #:layer.lines
        for line in layer.lines:
            data_to_plot = []
            
            #:line.visible
            if uwrap.get(line, 'visible') is False:
                if line in ax.lines:
                    ax.lines.remove(line)
                continue

            #:line.source            
            if line.source is None:
                logger.warn("No Dataset specified for Line!")
                continue
            else:
                ds = line.source
                
            if ds.is_empty() is True:
                logger.warn("No data for Line!")
                continue

            table = ds.get_data()
            if not isinstance(table, Table):
                raise TypeError("Matplotlib Backend currently only supports data of type Table, while this is of %s"
                                % type(table))

            #:line.cx
            if line.cx is None or line.cy is None:
                logger.error("No x or y source given for Line. Line skipped.")
                continue
            else:
                cx, cy = line.cx, line.cy
            
            try:
                xdata = table[cx]
            except IndexError:
                logger.error("X-Index out of range (%s). Line skipped." % cx)
                continue


            #:line.cy
            try:
                ydata = table[cy]
            except IndexError:
                logger.error("Y-Index out of range (%s). Line skipped." % cy)
                continue


            #:line.style
            global linestyle_mappings
            default = default_style or group_styles[line_count % len(group_styles)]
            style = uwrap.get(line, 'style', default)
            style = linestyle_mappings[style]

            #:line.marker
            global linemarker_mappings
            default = default_marker or group_markers[line_count % len(group_markers)]
            marker = uwrap.get(line, 'marker', default)
            marker = linemarker_mappings[marker]

            #:line.width
            width = uwrap.get(line, 'width')
            
            #:line.color
            default = default_color or group_colors[line_count % len(group_colors)]
            color = uwrap.get(line, 'color', default)


            #--- PLOT LINE ---
            l, = ax.plot( xdata, ydata,
                          linewidth=width,
                          linestyle=style,
                          marker=marker,
                          color=color)
            line_cache.append(l)
            
            # TODO: if we set the label afterwards, don't we then have a redraw?
            #:line.label
            label = line.label
            if label is None:
                column = table.column(cy)
                label = column.label or column.key or uwrap.get(line, 'label')
            l.set_label(label)

            line_count += 1

#         #
#         # additional lines
#         #
#         p = len(xdata)
#         if p > 2: p = p/2
#         atpoint = xdata[max(p-1,0)]
#         print "Printing vertical line at ", atpoint
#         ax.axvline(atpoint)
        
        #:layer.legend
        legend = uwrap.get(layer, 'legend')
        if legend is not None and line_count > 0:
            visible = uwrap.get(legend, 'visible')
            if visible is True:
                #:legend.label TODO
                label = uwrap.get(legend, 'visible')
                if label is not None:
                    pass
                                
                #:legend.border TODO
                border = uwrap.get(legend, 'border')
                
                #:legend.position TODO
                position = uwrap.get(legend, 'position', 'best')
                if position == 'at position':
                    position = (uwrap.get(legend, 'x'), uwrap.get(legend, 'y'))

                # create legend entries from line labels
                labels = [l.get_label() for l in line_cache]
                ax.legend(line_cache, labels, loc=position)                
            else:
                ax.legend_ = None
        else:
            ax.legend_ = None

        #:layer.axes
        for (key, axis) in layer.axes.iteritems():
            #:axis.label
            #:axis.scale
            #:axis.start
            #:axis.end
            label = uwrap.get(axis, 'label')            
            scale = uwrap.get(axis, 'scale')
            start = uwrap.get(axis, 'start')
            end = uwrap.get(axis, 'end')
            print "START = %s, END = %s" % (str(start), str(end))
            if key == 'x':
                set_label = ax.set_xlabel
                set_scale = ax.set_xscale
                set_start = (lambda l: ax.set_xlim(xmin=l))
                set_end = (lambda l: ax.set_xlim(xmax=l))
            elif key == 'y':
                set_label = ax.set_ylabel
                set_scale = ax.set_yscale
                set_start = (lambda l: ax.set_ylim(ymin=l))
                set_end = (lambda l: ax.set_ylim(ymax=l))
            else:
                raise RuntimeError("Invalid axis key '%s'" % key)

            if label is not None: set_label(label)
            if scale is not None: set_scale(scale)
            if start is not None: set_start(start)
            if end is not None: set_end(end)  




    def draw(self):
        logger.debug("Matplotlib: draw()")
        
        self.check_connection()
               
        # plot all curves together in one plot
        legend_list = [] # for legend later on
        curve_count = 0
       
        #
        if self.plot.layers != self.layers_cache:
            self.arrange()

        for layer in self.plot.layers:
            group_info = {}
            self.draw_layer(layer, group_info)
       
        self.canvas.draw()
Exemplo n.º 12
0
class RAMSTKPlot(object):
    """
    The RAMSTKPlot class.

    This module contains RAMSTK plot class.  This class is derived from the
    applicable pyGTK widgets and matplotlib plots, but are provided with RAMSTK
    specific property values and methods.  This ensures a consistent look and
    feel to widgets in the RAMSTK application.
    """
    def __init__(self):
        """Initialize an instance of the RAMSTKPlot."""
        # Initialize private dictionary attributes.

        # Initialize private list attributes.
        self._lst_max = []
        self._lst_min = [0.0]

        # Initialize private scalar attributes.

        # Initialize public dictionary attributes.

        # Initialize public list attributes.

        # Initialize public scalar attributes.
        self.figure = Figure()
        self.plot = FigureCanvas(self.figure)
        self.axis = self.figure.add_subplot(111)

    def _do_make_date_plot(self, x_values, y_values, marker='g-'):
        """
        Make a date plot.

        :param list x_values: the list of x-values (dates) for the plot.
        :param list y_values: the list of y-values for the plot.
        :keyword str marker: the type and color of marker to use for the plot.
                             Default is a solid green line.
        """
        _line, = self.axis.plot_date(x_values,
                                     y_values,
                                     marker,
                                     xdate=True,
                                     linewidth=2)
        self._lst_min.append(min(y_values))
        self._lst_max.append(max(y_values))

        return _line

    def _do_make_histogram(self, x_values, y_values, marker='g'):
        """
        Make a histogram.

        :param list x_values: the list of x-values for the plot.
        :param list y_values: the list of bin edges for the plot.
        :keyword str marker: the color of bars to use for the histogram.
                             Default is green.
        """
        self.axis.grid(False, which='both')
        _values, _edges, __ = self.axis.hist(x_values,
                                             bins=y_values,
                                             color=marker)
        self._lst_min.append(min(_values))
        self._lst_max.append(max(_values) + 1)

        return _values, _edges

    def _do_make_scatter_plot(self, x_values, y_values, marker='go'):
        """
        Make a scatter plot.

        :param list x_values: the list of x-values for the plot.
        :param list y_values: the list of y-values for the plot.
        :keyword str marker: the type and color of marker to use for the plot.
                             Default is open green circles.
        """
        _line, = self.axis.plot(x_values, y_values, marker, linewidth=2)
        _line.set_ydata(y_values)
        self._lst_min.append(min(y_values))
        self._lst_max.append(max(y_values))

        return _line

    def _do_make_step_plot(self, x_values, y_values, marker='g-'):
        """
        Make a step plot.

        :param list x_values: the list of x-values for the plot.
        :param list y_values: the list of y-values for the plot.
        :keyword str marker: the type and color of marker to use for the plot.
                             Default is a solid green line.
        """
        _line, = self.axis.step(x_values, y_values, marker, where='mid')
        _line.set_ydata(y_values)
        self._lst_min.append(min(y_values))
        self._lst_max.append(max(y_values))

        return _line

    def do_load_plot(self,
                     x_values,
                     y_values=None,
                     plot_type='scatter',
                     marker='g-'):
        """
        Load the RAMSTKPlot.

        :param list x_values: list of the x-values to plot.
        :keyword list y_values: list of the y-values to plot or list of bin
                                edges if plotting a histogram.
        :keyword str plot_type: list of the type of line to plot. Options are:
                                    * 'date'
                                    * 'histogram'
                                    * 'scatter' (default)
                                    * 'step'
        :keyword str marker: the marker to use on the plot. Defaults is 'g-' or
                             a solid green line.  See matplotlib documentation
                             for other options.
        :return: False if successful or True if an error is encountered.
        :rtype: bool
        """
        if y_values is not None:
            if plot_type == 'step':
                self._do_make_step_plot(x_values, y_values, marker)
            elif plot_type == 'scatter':
                self._do_make_scatter_plot(x_values, y_values, marker)
            elif plot_type == 'histogram':
                _values, _edges = self._do_make_histogram(
                    x_values, y_values, marker)
            elif plot_type == 'date':
                self._do_make_date_plot(x_values, y_values, marker)

        # Get the minimum and maximum y-values to set the axis bounds.  If the
        # maximum value is infinity, use the next largest value and so forth.
        _min = min(self._lst_min)
        _max = self._lst_max[0]
        for i in range(1, len(self._lst_max)):
            if _max < self._lst_max[i] and self._lst_max[i] != float('inf'):
                _max = self._lst_max[i]

        self.axis.set_ybound(_min, 1.05 * _max)

        self.plot.draw()

        return False

    def do_add_line(self, x_values, y_values=None, color='k', marker='^'):
        """
        Load the RAMSTKPlot.

        :param list x_values: list of the x-values to plot.
        :keyword list y_values: list of the y-values to plot or list of bin
                                edges if plotting a histogram.
        :keyword str color: the color of the line to add to the plot.  Black
                            is the default.  See matplotlib documentation for
                            options.
        :keyword str marker: the marker to use on the plot. Defaults is '^' or
                             an upward pointing triangle.  See matplotlib
                             documentation for other options.
        :return: False if successful or True if an error is encountered.
        :rtype: bool
        """
        _line = Line2D(x_values,
                       y_values,
                       lw=0.0,
                       color=color,
                       marker=marker,
                       markersize=10)
        self.axis.add_line(_line)
        self.figure.canvas.draw()

        return False

    def do_close_plot(self, __window, __event, parent):
        """
        Return the plot to the Work Book page it is part of.

        :param __window: the gtk.Window() that is being destroyed.
        :type __window: :class:`gtk.Window`
        :param __event: the gtk.gdk.Event() that called this method.
        :type __event: :class:`gtk.gdk.Event`
        :param parent: the original parent gtk.Widget() for the plot.
        :type parent: :class:`gtk.Widget`
        :return: False if successful or True if an error is encountered.
        :rtype: bool
        """
        self.plot.reparent(parent)

        return False

    def do_expand_plot(self, event):
        """
        Display a plot in it's own window.

        :param event: the matplotlib.MouseEvent() that called this method.
        :type event: :class:`matplotlib.MouseEvent`
        :return: False if successful or True if an error is encountered.
        :rtype: bool
        """
        self.plot = event.canvas
        _parent = self.plot.get_parent()

        if event.button == 3:  # Right click.
            _window = gtk.Window()
            _window.set_skip_pager_hint(True)
            _window.set_skip_taskbar_hint(True)
            _window.set_default_size(800, 400)
            _window.set_border_width(5)
            _window.set_position(gtk.WIN_POS_NONE)
            _window.set_title(_(u"RAMSTK Plot"))

            _window.connect('delete_event', self.close_plot, _parent)

            self.plot.reparent(_window)

            _window.show_all()

        return False

    def do_make_labels(self, label, x_pos, y_pos, **kwargs):
        r"""
        Make the abscissa or ordinate label.

        :param str label: the text to display as the abscissa or ordinate
                          label.
        :param float x_pos: the position along the abscissa to place the label.
        :param float y_pos: the position along the ordinate to place the label.
        :param \**kwargs: See below

        :Keyword Arguments:
            * *set_x* (bool) -- whether to set the abscissa (default) or
                                ordinate label.
            * *fontsize* (int) -- the size of the font to use for the axis
                                  label.
            * *fontweight* (str) -- the weight of the font to use for the axis
                                    label.
        :return: matplotlib text instance representing the label.
        :rtype: :class:`matplotlib.text.Text`
        """
        try:
            _set_x = kwargs['set_x']
        except KeyError:
            _set_x = True
        try:
            _fontsize = kwargs['fontsize']
        except KeyError:
            _fonsize = 14
        try:
            _fontweight = kwargs['fontweight']
        except KeyError:
            _fontweight = 'bold'

        _label = None

        if _set_x:
            _label = self.axis.set_xlabel(
                label, {
                    'fontsize': _fontsize,
                    'fontweight': _fontweight,
                    'verticalalignment': 'center',
                    'horizontalalignment': 'center',
                    'x': x_pos,
                    'y': y_pos
                })
        else:
            _label = self.axis.set_ylabel(
                label, {
                    'fontsize': _fontsize,
                    'fontweight': _fontweight,
                    'verticalalignment': 'center',
                    'horizontalalignment': 'center',
                    'rotation': 'vertical'
                })

        return _label

    # pylint: disable=too-many-arguments
    def do_make_legend(self, text, **kwargs):
        r"""
        Make a legend on the RAMSTKPlot.

        :param tuple text: the text to display in the legend.
        :param \**kwargs: See below

        :Keyword Arguments:
            * *fontsize* (str) -- the size of the font to use for the legend.
                                  Options are:
                                   - xx-small
                                   - x-small
                                   - small (default)
                                   - medium
                                   - large
                                   - x-large
                                   - xx-large
            * *frameon* (bool) -- whether or not there is a frame around the
                                  legend.
            * *location* (str) -- the location of the legend on the plot.
                                  Options are:
                                   - best
                                   - upper right (default)
                                   - upper left
                                   - lower left
                                   - lower right
                                   - right
                                   - center left
                                   - center right
                                   - lower center
                                   - upper center
                                   - center
            * *ncol* (int) -- the number columns in the legend.  Default is 1.
            * *shadow* (bool) -- whether or not to display a shadow behind the
                                 legend block.  Default is True.
            * *title* (str) -- the title of the legend.  Default is an empty
                               string.
            * *lwd* (float) -- the linewidth of the box around the legend.
        :return: None
        :rtype: None
        """
        try:
            _fontsize = kwargs['fontsize']
        except KeyError:
            _fontsize = 'small'
        try:
            _frameon = kwargs['frameon']
        except KeyError:
            _frameon = False
        try:
            _location = kwargs['location']
        except KeyError:
            _location = 'upper right'
        try:
            _ncol = kwargs['ncol']
        except KeyError:
            _ncol = 1
        try:
            _shadow = kwargs['shadow']
        except KeyError:
            _shadow = True
        try:
            _title = kwargs['title']
        except KeyError:
            _title = ""
        try:
            _lwd = kwargs['lwd']
        except KeyError:
            _lwd = 0.5

        _legend = self.axis.legend(text,
                                   frameon=_frameon,
                                   loc=_location,
                                   ncol=_ncol,
                                   shadow=_shadow,
                                   title=_title)

        for _text in _legend.get_texts():
            _text.set_fontsize(_fontsize)
        for _line in _legend.get_lines():
            _line.set_linewidth(_lwd)

        return None

    def do_make_title(self, title, fontsize=16, fontweight='bold'):
        """
        Make the plot title.

        :param str title: the text to display as the title.
        :keyword int fontsize: the size of the font to use for the title.
        :keyword str fontweight: the weight of the font to use for the title.
        :return: matplotlib text instance representing the title.
        :rtype: :class:`matplotlib.text.Text`
        """
        return self.axis.set_title(
            title, {
                'fontsize': fontsize,
                'fontweight': fontweight,
                'verticalalignment': 'baseline',
                'horizontalalignment': 'center'
            })
Exemplo n.º 13
0
class plot:
    """Note, currently, this cant be used interactively - because Gtk has to be running...."""
    def __init__(self, window=None, startGtk=0, dims=2):
        self.dims = dims
        self.data = numpy.zeros((10, 10), numpy.float32)
        self.data[:] = numpy.arange(10).astype(numpy.float32)
        self.deactivatefn = None  #this can be set by the caller, eg to turn off buttons...

        self.win = gtk.Window()
        self.win.connect("destroy", self.quit)
        self.win.set_default_size(400, 400)
        self.win.set_title("Window")
        self.cmap = colour.gray
        self.vbox = gtk.VBox()
        self.interpolation = "nearest"  #see pylab documantation for others.
        self.win.add(self.vbox)
        self.vbox.connect("button_press_event", self.buttonPress)
        self.fig = Figure(figsize=(5, 4), dpi=50)
        self.ax = self.fig.add_subplot(111)
        self.fig.subplots_adjust(right=0.99, left=0.08, bottom=0.05, top=0.99)
        #self.ax.imshow(self.data,interpolation=self.interpolation)
        #print type(fig),dir(ax),dir(fig)
        self.canvas = FigureCanvas(self.fig)  # a gtk.DrawingArea
        self.vbox.pack_start(self.canvas)
        self.toolbar = NavigationToolbar(self.canvas, self.win)
        self.vbox.pack_start(self.toolbar, False, False)
        self.mytoolbar = myToolbar(plotfn=self.plot)
        #self.toolbar.save_figure=self.mytoolbar.mysave
        self.vbox.pack_start(self.mytoolbar.toolbar, False, False)
        self.win.show_all()
        self.toolbar.hide()
        self.mytoolbar.toolbar.hide()
        self.active = 1  #will be set to zero once quit or window closed.
        self.toolbarVisible = 0
        self.startedGtk = 0
        self.update = 0
        #self.plot()
        if startGtk == 1 and gtk.main_level() == 0:
            self.startedGtk = 1
            thread.start_new_thread(gtk.main, ())

    def quit(self, w=None, data=None):
        if self.deactivatefn != None:
            d = self.deactivatefn
            self.deactivatefn = None
            d()
        self.active = 0
        self.win.hide()
        if self.startedGtk:
            gtk.main_quit()

    def newPalette(self, palette):
        if palette[-3:] == ".gp":
            palette = palette[:-3]
        if palette in colour.datad.keys():
            self.cmap = getattr(colour, palette)
        else:
            print "Palette %s not regocnised" % str(palette)
        #self.plot()
    def newInterpolation(self, interp):
        if interp not in [
                "bicubic", "bilinear", "blackman100", "blackman256",
                "blackman64", "nearest", "sinc144", "sinc64", "spline16",
                "spline36"
        ]:
            print "Interpolation %s not recognised" % str(interp)
        else:
            self.interpolation = interp
        #self.plot()

    def buttonPress(self, w, e, data=None):
        """If the user right clicks, we show or hide the toolbar..."""
        if e.button == 3:
            if self.toolbarVisible:
                self.toolbar.hide()
                self.mytoolbar.toolbar.hide()
                self.toolbarVisible = 0
            else:
                self.toolbar.show()
                self.mytoolbar.toolbar.show()
                self.toolbarVisible = 1

        return True

    def queuePlot(self, axis):
        """puts a request to plot in the idle loop... (gives the rest of the
        gui a chance to update before plotting)
        """
        #print type(axis),self.data.shape
        #if type(axis)!=type(None):
        #    print axis.shape
        if self.update:
            if hasattr(self.ax.xaxis, "callbacks"):
                if hasattr(self.ax.xaxis.callbacks, "signals") and hasattr(
                        self.ax.xaxis.callbacks, "callbacks"):
                    self.ax.xaxis.callbacks.callbacks = dict([
                        (s, dict()) for s in self.ax.xaxis.callbacks.signals
                    ])  #needed to fix a bug!
                    self.ax.yaxis.callbacks.callbacks = dict([
                        (s, dict()) for s in self.ax.yaxis.callbacks.signals
                    ])  #needed to fix a bug!

            self.ax.clear()
            freeze, logscale, data, scale, aspect = self.mytoolbar.prepare(
                self.data, dim=self.dims)
            if len(data.shape) == 1 or self.dims == 1:
                #1D
                if len(data.shape) == 1:
                    if freeze == 0:
                        if type(axis) == type(
                                None) or axis.shape[0] != data.shape[0]:
                            axis = numpy.arange(data.shape[0]) + 1
                        if logscale:
                            try:
                                axis = numpy.log10(axis)
                            except:
                                print "Cannot take log"
                        #self.fig.axis([axis[0],axis[-1],scale[0],scale[1]])
                        #print dir(self.ax)
                        #print dir(self.ax.axis)
                        #print self.ax.get_position()
                        #self.ax.cla()
                        #self.ax.axis([-1,1,-1,1])
                        #self.ax.autoscale_view()
                        try:  #older installations don't have this (e.g. cray)
                            self.ax.set_aspect("auto")
                        except:
                            pass
                        self.ax.plot(axis, data)
                else:  #use first row of data for the x axis...
                    #axis=data[0]
                    #freeze,logscale,data,scale=self.mytoolbar.prepare(self.data,dim=1)
                    if freeze == 0:
                        if type(axis) == type(
                                None) or axis.shape[0] != data.shape[-1]:
                            axis = numpy.arange(data.shape[0]) + 1
                        if logscale:
                            try:
                                axis = numpy.log10(axis)
                            except:
                                print "Cannot take log"
                        #self.fig.axis([axis[0],axis[-1],scale[0],scale[1]])
                        for i in range(data.shape[0]):
                            self.ax.plot(axis, data[i])

            else:  #2D
                if len(data.shape) != 2:  #force to 2d
                    data = numpy.reshape(data, (reduce(
                        lambda x, y: x * y, data.shape[:-1]), data.shape[-1]))
                #freeze,logscale,data,scale=self.mytoolbar.prepare(self.data)
                if freeze == 0:
                    self.ax.imshow(data,
                                   interpolation=self.interpolation,
                                   cmap=self.cmap,
                                   vmin=scale[0],
                                   vmax=scale[1],
                                   origin="lower",
                                   aspect=("auto" if aspect else "equal"))
            if freeze == 0:
                try:
                    self.ax.draw()
                except:
                    pass
                #self.ax.update()
                self.canvas.draw()
                #self.canvas.queue_draw()
        self.update = 0
        return False

    def plot(self, data=None, copy=0, axis=None):
        """Plot new data... axis may be specified if 1d...
        """
        if self.active == 0:
            self.active = 1
            self.win.show()
        #if type(data)==numpy.ndarray:
        #    data=Numeric.array(data)
        if type(data) != type(None):
            if copy:
                self.data = data.copy().astype("d")
            else:
                if data.dtype.char == "d":
                    self.data = data
                else:
                    self.data = data.astype("d")
        else:  #data==None?
            pass
            #if type(self.data)==numpy.ndarray:
            #    self.data=Numeric.array(self.data)
        self.update = 1
        #print "plot"
        #print type(axis)
        #if type(axis)!=type(None):
        #    print axis.shape
        gobject.idle_add(self.queuePlot, axis)
        ##         self.ax.clear()
        ##         if len(self.data.shape)==1 or self.dims==1:
        ##             #1D
        ##             if len(self.data.shape)==1:
        ##                 freeze,logscale,data,scale=self.mytoolbar.prepare(self.data,dim=1)
        ##                 if freeze==0:
        ##                     if type(axis)==type(None) or axis.shape[0]!=data.shape[0]:
        ##                         axis=Numeric.arange(data.shape[0])+1
        ##                     if logscale:
        ##                         try:
        ##                             axis=Numeric.log10(axis)
        ##                         except:
        ##                             print "Cannot take log"
        ##                     #self.fig.axis([axis[0],axis[-1],scale[0],scale[1]])
        ##                     self.ax.plot(axis,data)
        ##             else:#use first row of data for the x axis...
        ##                 #axis=data[0]
        ##                 freeze,logscale,data,scale=self.mytoolbar.prepare(self.data,dim=1)
        ##                 if freeze==0:
        ##                     if type(axis)==type(None) or axis.shape[0]!=data.shape[-1]:
        ##                         axis=Numeric.arange(data.shape[0])+1
        ##                     if logscale:
        ##                         try:
        ##                             axis=Numeric.log10(axis)
        ##                         except:
        ##                             print "Cannot take log"
        ##                     #self.fig.axis([axis[0],axis[-1],scale[0],scale[1]])
        ##                     for i in range(data.shape[0]):
        ##                         self.ax.plot(axis,data[i])

        ##         else:#2D
        ##             if len(self.data.shape)!=2:#force to 2d
        ##                 self.data=Numeric.reshape(self.data,(reduce(lambda x,y:x*y,self.data.shape[:-1]),self.data.shape[-1]))
        ##             freeze,logscale,data,scale=self.mytoolbar.prepare(self.data)
        ##             if freeze==0:
        ##                 self.ax.imshow(data,interpolation=self.interpolation,cmap=self.cmap,vmin=scale[0],vmax=scale[1])
        ##         if freeze==0:
        ##             try:
        ##                 self.ax.draw()
        ##             except:
        ##                 pass
        ##             #self.ax.update()
        ##             self.canvas.draw()
        ##             #self.canvas.queue_draw()
        return True
Exemplo n.º 14
0
class XYDialog:
    def __init__(self, title, parent, syn2d, numX, numY):
        # create buttons
        self.loadButton = gtk.Button(label="Load", stock=gtk.STOCK_OPEN)
        self.saveButton = gtk.Button(label="Save and Use",
                                     stock=gtk.STOCK_SAVE)
        self.useButton = gtk.Button(label="Use")
        self.revertButton = gtk.Button(label="Revert")
        self.clearButton = gtk.Button(label="Clear")
        self.cancelButton = gtk.Button(label="Cancel")

        # create matplotlib figure
        self.figure = Figure()
        self.canvas = FigureCanvas(self.figure)
        self.mp = DataPointChooser(self.figure, self, numX, numY)

        self.syn2d = syn2d
        self.parent = parent

        self.sourcesFile, self.receiversFile = self.syn2d.getDataFiles()
        print "Loading initial data from: " + self.sourcesFile + " , " + self.receiversFile
        sources = self.loadXYFile(self.sourcesFile)
        receivers = self.loadXYFile(self.receiversFile, True)

        # create GTK dialog
        self.dialog = gtk.Dialog(title=title,
                                 parent=parent,
                                 flags=gtk.DIALOG_MODAL
                                 | gtk.DIALOG_DESTROY_WITH_PARENT)
        self.dialog.set_default_size(500, 400)
        self.vBox = self.dialog.vbox

        # setup matplotlib events
        self.canvas.mpl_connect('button_press_event', self.mp.on_click)

        # pack buttons
        self.buttonBox = gtk.HBox(homogeneous=True, spacing=5)
        self.buttonBox.pack_start(self.loadButton, expand=False)
        self.buttonBox.pack_start(self.saveButton, expand=False)
        self.buttonBox.pack_start(self.useButton, expand=False)
        self.buttonBox.pack_start(self.revertButton, expand=False)
        self.buttonBox.pack_start(self.clearButton, expand=False)
        self.buttonBox.pack_end(self.cancelButton, expand=False)

        # connect buttons
        self.use = False
        self.loadButton.connect("clicked", self.loadHandler)
        self.saveButton.connect("clicked", self.saveHandler)
        self.useButton.connect("clicked", self.useHandler)
        self.revertButton.connect("clicked", self.revertHandler)
        self.clearButton.connect("clicked", self.clearHandler)
        self.cancelButton.connect("clicked", self.cancelHandler)

        self.label = gtk.Label(
            "Mouse Buttons: L-Add Station, M-Delete Point, R-Add Source")

        # pack and show dialog
        self.vBox.pack_start(self.canvas, expand=True)
        self.vBox.pack_start(gtk.HSeparator(), expand=False)
        self.vBox.pack_start(self.label, expand=False)
        self.vBox.pack_end(self.buttonBox, expand=False)

        self.mp.setOriginalData(sources, receivers)
        self.mp.reset_data()

        self.dialog.show_all()

    def redraw(self):
        self.canvas.draw()

    def loadHandler(self, widget):
        chooser = gtk.FileChooserDialog(title="Select DIRECTORY Containing 'sources.txt' and 'receivers.txt' Files", \
            parent=self.parent, \
             action=gtk.FILE_CHOOSER_ACTION_SELECT_FOLDER, \
             buttons=(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, \
                gtk.STOCK_OPEN, gtk.RESPONSE_OK))

        response = chooser.run()
        if (response == gtk.RESPONSE_OK):
            dir = chooser.get_filename()
            sourceName = dir + os.sep + "sources.txt"
            if (os.path.exists(sourceName)):
                sources = self.loadXYFile(sourceName)
            else:
                sources = []
            receiverName = dir + os.sep + "receivers.txt"
            if (os.path.exists(receiverName)):
                receivers = self.loadXYFile(receiverName)
            else:
                receivers = []
            self.mp.setOriginalData(sources, receivers)
            self.mp.reset_data()
        chooser.destroy()

    def loadXYFile(self, file, skipDuplicates=False):

        if not os.path.exists(file):
            return []

        x, y = self.syn2d.loadXYFile(file)

        data = []

        for i in range(0, len(x)):
            if skipDuplicates:
                skip = False
                for point in data:
                    if point[0] == x[i] and point[1] == y[i]:
                        skip = True
                        break
                if skip:
                    continue
            data.append((x[i], y[i]))

        return data

    def writeXYFile(self, file, data):
        fp = open(file, "w")
        for point in data:
            fp.write(str(point[0]) + " " + str(point[1]) + "\n")
        fp.close()

    def saveHandler(self, widget):
        chooser = gtk.FileChooserDialog(title="Select DIRECTORY to save 'sources.txt' and 'receivers.txt' Files", \
            parent=self.parent, \
             action=gtk.FILE_CHOOSER_ACTION_SELECT_FOLDER, \
             buttons=(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, \
                gtk.STOCK_OPEN, gtk.RESPONSE_OK))

        response = chooser.run()
        if (response == gtk.RESPONSE_OK):
            dir = chooser.get_filename()
            self.writeDataFiles(dir)
        chooser.destroy()

    def writeDataFiles(self, dir):
        if not dir.endswith(os.sep):
            dir += os.sep
        sourceName = dir + "sources.txt"
        self.writeXYFile(sourceName, self.mp.getSources())
        receiverName = dir + "receivers.txt"
        self.writeXYFile(receiverName, self.mp.getReceivers())
        return (sourceName, receiverName)

    def useHandler(self, widget):
        self.sourcesFile, self.receiversFile = self.writeDataFiles(
            self.syn2d.getWorkingDir())
        self.use = True
        self.exit()

    def clearHandler(self, widget):
        self.mp.setOriginalData([], [])
        self.mp.reset_data()

    def getSourcesFile(self):
        return self.sourcesFile

    def getReceiversFile(self):
        return self.receiversFile

    def wasUseSelected(self):
        print "USE? " + str(self.use)
        return self.use

    def revertHandler(self, widget):
        self.mp.reset_data()

    def cancelHandler(self, widget):
        self.use = False
        self.exit()

    def updateButtons(self, sources, receivers):
        self.useButton.set_sensitive(len(sources) > 0 and len(receivers) > 0)

    def exit(self):
        self.dialog.hide()
Exemplo n.º 15
0
class ResultViewer(gtk.Window):
    def __init__(self,modelf,paramsf,resultsf,auto_update = 1):
        super(ResultViewer, self).__init__()
        self.model_file = modelf if modelf!=None else "model.json"
        self.param_file = paramsf
        self.results_file = resultsf
        self.connect("destroy", gtk.main_quit)
        self.set_size_request(800, 600)
        self.set_position(gtk.WIN_POS_CENTER)
        
        self.vbox = gtk.VBox()
        
        self.time = gtk.SpinButton()
        self.time.set_numeric(True)
        self.time.set_increments(1,1)
        self.time.connect('value-changed', self.on_time_changed)
        self.vbox.pack_start(self.time,False)
        
        self.hbox = gtk.HPaned()
        self.add(self.hbox)
        self.graph = xdot.DotWidget()
        
        self.hbox.pack1(self.graph,True)
        self.set_focus(self.graph)
        
        self.graph.connect('clicked', self.on_url_clicked)

        self.current_node = None
        
        self.hbox.pack2(self.vbox,True)
        self.hbox.set_position(400)
        self.init_chart()
        if auto_update==1:
            import gobject
            gobject.timeout_add(500, self.update)
            self.update()
        else:
            self.reload()
            
        self.show_all()
    
    def reload(self):
        modelins = get_in_stream(self.model_file or "model.json")
        parameterins = get_in_stream(self.param_file or "prm.json")
        resultins = get_in_stream(self.results_file or "res.json")

        self.model = json.load(modelins)
        self.params = json.load(parameterins)
        self.results = json.load(resultins)

        modelins.close()
        parameterins.close()
        resultins.close()
        
        self.set_title(self.model["properties"]["name"])
        self.time.set_range(0,len(self.results)-1)
        
        dotcode = generate_dot(self.model)
        self.graph.set_dotcode(dotcode, filename='<stdin>')

        self.draw_chart()        
        dotcode = generate_dot(self.model)
        self.graph.set_dotcode(dotcode, filename='<stdin>')
        self.graph.zoom_to_fit()
    
    def update(self):
        import os
        import subprocess
        if not hasattr(self, "last_mtime"):
            self.last_mtime = None
        current_mtime = os.stat(self.model_file).st_mtime
        if current_mtime != self.last_mtime:
            self.last_mtime = current_mtime
            subprocess.call("make")
            self.reload()
        return True
    
    def init_chart(self):
        self.figure = Figure(figsize=(6,4), dpi=72)
        self.axis = self.figure.add_subplot(111)
        self.axis.grid(True)   
        self.canvas = FigureCanvasGTK(self.figure) # a gtk.DrawingArea   
        self.canvas.show()
        self.vbox.pack_start(self.canvas, True, True)  
    
    def on_url_clicked(self, widget, url, event):
        self.current_node = url
        self.draw_chart()
        return True
    
    def on_time_changed(self,widget):
        self.draw_chart()
    
    def draw_chart(self):
        self.axis.clear()
        if not (self.current_node is None):
            setup_node_states(self.model["nodes"])
            for n in self.model["nodes"]:
                if n["id"] == self.current_node:
                    node = n
                    break
            
            left = map(lambda x: x[0],n["states"])
            width = map(lambda x: x[1] - x[0],n["states"])

            self.axis.set_xlabel('')
            self.axis.set_ylabel('Probability')
            self.axis.grid(True)
            self.axis.set_title("{1} ({0})".format(self.current_node,n["label"]))            
            values = self.results[int(self.time.get_value())][self.current_node]
            self.axis.bar(left, values, width, color='b')  
            self.axis.set_xlim(left[0],left[-1]+width[-1])
#            self.axis.set_ylim(0,1)
        self.canvas.draw()
Exemplo n.º 16
0
class GuiTourneyGraphViewer:

    def __init__(self, querylist, config, parent, debug=True):
        """Constructor for GraphViewer"""
        self.sql = querylist
        self.conf = config
        self.debug = debug
        self.parent = parent
        #print "start of GraphViewer constructor"
        self.db = Database.Database(self.conf, sql=self.sql)


        filters_display = { "Heroes"        : True,
                            "Sites"         : True,
                            "Games"         : False,
                            "Currencies"    : True,
                            "Limits"        : False,
                            "LimitSep"      : False,
                            "LimitType"     : False,
                            "Type"          : False,
                            "UseType"       : 'tour',
                            "Seats"         : False,
                            "SeatSep"       : False,
                            "Dates"         : True,
                            "GraphOpsTour"  : True,
                            "Groups"        : False,
                            "Button1"       : True,
                            "Button2"       : True
                          }

        self.filters = Filters.Filters(self.db, self.conf, self.sql, display = filters_display)
        self.filters.registerButton1Name(_("Refresh _Graph"))
        self.filters.registerButton1Callback(self.generateGraph)
        self.filters.registerButton2Name(_("_Export to File"))
        self.filters.registerButton2Callback(self.exportGraph)

        self.mainHBox = gtk.HBox(False, 0)
        self.mainHBox.show()

        self.leftPanelBox = self.filters.get_vbox()

        self.hpane = gtk.HPaned()
        self.hpane.pack1(self.leftPanelBox)
        self.mainHBox.add(self.hpane)
        # hierarchy:  self.mainHBox / self.hpane / self.graphBox / self.canvas / self.fig / self.ax

        self.graphBox = gtk.VBox(False, 0)
        self.graphBox.show()
        self.hpane.pack2(self.graphBox)
        self.hpane.show()

        self.fig = None
        #self.exportButton.set_sensitive(False)
        self.canvas = None


        self.db.rollback()

        #update the graph at entry (simulate a "Refresh Graph" click)
        gobject.GObject.emit (self.filters.Button1, "clicked");

    def get_vbox(self):
        """returns the vbox of this thread"""
        return self.mainHBox
    #end def get_vbox

    def clearGraphData(self):
        try:
            if self.canvas:
                self.graphBox.remove(self.canvas)
        except:
            pass

        if self.fig != None:
            self.fig.clear()
        self.fig = Figure(figsize=(5,4), dpi=100)
        if self.canvas is not None:
            self.canvas.destroy()

        self.canvas = FigureCanvas(self.fig)  # a gtk.DrawingArea

    def generateGraph(self, widget, data):
        self.clearGraphData()

        sitenos = []
        playerids = []

        sites   = self.filters.getSites()
        heroes  = self.filters.getHeroes()
        siteids = self.filters.getSiteIds()
        currencies = self.filters.getCurrencies()

        # Which sites are selected?
        for site in sites:
            if sites[site] == True:
                sitenos.append(siteids[site])
                _hname = Charset.to_utf8(heroes[site])
                result = self.db.get_player_id(self.conf, site, _hname)
                if result is not None:
                    playerids.append(int(result))

        if not sitenos:
            #Should probably pop up here.
            print _("No sites selected - defaulting to PokerStars")
            self.db.rollback()
            return

        if not playerids:
            print _("No player ids found")
            self.db.rollback()
            return

        #Set graph properties
        self.ax = self.fig.add_subplot(111)

        #Get graph data from DB
        starttime = time()
        (green, datesXAbs) = self.getData(playerids, sitenos, currencies)
        print _("Graph generated in: %s") %(time() - starttime)

        currencyLabel = ','.join(['%s' % key for key in currencies.keys()])

        #Set axis labels and grid overlay properites
        self.ax.set_ylabel(currencyLabel, fontsize = 12)
        self.ax.grid(color='g', linestyle=':', linewidth=0.2)
        if green == None or green == []:
            self.ax.set_title(_("No Data for Player(s) Found"))
            green = ([    0.,     0.,     0.,     0.,   500.,  1000.,   900.,   800.,
                        700.,   600.,   500.,   400.,   300.,   200.,   100.,     0.,
                        500.,  1000.,  1000.,  1000.,  1000.,  1000.,  1000.,  1000.,
                        1000., 1000.,  1000.,  1000.,  1000.,  1000.,   875.,   750.,
                        625.,   500.,   375.,   250.,   125.,     0.,     0.,     0.,
                        0.,   500.,  1000.,   900.,   800.,   700.,   600.,   500.,
                        400.,   300.,   200.,   100.,     0.,   500.,  1000.,  1000.])
            red   =  ([    0.,     0.,     0.,     0.,   500.,  1000.,   900.,   800.,
                        700.,   600.,   500.,   400.,   300.,   200.,   100.,     0.,
                        0.,   0.,     0.,     0.,     0.,     0.,   125.,   250.,
                        375.,   500.,   500.,   500.,   500.,   500.,   500.,   500.,
                        500.,   500.,   375.,   250.,   125.,     0.,     0.,     0.,
                        0.,   500.,  1000.,   900.,   800.,   700.,   600.,   500.,
                        400.,   300.,   200.,   100.,     0.,   500.,  1000.,  1000.])
            blue =    ([    0.,     0.,     0.,     0.,   500.,  1000.,   900.,   800.,
                          700.,   600.,   500.,   400.,   300.,   200.,   100.,     0.,
                          0.,     0.,     0.,     0.,     0.,     0.,   125.,   250.,
                          375.,   500.,   625.,   750.,   875.,  1000.,   875.,   750.,
                          625.,   500.,   375.,   250.,   125.,     0.,     0.,     0.,
                        0.,   500.,  1000.,   900.,   800.,   700.,   600.,   500.,
                        400.,   300.,   200.,   100.,     0.,   500.,  1000.,  1000.])

            self.ax.plot(green, color='green', label=_('Tournaments') + ': %d\n' % len(green) + _('Profit') + '(' + currencyLabel + '): %.2f' % green[-1])
            self.graphBox.add(self.canvas)
            self.canvas.show()
            self.canvas.draw()

            #TODO: Do something useful like alert user
        else:
            self.ax.set_title(_("Tournament Results"))
            useDates = True

            #nothing to draw
            if (len(green) == 0):
                return
            #Get the dates of tourneys
            #if first tourney has no date, get the most ancient date and assume it's his one
            if datesXAbs[0] is None:
                i = 1
                while i < len(datesXAbs) and type(datesXAbs[i]) is None:
                    i = i+1
                if i == len(datesXAbs):
                    print "Wow wow wow : no dates in your whole tourneys"
                    useDates = False
                else:
                    datesXAbs[0] = datesXAbs[i]

            #now convert date to dateTime format
            if useDates:
                for i in range(0, len(datesXAbs)):
                    if datesXAbs[i] is None:
                        datesXAbs[i] = datesXAbs[i-1]
                    else:
                        datesXAbs[i] = datetime.datetime.strptime(datesXAbs[i], "%Y-%m-%d %H:%M:%S")

                    datesXAbs[i] = datesXAbs[i].strftime('%d/%m')



            mycolor='red'
            if green[0]>0:
                mycolor='green'

            self.ax.plot([0,1], [0,green[0]], color=mycolor, label=_('Tournaments') + ': %d\n' % len(green) + _('Profit') + '(' + currencyLabel + '): %.2f' % green[-1])
            for i in range(1,  len(green)):
                final=green[i]-green[i-1]
                mycolor='red'
                if (green[i]>0):
                    mycolor='green'


                self.ax.plot([i,i+1], [green[i-1],green[i]], color=mycolor)
                if (i % (len(green)/5) == 0):
                    gain=""
                    if (green[i]==0):
                        gain="="
                    else:
                        if (green[i]>0):
                            gain="+"
                        gain += str(green[i])

                    self.ax.annotate(gain, xy=(i, 0), color=mycolor, xycoords=('data', 'axes fraction'),
                    xytext=(0, 18), textcoords='offset points', va='top', ha='left')

                    if useDates:
                        self.ax.annotate(datesXAbs[i], xy=(i, 0), xycoords=('data', 'axes fraction'),
                        xytext=(0, -18), textcoords='offset points', va='top', ha='left')


            #~self.ax.axhline(0, color='black', lw=2)

            legend = self.ax.legend(loc='upper left', fancybox=True, shadow=True, prop=FontProperties(size='smaller'))
            legend.draggable(True)

            self.graphBox.add(self.canvas)
            self.canvas.show()
            self.canvas.draw()
            #self.exportButton.set_sensitive(True)

    #end of def showClicked

    def getData(self, names, sites, currencies):
        tmp = self.sql.query['tourneyGraph']
        # print "DEBUG: getData. :"
        start_date, end_date = self.filters.getDates()

        #Buggered if I can find a way to do this 'nicely' take a list of integers and longs
        # and turn it into a tuple readale by sql.
        # [5L] into (5) not (5,) and [5L, 2829L] into (5, 2829)
        nametest = str(tuple(names))
        sitetest = str(tuple(sites))
        currencytest = str(tuple())

        #Must be a nicer way to deal with tuples of size 1 ie. (2,) - which makes sql barf
        tmp = tmp.replace("<player_test>", nametest)
        tmp = tmp.replace("<site_test>", sitetest)
        
        currencytest = str(tuple(currencies))
        currencytest = currencytest.replace(",)",")")
        currencytest = currencytest.replace("u'","'")
        currencytest = "AND tt.currency in %s" % currencytest
        tmp = tmp.replace("<currency_test>", currencytest)

        tmp = tmp.replace("<startdate_test>", start_date)
        tmp = tmp.replace("<enddate_test>", end_date)
        tmp = tmp.replace(",)", ")")

        # print "DEBUG: sql query:", tmp

        self.db.cursor.execute(tmp)
        #returns (HandId,Winnings,Costs,Profit)
        winnings = self.db.cursor.fetchall()
        self.db.rollback()

        if len(winnings) == 0:
            return (None, None)

        green = map(lambda x:float(x[1]), winnings)

        datesXAbs = map(lambda x:x[8], winnings)
        #blue  = map(lambda x: float(x[1]) if x[2] == True  else 0.0, winnings)
        #red   = map(lambda x: float(x[1]) if x[2] == False else 0.0, winnings)
        greenline = cumsum(green)
        #blueline  = cumsum(blue)
        #redline   = cumsum(red)

        return (greenline/100, datesXAbs)

    def exportGraph (self, widget, data):
        if self.fig is None:
            return # Might want to disable export button until something has been generated.

        dia_chooser = gtk.FileChooserDialog(title=_("Please choose the directory you wish to export to:"),
                                            action=gtk.FILE_CHOOSER_ACTION_SELECT_FOLDER,
                                            buttons=(gtk.STOCK_CANCEL,gtk.RESPONSE_CANCEL,gtk.STOCK_OK,gtk.RESPONSE_OK))
        dia_chooser.set_destroy_with_parent(True)
        dia_chooser.set_transient_for(self.parent)
        try:
            dia_chooser.set_filename(self.exportFile) # use previously chosen export path as default
        except:
            pass

        response = dia_chooser.run()

        if response <> gtk.RESPONSE_OK:
            print _('Closed, no graph exported')
            dia_chooser.destroy()
            return

        # generate a unique filename for export
        now = datetime.now()
        now_formatted = now.strftime("%Y%m%d%H%M%S")
        self.exportFile = dia_chooser.get_filename() + "/fpdb" + now_formatted + ".png"
        dia_chooser.destroy()

        #print "DEBUG: self.exportFile = %s" %(self.exportFile)
        self.fig.savefig(self.exportFile, format="png")

        #display info box to confirm graph created
        diainfo = gtk.MessageDialog(parent=self.parent,
                                flags=gtk.DIALOG_DESTROY_WITH_PARENT,
                                type=gtk.MESSAGE_INFO,
                                buttons=gtk.BUTTONS_OK,
                                message_format=_("Graph created"))
        diainfo.format_secondary_text(self.exportFile)
        diainfo.run()
        diainfo.destroy()
Exemplo n.º 17
0
class ManipulateGUI(object):
    """woot"""

    def __init__(self,parameterDict, liveUpdate=False):
        # 'public' vars
	self.parameterDict = parameterDict
        self.liveUpdate = liveUpdate
        self.nParams = len(parameterDict)

        #Set the Glade file and build from it
        self.gladefile = findFileInPythonPath('manipulateGUI.glade')
        self.builder = gtk.Builder()
        self.builder.add_from_file(self.gladefile)

        #Grab some key gui handles
        self.window = self.builder.get_object('manipulateWindow')
        self.window.connect('destroy', gtk.main_quit)
        self.paramBox = self.builder.get_object("paramBox")

        # loop over the parameterDict and...
        # ... label for every fixed parameter
        # ... slider for every variable
        # ... dropdown for non-fixed parameter

        self.widgetList = []
        self.adjustmentList = []
        self.comboboxList = []

        for arg, params in self.parameterDict.iteritems():
            hbox = gtk.HBox(False, 0)
            label = gtk.Label(arg+':')
            label.show()
            hbox.pack_start(label, True, True)

            if params['type'] == 'fixed':
                #add a new GTKlabel
                self.widgetList.append(gtk.Label(params['value']))

            elif params['type'] == 'range':
                # a horizatonal scale bar
                # self.adjustmentList.append(gtk.Adjustment(value=params['value'], lower=params['lower'], upper=params['upper'], step_incr=params['step'], page_incr=params['page_inc'],page_size=params['page_size']))
                self.adjustmentList.append(gtk.Adjustment(value=params['value'], lower=params['lower'], upper=params['upper'], step_incr=params['step']))
                self.widgetList.append(gtk.HScale(adjustment=self.adjustmentList[-1]))

                self.widgetList[-1].connect('change-value', self.on_param_change_range_value)

            elif params['type'] == 'list':
                # build combobox from list
                self.widgetList.append(gtk.combo_box_new_text())
                for item in params['options']:
                    self.widgetList[-1].append_text(item)

                self.widgetList[-1].set_active(0)
                self.widgetList[-1].connect('changed', self.on_param_change_list_value)

            self.widgetList[-1].argName = arg

            hbox.pack_start(child=self.widgetList[-1], expand=True, fill=True)
            self.paramBox.pack_start(child=hbox, expand=True, fill=True)
            # self.paramBox.pack_start(child=self.widgetList[-1], expand=True, fill=True)


        # setup matplotlib in the matplotlibWindow
        self.figure = Figure(figsize=(10,4), dpi=72)
        self.inputAxis = self.figure.add_subplot(1,2,1)
        self.outputAxis = self.figure.add_subplot(1,2,2)
        
        self.canvas = FigureCanvasGTK(self.figure) # a gtk.DrawingArea
        self.canvas.show()
        self.canvas.draw()
        
        self.plotView = self.builder.get_object("mplBox")
        self.plotView.pack_start(self.canvas, True, True)

        # connect and init data
        self.builder.connect_signals(self)
        self.window.show_all()

    # button and checkbox callbacks
    def on_return_clicked(self, widget):
        # overload in subclass
        pass

    def on_refresh_clicked(self, widget):
        self.eval_function()

    def on_param_change_range_value(self, widget, event, paramValue):
        self.parameterDict[widget.argName]['value'] = paramValue
        if self.liveUpdate:
            self.eval_function()

    def on_param_change_list_value(self, widget):
        self.parameterDict[widget.argName]['value'] = widget.get_active()
        if self.liveUpdate:
            self.eval_function()

    def eval_function(self):
    # overload in subclass
    # should use self.parameterDict somehow... (particular for each subclass)
    # self.function(arg1 = self.parameterDict['arg1']['value'] , ... )
        pass
Exemplo n.º 18
0
class Backend( backend.Backend ):

    def init(self):
        # line_cache: key = id(Curve), value=mpl line object
        self.line_cache = dict()
        
        self.layer_to_axes = dict()
        self.axes_to_layer = dict()
        self.layers_cache = list() # copy of self.plot.layers
        
    def connect(self):
        logger.debug("Opening matplotlib session.")        

        self.figure = Figure(dpi=100, facecolor="white")  # figsize=(5,4), dpi=100)        
        self.canvas = FigureCanvas(self.figure)
        self.canvas.show()

        self.line_cache.clear()
        self.layer_to_axes.clear()
        self.axes_to_layer.clear()

        backend.Backend.connect(self)
        logger.debug("Init finished")


    def disconnect(self):
        logger.debug("Closing matplotlib session.")

        if not self.canvas is None:
            self.canvas.destroy()
            self.canvas = None
        if not self.figure is None:
            self.figure = None
        
        backend.Backend.disconnect(self)


    #----------------------------------------------------------------------

    def arrange(self, rows=1, cols=1):

        layers = self.plot.layers
        n = len(layers)

        if n > (rows*cols):
            rows = int((rows*cols) / n) + 1
            cols = rows * n
            #raise ValueError("Not enough rows and cols for all layers!")

        self.figure.clear()
        self.figure.axes = []
        
        self.layer_to_axes.clear()
        self.axes_to_layer.clear()
        self.layers_cache = list()
        j = 1
        for layer in layers:
            print "Setting up layer", layer
            axes = self.figure.add_subplot("%d%d%d" % (rows,cols,j))
            self.layer_to_axes[layer] = axes
            self.axes_to_layer[axes] = layer
            self.layers_cache.append(layer)
            j += 1
        

        
    def draw_layer(self, layer, group_info):

        ax = self.layer_to_axes[layer]

        print "DRAWING AXES ", ax
        ax.lines = []

        line_cache = []
        line_count = 0
        last_cx = -1

        # Default values come in two flavors:
        # group-wise and single default values        
        group_colors = uwrap.get(layer, 'group_colors')
        group_styles = uwrap.get(layer, 'group_styles')
        group_markers = uwrap.get(layer, 'group_markers')

        #default_color = 'r'
        default_color = None
        default_style = 'solid'
        default_marker = 'None'
        

        #:layer.visible
        if uwrap.get(layer, 'visible') is False:
            return

        #:layer.title
        title = uwrap.get(layer, 'title', None)
        if title is not None:
            ax.set_title(title)        

        #:layer.grid
        grid = uwrap.get(layer, 'grid')
        ax.grid(grid)                         

        #:layer.lines
        for line in layer.lines:
            data_to_plot = []
            
            #:line.visible
            if uwrap.get(line, 'visible') is False:
                if line in ax.lines:
                    ax.lines.remove(line)
                continue

            ds = self.get_line_source(line)
            table = self.get_table(ds)
            cx, cy = self.get_column_indices(line)
            xdata, ydata = self.get_table_data(table, cx, cy)

            #:line.row_first
            #:line.row_last
            def limit_data(data, start, end):
                try:
                    return data[start:end]
                except IndexError:
                    backend.BackendError("Index range '%s'out of bounds!" % (start,end) )

            start, end = line.row_first, line.row_last
            xdata = limit_data(xdata, start, end)
            ydata = limit_data(ydata, start, end)
            

            #:line.style
            global linestyle_mappings
            default = default_style or group_styles[line_count % len(group_styles)]
            style = uwrap.get(line, 'style', default)
            style = linestyle_mappings[style]


            #:line.marker
            global linemarker_mappings
            default = default_marker or group_markers[line_count % len(group_markers)]
            marker = uwrap.get(line, 'marker', default)
            marker = linemarker_mappings[marker]


            #:line.width
            width = uwrap.get(line, 'width')

            
            #:line.color
            default = default_color or group_colors[line_count % len(group_colors)]
            color = uwrap.get(line, 'color', default)


            #--- PLOT LINE ---
            l, = ax.plot( xdata, ydata,
                          linewidth=width,
                          linestyle=style,
                          marker=marker,
                          color=color)
            line_cache.append(l)


            label = self.get_line_label(line, table=table, cy=cy)
            l.set_label(label)

            line_count += 1

#         #
#         # additional lines
#         #
#         p = len(xdata)
#         if p > 2: p = p/2
#         atpoint = xdata[max(p-1,0)]
#         print "Printing vertical line at ", atpoint
#         ax.axvline(atpoint)
        
        #:layer.legend
        legend = uwrap.get(layer, 'legend')
        if legend is not None and line_count > 0:
            visible = uwrap.get(legend, 'visible')
            if visible is True:
                #:legend.label:TODO
                label = uwrap.get(legend, 'visible')
                if label is not None:
                    pass

                #:legend.border:OK
                # (see below but keep it here!)
                border = uwrap.get(legend, 'border')
                                                
                #:legend.position TODO
                position = uwrap.get(legend, 'position', 'best')
                if position == 'at position':
                    position = (uwrap.get(legend, 'x'), uwrap.get(legend, 'y'))

                # create legend entries from line labels
                labels = [l.get_label() for l in line_cache]                
                
                legend = ax.legend(line_cache, labels, loc=position)
                legend.draw_frame(border)

            else:
                ax.legend_ = None
        else:
            ax.legend_ = None

        #:layer.axes
        for (key, axis) in layer.axes.iteritems():
            #:axis.label
            #:axis.scale
            #:axis.start
            #:axis.end
            label = uwrap.get(axis, 'label')            
            scale = uwrap.get(axis, 'scale')
            start = uwrap.get(axis, 'start')
            end = uwrap.get(axis, 'end')
            print "START = %s, END = %s" % (str(start), str(end))
            if key == 'x':
                set_label = ax.set_xlabel
                set_scale = ax.set_xscale
                set_start = (lambda l: ax.set_xlim(xmin=l))
                set_end = (lambda l: ax.set_xlim(xmax=l))
            elif key == 'y':
                set_label = ax.set_ylabel
                set_scale = ax.set_yscale
                set_start = (lambda l: ax.set_ylim(ymin=l))
                set_end = (lambda l: ax.set_ylim(ymax=l))
            else:
                raise RuntimeError("Invalid axis key '%s'" % key)

            if label is not None: set_label(label)
            if scale is not None: set_scale(scale)
            if start is not None: set_start(start)
            if end is not None: set_end(end)  




    def draw(self):
        logger.debug("Matplotlib: draw()")
        
        self.check_connection()
               
        # plot all curves together in one plot
        legend_list = [] # for legend later on
        curve_count = 0
       
        #
        if self.plot.layers != self.layers_cache:
            self.arrange()

        for layer in self.plot.layers:
            group_info = {}
            self.draw_layer(layer, group_info)
       
        self.canvas.draw()
Exemplo n.º 19
0
class GuiGraphViewer (threading.Thread):

    def __init__(self, querylist, config, parent, debug=True):
        """Constructor for GraphViewer"""
        self.sql = querylist
        self.conf = config
        self.debug = debug
        self.parent = parent
        #print "start of GraphViewer constructor"
        self.db = Database.Database(self.conf, sql=self.sql)


        filters_display = { "Heroes"    : True,
                            "Sites"     : True,
                            "Games"     : True,
                            "Limits"    : True,
                            "LimitSep"  : True,
                            "LimitType" : True,
                            "Type"      : False,
                            "UseType"   : 'ring',
                            "Seats"     : False,
                            "SeatSep"   : False,
                            "Dates"     : True,
                            "Groups"    : False,
                            "Button1"   : True,
                            "Button2"   : True
                          }

        self.filters = Filters.Filters(self.db, self.conf, self.sql, display = filters_display)
        self.filters.registerButton1Name("Refresh _Graph")
        self.filters.registerButton1Callback(self.generateGraph)
        self.filters.registerButton2Name("_Export to File")
        self.filters.registerButton2Callback(self.exportGraph)

        self.mainHBox = gtk.HBox(False, 0)
        self.mainHBox.show()

        self.leftPanelBox = self.filters.get_vbox()

        self.hpane = gtk.HPaned()
        self.hpane.pack1(self.leftPanelBox)
        self.mainHBox.add(self.hpane)
        # hierarchy:  self.mainHBox / self.hpane / self.graphBox / self.canvas / self.fig / self.ax

        self.graphBox = gtk.VBox(False, 0)
        self.graphBox.show()
        self.hpane.pack2(self.graphBox)
        self.hpane.show()

        self.fig = None
        #self.exportButton.set_sensitive(False)
        self.canvas = None


        self.db.rollback()

    def get_vbox(self):
        """returns the vbox of this thread"""
        return self.mainHBox
    #end def get_vbox

    def clearGraphData(self):

        try:
            try:
                if self.canvas:
                    self.graphBox.remove(self.canvas)
            except:
                pass

            if self.fig != None:
                self.fig.clear()
            self.fig = Figure(figsize=(5,4), dpi=100)
            if self.canvas is not None:
                self.canvas.destroy()

            self.canvas = FigureCanvas(self.fig)  # a gtk.DrawingArea
        except:
            err = traceback.extract_tb(sys.exc_info()[2])[-1]
            print _("***Error: ")+err[2]+"("+str(err[1])+"): "+str(sys.exc_info()[1])
            raise

    def generateGraph(self, widget, data):
        try:
            self.clearGraphData()

            sitenos = []
            playerids = []

            sites   = self.filters.getSites()
            heroes  = self.filters.getHeroes()
            siteids = self.filters.getSiteIds()
            limits  = self.filters.getLimits()
            games   = self.filters.getGames()
            
            for i in ('show', 'none'):
                if i in limits:
                    limits.remove(i)
            # Which sites are selected?
            for site in sites:
                if sites[site] == True:
                    sitenos.append(siteids[site])
                    _hname = Charset.to_utf8(heroes[site])
                    result = self.db.get_player_id(self.conf, site, _hname)
                    if result is not None:
                        playerids.append(int(result))

            if not sitenos:
                #Should probably pop up here.
                print _("No sites selected - defaulting to PokerStars")
                self.db.rollback()
                return

            if not playerids:
                print _("No player ids found")
                self.db.rollback()
                return

            if not limits:
                print _("No limits found")
                self.db.rollback()
                return

            #Set graph properties
            self.ax = self.fig.add_subplot(111)

            #Get graph data from DB
            starttime = time()
            (green, blue, red) = self.getRingProfitGraph(playerids, sitenos, limits, games)
            print _("Graph generated in: %s") %(time() - starttime)


            #Set axis labels and grid overlay properites
            self.ax.set_xlabel(_("Hands"), fontsize = 12)
            self.ax.set_ylabel("$", fontsize = 12)
            self.ax.grid(color='g', linestyle=':', linewidth=0.2)
            if green == None or green == []:
                self.ax.set_title(_("No Data for Player(s) Found"))
                green = ([    0.,     0.,     0.,     0.,   500.,  1000.,   900.,   800.,
                            700.,   600.,   500.,   400.,   300.,   200.,   100.,     0.,
                            500.,  1000.,  1000.,  1000.,  1000.,  1000.,  1000.,  1000.,
                            1000., 1000.,  1000.,  1000.,  1000.,  1000.,   875.,   750.,
                            625.,   500.,   375.,   250.,   125.,     0.,     0.,     0.,
                            0.,   500.,  1000.,   900.,   800.,   700.,   600.,   500.,
                            400.,   300.,   200.,   100.,     0.,   500.,  1000.,  1000.])
                red   =  ([    0.,     0.,     0.,     0.,   500.,  1000.,   900.,   800.,
                            700.,   600.,   500.,   400.,   300.,   200.,   100.,     0.,
                            0.,   0.,     0.,     0.,     0.,     0.,   125.,   250.,
                            375.,   500.,   500.,   500.,   500.,   500.,   500.,   500.,
                            500.,   500.,   375.,   250.,   125.,     0.,     0.,     0.,
                            0.,   500.,  1000.,   900.,   800.,   700.,   600.,   500.,
                            400.,   300.,   200.,   100.,     0.,   500.,  1000.,  1000.])
                blue =    ([    0.,     0.,     0.,     0.,   500.,  1000.,   900.,   800.,
                              700.,   600.,   500.,   400.,   300.,   200.,   100.,     0.,
                              0.,     0.,     0.,     0.,     0.,     0.,   125.,   250.,
                              375.,   500.,   625.,   750.,   875.,  1000.,   875.,   750.,
                              625.,   500.,   375.,   250.,   125.,     0.,     0.,     0.,
                            0.,   500.,  1000.,   900.,   800.,   700.,   600.,   500.,
                            400.,   300.,   200.,   100.,     0.,   500.,  1000.,  1000.])

                self.ax.plot(green, color='green', label=_('Hands: %d\nProfit: $%.2f') %(len(green), green[-1]))
                self.ax.plot(blue, color='blue', label=_('Showdown: $%.2f') %(blue[-1]))
                self.ax.plot(red, color='red', label=_('Non-showdown: $%.2f') %(red[-1]))
                self.graphBox.add(self.canvas)
                self.canvas.show()
                self.canvas.draw()

                #TODO: Do something useful like alert user
                #print "No hands returned by graph query"
            else:
                self.ax.set_title(_("Profit graph for ring games"))
                #text = "Profit: $%.2f\nTotal Hands: %d" %(green[-1], len(green))
                #self.ax.annotate(text,
                #                 xy=(10, -10),
                #                 xycoords='axes points',
                #                 horizontalalignment='left', verticalalignment='top',
                #                 fontsize=10)

                #Draw plot
                self.ax.plot(green, color='green', label=_('Hands: %d\nProfit: $%.2f') %(len(green), green[-1]))
                self.ax.plot(blue, color='blue', label=_('Showdown: $%.2f') %(blue[-1]))
                self.ax.plot(red, color='red', label=_('Non-showdown: $%.2f') %(red[-1]))
                if sys.version[0:3] == '2.5':
                    self.ax.legend(loc='upper left', shadow=True, prop=FontProperties(size='smaller'))
                else:
                    self.ax.legend(loc='upper left', fancybox=True, shadow=True, prop=FontProperties(size='smaller'))

                self.graphBox.add(self.canvas)
                self.canvas.show()
                self.canvas.draw()
                #self.exportButton.set_sensitive(True)
        except:
            err = traceback.extract_tb(sys.exc_info()[2])[-1]
            print _("***Error: ")+err[2]+"("+str(err[1])+"): "+str(sys.exc_info()[1])

    #end of def showClicked

    def getRingProfitGraph(self, names, sites, limits, games):
        tmp = self.sql.query['getRingProfitAllHandsPlayerIdSite']
#        print "DEBUG: getRingProfitGraph"
        start_date, end_date = self.filters.getDates()

        #Buggered if I can find a way to do this 'nicely' take a list of integers and longs
        # and turn it into a tuple readale by sql.
        # [5L] into (5) not (5,) and [5L, 2829L] into (5, 2829)
        nametest = str(tuple(names))
        sitetest = str(tuple(sites))
        #nametest = nametest.replace("L", "")

        q = []
        for m in self.filters.display.items():
            if m[0] == 'Games' and m[1]:
                for n in games:
                    if games[n]:
                        q.append(n)
                if len(q) > 0:
                    gametest = str(tuple(q))
                    gametest = gametest.replace("L", "")
                    gametest = gametest.replace(",)",")")
                    gametest = gametest.replace("u'","'")
                    gametest = "and gt.category in %s" % gametest
                else:
                    gametest = "and gt.category IS NULL"
        tmp = tmp.replace("<game_test>", gametest)
        
        lims = [int(x) for x in limits if x.isdigit()]
        potlims = [int(x[0:-2]) for x in limits if len(x) > 2 and x[-2:] == 'pl']
        nolims = [int(x[0:-2]) for x in limits if len(x) > 2 and x[-2:] == 'nl']
        limittest = "and ( (gt.limitType = 'fl' and gt.bigBlind in "
                 # and ( (limit and bb in()) or (nolimit and bb in ()) )
        if lims:
            blindtest = str(tuple(lims))
            blindtest = blindtest.replace("L", "")
            blindtest = blindtest.replace(",)",")")
            limittest = limittest + blindtest + ' ) '
        else:
            limittest = limittest + '(-1) ) '
        limittest = limittest + " or (gt.limitType = 'pl' and gt.bigBlind in "
        if potlims:
            blindtest = str(tuple(potlims))
            blindtest = blindtest.replace("L", "")
            blindtest = blindtest.replace(",)",")")
            limittest = limittest + blindtest + ' ) '
        else:
            limittest = limittest + '(-1) ) '
        limittest = limittest + " or (gt.limitType = 'nl' and gt.bigBlind in "
        if nolims:
            blindtest = str(tuple(nolims))
            blindtest = blindtest.replace("L", "")
            blindtest = blindtest.replace(",)",")")
            limittest = limittest + blindtest + ' ) )'
        else:
            limittest = limittest + '(-1) ) )'

        if type == 'ring':
            limittest = limittest + " and gt.type = 'ring' "
        elif type == 'tour':
            limittest = limittest + " and gt.type = 'tour' "

        #Must be a nicer way to deal with tuples of size 1 ie. (2,) - which makes sql barf
        tmp = tmp.replace("<player_test>", nametest)
        tmp = tmp.replace("<site_test>", sitetest)
        tmp = tmp.replace("<startdate_test>", start_date)
        tmp = tmp.replace("<enddate_test>", end_date)
        tmp = tmp.replace("<limit_test>", limittest)
        tmp = tmp.replace(",)", ")")

        #print "DEBUG: sql query:"
        #print tmp
        self.db.cursor.execute(tmp)
        #returns (HandId,Winnings,Costs,Profit)
        winnings = self.db.cursor.fetchall()
        self.db.rollback()

        if len(winnings) == 0:
            return (None, None, None)

        green = map(lambda x:float(x[1]), winnings)
        blue  = map(lambda x: float(x[1]) if x[2] == True  else 0.0, winnings)
        red   = map(lambda x: float(x[1]) if x[2] == False else 0.0, winnings)
        greenline = cumsum(green)
        blueline  = cumsum(blue)
        redline   = cumsum(red)
        return (greenline/100, blueline/100, redline/100)
        #end of def getRingProfitGraph

    def exportGraph (self, widget, data):
        if self.fig is None:
            return # Might want to disable export button until something has been generated.

        dia_chooser = gtk.FileChooserDialog(title=_("Please choose the directory you wish to export to:"),
                                            action=gtk.FILE_CHOOSER_ACTION_SELECT_FOLDER,
                                            buttons=(gtk.STOCK_CANCEL,gtk.RESPONSE_CANCEL,gtk.STOCK_OK,gtk.RESPONSE_OK))
        dia_chooser.set_destroy_with_parent(True)
        dia_chooser.set_transient_for(self.parent)
        try: 
            dia_chooser.set_filename(self.exportFile) # use previously chosen export path as default
        except:
            pass

        response = dia_chooser.run()
        
        if response <> gtk.RESPONSE_OK:
            print _('Closed, no graph exported')
            dia_chooser.destroy()
            return
            
        # generate a unique filename for export
        now = datetime.now()
        now_formatted = now.strftime("%Y%m%d%H%M%S")
        self.exportFile = dia_chooser.get_filename() + "/fpdb" + now_formatted + ".png"
        dia_chooser.destroy()
        
        #print "DEBUG: self.exportFile = %s" %(self.exportFile)
        self.fig.savefig(self.exportFile, format="png")

        #display info box to confirm graph created
        diainfo = gtk.MessageDialog(parent=self.parent,
                                flags=gtk.DIALOG_DESTROY_WITH_PARENT,
                                type=gtk.MESSAGE_INFO,
                                buttons=gtk.BUTTONS_OK,
                                message_format=_("Graph created"))
        diainfo.format_secondary_text(self.exportFile)          
        diainfo.run()
        diainfo.destroy()
Exemplo n.º 20
0
class Main:

	def delete(self, widget, event, data=None):
		return False

	def destroy(self, widget, data=None):
		self.thread.abort()
		gtk.main_quit()
	
	def update(self):
		if (self.queue.empty()):
			return True

		data = self.queue.get()
		self.lines1[0].set_data(data.time,data.setpoint)
		self.lines1[1].set_data(data.time,data.temperature)
		self.lines2[0].set_data(data.time,data.power)
		self.x1.relim()
		self.x2.relim()
		self.x1.autoscale_view()
		self.x2.autoscale_view()
		self.canvas.draw()
		return True
		
	def save_settings(self,widget,port):
		self.thread.wait(1)
		port.write("save\r")
		port.readline()
		self.thread.wait(0)
		return 
	
	def set_settings(self,widget,port,P,I,D,T):
		self.thread.wait(1)
		port.write("set KP " + str(P.get_value_as_int()) + "\r")
		port.readline()

		port.write("set KI " + str(I.get_value_as_int()) + "\r")
		port.readline()

		port.write("set KD " + str(D.get_value_as_int()) + "\r")
		port.readline()

		port.write("set KT " + str(T.get_value_as_int()) + "\r")
		port.readline()

		self.thread.wait(0)
		return

	def get_settings(self,widget,port,P,I,D,T):
		self.thread.wait(1)
	
		port.write("eeprom\r")
		port.readline()
		words = port.readline().split()
		P.set_value( int(words[1]) )
		words = port.readline().split()
		I.set_value( int(words[1]) )
		words = port.readline().split()
		D.set_value( int(words[1]) )
		words = port.readline().split()
		T.set_value( int(words[1]) )
		port.readline()
		self.thread.wait(0)
		return

	def __init__(self):
		try:
			port = serial.Serial(port='/dev/ttyS0', baudrate=9600, bytesize=8, parity='N', stopbits=1, timeout=0.1)
		except serial.SerialException:
			sys.stderr.write("could not open port\n")
			sys.exit(1)

		port.write("log 1\r")
		port.readline()

		self.queue = Queue.Queue(1)
		self.thread = UpdateData(port,self.queue)
		self.thread.start()

		self.window = gtk.Window(gtk.WINDOW_TOPLEVEL)
		self.window.set_default_size(800,600)
		self.window.set_title("PID logger")

		self.window.connect("delete_event",self.delete)
		self.window.connect("destroy",self.destroy)
		
		## matlibplot
		self.figure = Figure(figsize=(5,4),dpi=100)
		self.x1 = self.figure.add_subplot(111)
		self.x2 = self.figure.add_subplot(111,sharex=self.x1,frameon=False)

		self.x1.set_xlabel('time')   
		self.x1.set_ylabel('temperature')   
		self.x1.set_title('temperature profile')   
		self.x1.grid(True)
		self.x1.yaxis.tick_left()
		self.x2.yaxis.tick_right()

		self.canvas = FigureCanvasGTK(self.figure)
		self.canvas.draw()	
		self.canvas.show()

		vbox = gtk.VBox(homogeneous=False, spacing=0)
		hbox0 = gtk.HBox()
		self.window.add(vbox)
		vbox.pack_start(self.canvas,expand=True,fill=True,padding=0)

		separator0 = gtk.HSeparator()
		vbox.pack_start(separator0, expand=False, fill=False, padding=10)

		#PID settings
		PAdjustment = gtk.Adjustment(value=0,lower=0,upper=32,step_incr=1,page_incr=1,page_size=0)
		IAdjustment = gtk.Adjustment(value=0,lower=0,upper=32,step_incr=1,page_incr=1,page_size=0)
		DAdjustment = gtk.Adjustment(value=0,lower=0,upper=32,step_incr=1,page_incr=1,page_size=0)
		TAdjustment = gtk.Adjustment(value=0,lower=0,upper=255,step_incr=1,page_incr=10,page_size=0)

		Plabel = gtk.Label("P")
		Ilabel = gtk.Label("I")
		Dlabel = gtk.Label("D")
		Tlabel = gtk.Label("PID threshold")

		Pspinbutton = gtk.SpinButton(adjustment=PAdjustment,digits=0)
		Ptooltips = gtk.Tooltips()
		Ptooltips.set_tip(Pspinbutton,"Proportional term of the PID function",tip_private=None)
		Ispinbutton = gtk.SpinButton(adjustment=IAdjustment,digits=0)
		Itooltips = gtk.Tooltips()
		Itooltips.set_tip(Ispinbutton,"Integral term of the PID function (in units of 1/100)",tip_private=None)
		Dspinbutton = gtk.SpinButton(adjustment=DAdjustment,digits=0)
		Dtooltips = gtk.Tooltips()
		Dtooltips.set_tip(Dspinbutton,"Derivative term of the PID function",tip_private=None)
		Tspinbutton = gtk.SpinButton(adjustment=TAdjustment,digits=0)
		Ttooltips = gtk.Tooltips()
		Ttooltips.set_tip(Tspinbutton,"Error threshold between PD and PID behaviour of the controller",tip_private=None)

		Pvbox = gtk.VBox()
		Pvbox.pack_start(Plabel)
		Pvbox.pack_start(Pspinbutton)

		Ivbox = gtk.VBox()
		Ivbox.pack_start(Ilabel)
		Ivbox.pack_start(Ispinbutton)

		Dvbox = gtk.VBox()
		Dvbox.pack_start(Dlabel)
		Dvbox.pack_start(Dspinbutton)

		Tvbox = gtk.VBox()
		Tvbox.pack_start(Tlabel)
		Tvbox.pack_start(Tspinbutton)

		hbox0.pack_start(Pvbox,expand=True,fill=False)
		hbox0.pack_start(Ivbox,expand=True,fill=False)
		hbox0.pack_start(Dvbox,expand=True,fill=False)
		hbox0.pack_start(Tvbox,expand=True,fill=False)

		vbox.pack_start(hbox0,expand=False,fill=False,padding=0)
		
		hbox1 = gtk.HBox()
		Setbutton = gtk.Button(label="Set settings",stock=None)
		Setbutton.connect("clicked",self.set_settings,port,Pspinbutton,Ispinbutton,Dspinbutton,Tspinbutton)
		Settooltips = gtk.Tooltips()
		Settooltips.set_tip(Setbutton,"Apply settings to the PID controller",tip_private=None)
		self.get_settings(self,port,Pspinbutton,Ispinbutton,Dspinbutton,Tspinbutton)

		Savebutton = gtk.Button(label="Save settings",stock=None)
		Savetooltips = gtk.Tooltips()
		Savetooltips.set_tip(Savebutton,"Store current settings in the eeprom of the controller",tip_private=None)
		Savebutton.connect("clicked",self.save_settings,port)

		Getbutton = gtk.Button(label="Get settings",stock=None)
		Gettooltips = gtk.Tooltips()
		Gettooltips.set_tip(Getbutton,"Get PID settings from eeprom of the controller",tip_private=None)
		Getbutton.connect("clicked",self.get_settings,port,PAdjustment,IAdjustment,DAdjustment,TAdjustment)

		hbox1.pack_start(Getbutton,expand=True,fill=False,padding=10)
		hbox1.pack_start(Setbutton,expand=True,fill=False,padding=10)
		hbox1.pack_start(Savebutton,expand=True,fill=False,padding=10)
	
		separator1 = gtk.HSeparator()
		vbox.pack_start(separator1,expand=False,fill=False,padding=10)
		vbox.pack_start(hbox1,expand=False,fill=False,padding=0)



		self.lines1 = self.x1.plot([0,0],[0,0],'r-',[0,0],[0,0],'b-')
		self.lines2 = self.x2.plot([0,0],[0,0],'g-')
		self.window.show_all()

	def main(self):
		source_id = gobject.idle_add(self.update)
		gtk.main()
Exemplo n.º 21
0
class AnalyzerGTK:

    def __init__(self):
        
        # Set the Glade file
        self.gladefile = "analyzer.glade"
        self.wTree = gtk.glade.XML(self.gladefile)

        # Get the Main Window and connect the "destroy" event
        self.window = self.wTree.get_widget("MainWindow")
        if (self.window):
            self.window.connect("destroy", gtk.main_quit)

        # Hook up the signals
        dic = { 
            "on_menuOpen_activate": self.menuOpen_activate,
            "on_menuQuit_activate": self.menuQuit_activate,
            "on_menuAbout_activate": self.menuAbout_activate,
            "on_MainWindow_destroy": gtk.main_quit,
            "on_NetworkList_row_activated": self.plotRows,
            
            "on_btnPlotAnalysis_clicked": self.plotAnalysis,
            "on_checkShowTemplate_clicked": self.showTemplate,
            "on_btnClearFilter_clicked": self.clearFilter,
            "on_tbClear_clicked": self.clearPlot
        }

        self.wTree.signal_autoconnect(dic)

        # Create a LogFile object to handle data
        self.logfile = LogFile()

        # Create an empty plot window for tuning curves
        self.figureDT = Figure(figsize=(6,4), dpi=72)   
        self.axisDT = self.figureDT.add_subplot(111)   
        self.axisDT.set_xlabel('Duration')   
        self.axisDT.set_ylabel('Mean Number of Spikes')   
        self.axisDT.grid(True)   
        self.canvasDT = FigureCanvasGTK(self.figureDT) # a gtk.DrawingArea   
        self.canvasDT.show()   
        self.graphviewDT = self.wTree.get_widget("vboxTuning")   
        self.graphviewDT.pack_end(self.canvasDT)
        self.maxSpikes = 1
        self.showTemplate = False

        # Create an empty plot window for analysis
        self.figureAN = Figure(dpi=72)
        self.axisAN = self.figureAN.add_subplot(111)
        self.canvasAN = FigureCanvasGTK(self.figureAN)
        self.canvasAN.show()
        self.graphviewAN = self.wTree.get_widget("vboxAnalysis")
        self.graphviewAN.pack_end(self.canvasAN)

        # Setup the analyze window
        self.cbXAxis = gtk.combo_box_new_text()
        self.cbYAxis = gtk.combo_box_new_text()
        self.cbZAxis = gtk.combo_box_new_text()
        self.cbXAxis.show()
        self.cbYAxis.show()
        self.cbZAxis.show()
        self.hboxAnalyze = self.wTree.get_widget("hboxAnalyze")
        labelX = gtk.Label("X-Axis")
        labelX.show()
        labelY = gtk.Label("Y-Axis")
        labelY.show()
        labelZ = gtk.Label("Z-Axis")
        labelZ.show()
        self.hboxAnalyze.pack_start(labelX)
        self.hboxAnalyze.pack_start(self.cbXAxis)
        self.hboxAnalyze.pack_start(labelY)
        self.hboxAnalyze.pack_start(self.cbYAxis)
        self.hboxAnalyze.pack_start(labelZ)
        self.hboxAnalyze.pack_start(self.cbZAxis)

    def plotAnalysis(self, widget):
        Xvar = self.cbXAxis.get_active_text()
        Yvar = self.cbYAxis.get_active_text()
        Zvar = self.cbZAxis.get_active_text()
        if Xvar == None or Yvar == None or Zvar == None:
            return


        if Zvar == "None":
            XvarIndex = self.logfile.params().index(Xvar)+1
            YvarIndex = self.logfile.params().index(Yvar)+1
            rowiter = self.treemodelsorted.get_iter_first()
            values = defaultdict(list)

            while rowiter != None:
                X = self.treemodelsorted.get_value(rowiter,XvarIndex)
                Y = self.treemodelsorted.get_value(rowiter,YvarIndex)
                values[float(X)].append(float(Y))
                rowiter = self.treemodelsorted.iter_next(rowiter)

            X = []
            Y = []
            for k in sorted(values.keys()):
                X.append(k)
                Y.append(mean(values[k]))

            self.axisAN.cla()        
            self.figureAN.clf()
            self.axisAN = self.figureAN.add_subplot(111)
            self.axisAN.plot(X,Y, 'k', linewidth=4)
            self.axisAN.set_xlabel(Xvar)   
            self.axisAN.set_ylabel(Yvar)   
            self.canvasAN.draw()

        else:
            XvarIndex = self.logfile.params().index(Xvar)+1
            YvarIndex = self.logfile.params().index(Yvar)+1
            ZvarIndex = self.logfile.params().index(Zvar)+1
            rowiter = self.treemodelsorted.get_iter_first()
            values = {}
            Ykeys = []

            while rowiter != None:
                X = self.treemodelsorted.get_value(rowiter,XvarIndex)
                Y = self.treemodelsorted.get_value(rowiter,YvarIndex)
                Z = self.treemodelsorted.get_value(rowiter,ZvarIndex)
                Ykeys.append(Y)
                values.setdefault(X,defaultdict(list))[Y].append(Z)
                rowiter = self.treemodelsorted.iter_next(rowiter)


            Ykeys = unique(Ykeys)
            XY = []
            for k in sorted(values.keys()):
                tmp = []
                for k2 in sorted(Ykeys):
                    if values[k].has_key(k2):
                        tmp.append(mean(values[k][k2]))
                    else:
                        tmp.append(0)
                XY.append(tmp)
            
            Z = array(XY)

            self.axisAN.cla()        
            self.figureAN.clf()
            self.axisAN = self.figureAN.add_subplot(111)
            im = NonUniformImage(self.axisAN, interpolation='nearest', extent=(min(values.keys()),max(values.keys()),min(Ykeys),max(Ykeys)))
            
            im.set_data(values.keys(), Ykeys, Z.transpose())
            self.axisAN.images.append(im)
            self.axisAN.set_xlim(min(values.keys()),max(values.keys()))
            self.axisAN.set_ylim(min(Ykeys),max(Ykeys))
            self.axisAN.set_xlabel(Xvar)   
            self.axisAN.set_ylabel(Yvar)   
            self.axisAN.set_title(Zvar)   
            self.figureAN.colorbar(im)
            self.canvasAN.draw()



    def showTemplate(self, widget):
        self.showTemplate = widget.get_active()

    def plotRows(self, widget, path, column):
        (model, pathlist) = self.treeview.get_selection().get_selected_rows()
        for p in pathlist:
            treeiter = self.treemodelsorted.get_iter(p)
            X = self.logfile.getdurs()
            Y = self.logfile.getresults(self.treemodelsorted.get_value(treeiter,0))
            tmp = Y[:]
            tmp.append(self.maxSpikes)
            self.maxSpikes = max(tmp)
            self.axisDT.plot(X, Y, linewidth=2)
            self.axisDT.set_ylim( (0, self.maxSpikes+0.1) )

        if self.showTemplate:
            Y = self.logfile.getresults(0)
            tmp = Y[:]
            tmp.append(self.maxSpikes)
            self.maxSpikes = max(tmp)
            self.axisDT.plot(X, Y, 'k', linewidth=3)
            self.axisDT.set_ylim( (0, self.maxSpikes+0.1) )


        self.canvasDT.draw()

    def clearPlot(self, widget):
        self.maxSpikes = 1
        self.axisDT.cla()
        self.axisDT.set_xlabel('Duration')   
        self.axisDT.set_ylabel('Mean Number of Spikes')   
        self.axisDT.grid(True)   
        self.canvasDT.draw()

    def clearFilter(self, widget):
        for i in range(len(self.filtercboxes)):
            self.filtercboxes[i].set_active(0)

    def applyFilter(self,model,iter):
        show = True
        for i in range(len(self.filtercboxes)):
            f = self.filtercboxes[i].get_active_text()
            show = show and (f == "All" or f == str(self.liststore.get_value(iter,i+1)))
        return show


    def updateFilter(self, widget):
        self.treemodelfilter = self.liststore.filter_new(root=None)
        self.treemodelfilter.set_visible_func(self.applyFilter)
        self.treemodelsorted = gtk.TreeModelSort(self.treemodelfilter)
        self.treeview.set_model(self.treemodelsorted)


    def menuOpen_activate(self, widget):
        chooser = gtk.FileChooserDialog(title="Open Log File", 
                                    action=gtk.FILE_CHOOSER_ACTION_OPEN,
                                    buttons=(gtk.STOCK_CANCEL,gtk.RESPONSE_CANCEL,
                                             gtk.STOCK_OPEN, gtk.RESPONSE_OK))
        response = chooser.run()
        if response == gtk.RESPONSE_OK:
            filename = chooser.get_filename()
            if self.logfile.open(filename):
                # Data file opened
                # Populate the ListStore for our table
                self.liststore = gtk.ListStore(int, *([float] *len(self.logfile.params())))
                self.treeview = self.wTree.get_widget("NetworkList")
                self.treeview.set_model(self.liststore)
                self.treeview.get_selection().set_mode(gtk.SELECTION_MULTIPLE)

                # Remove any old columns
                for c in self.treeview.get_columns():
                    self.treeview.remove_column(c)

                self.cbXAxis.get_model().clear()
                self.cbYAxis.get_model().clear()
                self.cbZAxis.get_model().clear()
                self.cbZAxis.append_text("None")

                # Add columns to filter table and fill analysis dropdowns
                self.filtertable = self.wTree.get_widget("FilterTable")
                self.filtertable.resize(len(self.logfile.params()), 2)
                textrenderer = gtk.CellRendererText()
                col = 1
                self.filtercboxes = []
                for p in self.logfile.params():
                    column = gtk.TreeViewColumn(p, textrenderer, text=col)
                    column.set_sizing(gtk.TREE_VIEW_COLUMN_AUTOSIZE)
                    column.set_resizable(True)
                    column.set_clickable(True)
                    column.set_sort_column_id(col)
                    self.treeview.append_column(column)
                    label = gtk.Label(p)
                    label.set_justify(gtk.JUSTIFY_RIGHT)
                    label.show()
                    cbox = gtk.combo_box_new_text()
                    self.filtercboxes.append(cbox)
                    self.filtercboxes[-1].show()
                    self.filtercboxes[-1].connect("changed", self.updateFilter)
                    self.filtertable.attach(label, 0, 1, col-1, col)
                    self.filtertable.attach(cbox, 1, 2, col-1, col)
                    self.cbXAxis.append_text(p)
                    self.cbYAxis.append_text(p)
                    self.cbZAxis.append_text(p)
                    col = col + 1

                # Add data to table
                for n in self.logfile.networkdefs():
                    itt = self.liststore.append(n)

                # Add data to columns
                tmp = []
                for i in range(len(self.logfile.params())):
                    tmp.append([]) 

                for n in self.logfile.networkdefs():
                    for i in range(1,len(self.logfile.params())+1):
                        tmp[i-1].append(n[i])


                for i in range(len(tmp)):
                    tmp[i] = unique(tmp[i])
                    tmp[i].sort()
                    self.filtercboxes[i].append_text("All")
                    self.filtercboxes[i].set_active(0)
                    for n in tmp[i]:
                        self.filtercboxes[i].append_text(str(n))

                # Setup the filtered sorted liststores
                self.treemodelfilter = self.liststore.filter_new(root=None)
                self.treemodelfilter.set_visible_func(self.applyFilter)
                self.treemodelsorted = gtk.TreeModelSort(self.treemodelfilter)
                self.treeview.set_model(self.treemodelsorted)

        # Destroy the file chooser
        chooser.destroy()

    def menuAbout_activate(self, widget):
        aboutDialog = self.wTree.get_widget("AboutDialog")
        response = aboutDialog.run()
        if response == gtk.RESPONSE_CANCEL:
            aboutDialog.hide()

    def menuQuit_activate(self, widget):
        gtk.main_quit()
class Graphtemp(object):
    def __init__(self,tipo):
        self.cuento = 0
        self.magico = 800
        self.app = None
        self.tipo = tipo
        self.data = np.array([])
        self.fechas = np.array([])
        self.caldera = np.array([])
        self.dpi = 100
        self.f = Figure((3.0, 3.0), dpi=self.dpi)
        self.f.subplots_adjust(hspace=1, left=.05, right = .99, top=.92   )
        self.a = self.f.add_subplot(111)
        self.a.set_axis_bgcolor('white')
        setp(self.a.get_xticklabels(), fontsize=8)
        setp(self.a.get_yticklabels(), fontsize=8)
        self.plot_data= self.a.plot(
            self.data,
            linewidth= 1.4,
            color= tipo.color,
            )[0]
        self.plot_data2 = self.a.plot(
            np.array([]),
            linestyle= "--",
            linewidth= 1.4,
            color= "g",
            )[0]
        self.plot_data3 = self.a.plot(
            np.array([]),
            linestyle= "--",
            linewidth= 1.4,
            color= "r",
            )[0]
        self.a.grid(True)
#        self.a.set_xlabel('Time')
        self.a.set_ylabel(tipo.formal)
        self.canvas = FigureCanvas(self.f)

    @inlineCallbacks
    def on_redraw_timer(self):
        from twisted.internet import reactor
        self.tiempo = time.time()
        if not self.app.is_stoped:
            # if paused do not add data, but still redraw the plot
            # (to respond to scale modifications, grid change, etc.)
            #
            #print "They have called me!"
            numero = self.tipo.actual
            if numero:
                self.data = np.append (self.data, float(numero))# .append(float()) acá le agrega le dato
                self.fechas = np.append(self.fechas, self.cuento)
                self.caldera = np.append(self.caldera, 40 if self.app.caldera.actual else 20)
                self.cuento += 1
                if self.fechas.size > self.magico:
                    self.data = np.delete(self.data, 0)
                    self.fechas = np.delete(self.fechas, 0)
                    self.caldera = np.delete(self.caldera, 0)
                xmax = self.fechas.max() if self.fechas.max() > self.magico else self.magico
                xmin = xmax - self.magico
                #ymin = round(self.data.min(), 0) - 1
                ymin = -.5
                ymax = 42#round(self.data.max(), 0) + 1
                self.a.set_xbound(lower=xmin, upper=xmax)
                self.a.set_ybound(lower=ymin, upper=ymax)
                self.plot_data2.set_xdata(np.array([0, xmax]))
                yield
                self.plot_data2.set_ydata(np.array([self.tipo.medio]*2))
            #self.fechas = np.append(self.fechas, datetime())
            yield
            setp(self.a.get_xticklabels(),
                visible=True)
            yield
            #print np.arange(self.data.size) == self.fechas
            self.plot_data.set_xdata(self.fechas)
            self.plot_data.set_ydata(self.data)
            yield
            self.plot_data3.set_ydata(self.caldera)
            self.plot_data3.set_xdata(self.fechas)
            yield
            d = Deferred()
            reactor.callLater(.1, d.callback, None)
            yield d
            self.canvas.draw()
            yield
        else:
            d = Deferred()
            reactor.callLater(.1, d.callback, None)
            yield d
        reactor.callLater(time.time() - self.tiempo -.1, self.on_redraw_timer)
Exemplo n.º 23
0
class Backend( backend.Backend ):

    def init(self):
        
        self.layer_to_axes = {}
        self.axes_to_layer = {}
        self.layers_cache = [] # copy of self.plot.layers
        self.layer_signals = {}
        
        self.line_caches = {}
        self.omaps = {}
        
        
    def connect(self):
        logger.debug("Opening matplotlib session.")        

        self.figure = Figure(dpi=100, facecolor="white")  # figsize=(5,4), dpi=100)        
        self.canvas = FigureCanvas(self.figure)
        self.canvas.show()

        self.line_caches = {}
        self.layer_to_axes.clear()
        self.axes_to_layer.clear()

        backend.Backend.connect(self)
        logger.debug("Init finished")


    def set(self, project,plot):
        backend.Backend.set(self, project, plot)
        if self.project is not None:
            # TODO: connect to notify::layers of Plot
            pass

    def disconnect(self):
        logger.debug("Closing matplotlib session.")

        if not self.canvas is None:
            self.canvas.destroy()
            self.canvas = None
        if not self.figure is None:
            self.figure = None
        
        backend.Backend.disconnect(self)

        

    #----------------------------------------------------------------------

    def arrange(self, rows=1, cols=1):

        layers = self.plot.layers
        n = len(layers)

        if n > (rows*cols):
            rows = int((rows*cols) / n) + 1
            cols = rows * n
            #raise ValueError("Not enough rows and cols for all layers!")

        self.figure.clear()
        self.figure.axes = []
        
        self.layer_to_axes.clear()
        self.axes_to_layer.clear()
        self.layers_cache = []

        for signal_list in self.layer_signals.itervalues():
            for signal in signal_list:
                Signals.disconnect(signal)
        self.layer_signals = {}
        
        j = 1
        for layer in layers:
            print "Setting up layer", layer
            axes = self.figure.add_subplot("%d%d%d" % (rows,cols,j))
            self.layer_to_axes[layer] = axes
            self.axes_to_layer[axes] = layer
            self.layers_cache.append(layer)

            print "Connecting to notify of ", layer
            self.layer_signals[layer] = \
              [Signals.connect(layer, 'notify', self.on_update_layer),
               Signals.connect(layer, 'notify::labels', self.on_update_labels)]

            j += 1


    def draw(self):
        self.check_connection()
        logger.debug("Matplotlib: draw()")                
             
        if self.plot.layers != self.layers_cache:
            self.arrange()

        self.omaps = {}
        for layer in self.plot.layers:
            self.update_layer(layer)
        self.draw_canvas()
        
    def draw_canvas(self):
        self.canvas.draw()        


    #----------------------------------------------------------------------
    # Layer
    #
    
    def on_update_layer(self, sender, updateinfo={}):
        # updateinfo is ignored
        self.update_layer(sender)
        self.canvas.draw()
    
    def update_layer(self, layer, updateinfo={}):
        # updateinfo is ignored

        self.omaps[layer] = {}
        self.line_caches[layer] = {}

        axes = self.layer_to_axes[layer]        
        axes.lines = []
        line_cache = self.line_caches[layer] = []        

        #:layer.lines:OK
        for line in layer.lines:
            self.update_line(line, layer, axes=axes)

        #:layer.axes
        for (key, axis) in layer.axes.iteritems():
            #:axis.label
            #:axis.scale
            #:axis.start
            #:axis.end
            label = axis.label
            scale = axis.scale
            start = axis.start
            end = axis.end

            logger.debug("start = %s; end = %s" % (start, end))
            
            if key == 'x':
                set_label = axes.set_xlabel
                set_scale = axes.set_xscale
                set_start = (lambda l: axes.set_xlim(xmin=l))
                set_end = (lambda l: axes.set_xlim(xmax=l))
            elif key == 'y':
                set_label = axes.set_ylabel
                set_scale = axes.set_yscale
                set_start = (lambda l: axes.set_ylim(ymin=l))
                set_end = (lambda l: axes.set_ylim(ymax=l))
            else:
                raise RuntimeError("Invalid axis key '%s'" % key)

            if label is not None: set_label(label)
            if scale is not None: set_scale(scale)
            if start is not None: set_start(start)
            if end is not None: set_end(end)
            
        #:layer.visible
        if layer.visible is False:
            return

        # TODO
        #:layer.title
        title = layer.title
        if title is not None:
            axes.set_title(title)

        #:layer.grid
        axes.grid(layer.grid)
                    
        #:layer.legend:OK
        self.update_legend(layer)

        #:layer.labels:OK
        axes.texts = []
        for label in layer.labels:
            self.update_textlabel(label, layer)

        
    #----------------------------------------------------------------------
    # Line
    #
    
    def update_line(self, line, layer, axes=None, updateinfo={}):
        # updateinfo is ignored
        
        axes = axes or self.layer_to_axes[layer]
        omap = self.omaps[layer]
        line_cache = self.line_caches[layer]

        data_to_plot = []

        #:line.visible
        if line.visible is False:
            if line in axes.lines:
                axes.lines.remove(line)
                line_cache.remove(line)
            omap[line] = None                    
            return

        ds = self.get_line_source(line)
        table = self.get_table(ds)
        cx, cy = self.get_column_indices(line)
        xdata, ydata = self.get_table_data(table, cx, cy)

        #:line.row_first
        #:line.row_last
        def limit_data(data, start, end):
            try:
                return data[start:end]
            except IndexError:
                backend.BackendError("Index range '%s'out of bounds!" % (start,end) )

        start, end = line.row_first, line.row_last
        xdata = limit_data(xdata, start, end)
        ydata = limit_data(ydata, start, end)


        #:line.style
        global linestyle_mappings
        style = linestyle_mappings[line.style]

        #:line.marker
        global linemarker_mappings
        marker = linemarker_mappings[line.marker]

        #:line.width:OK

        #:line.color
        N = len(layer.group_colors)
        index = layer.lines.index(line)
        color = line.rget('color', layer.group_colors[index%N])

        #--- PLOT LINE ---
        l, = axes.plot( xdata, ydata,
                        linewidth=line.width,
                        linestyle=style,
                        marker=marker,
                        color=color)

        line_cache.append(l)
        omap[line] = l        

        label = self.get_line_label(line, table=table, cy=cy)
        if label is not None:
            l.set_label(label)

    
    #----------------------------------------------------------------------
    # TextLabel
    #

    def on_update_labels(self, layer, updateinfo={}):
        # updateinfo is ignored

        # clear existing labels and their corresponding mappings
        axes = self.layer_to_axes[layer]        
        axes.texts = []
        for label in layer.labels:
            try:
                self.omaps[layer].pop(label)
            except KeyError:
                pass
            
        # create new labels
        for label in layer.labels:            
            self.update_textlabel(label, layer)

        self.canvas.draw()        
    
    def update_textlabel(self, label, layer, axes=None, updateinfo={}):
        # updateinfo is ignored
        
        axes = axes or self.layer_to_axes[layer]
        kwargs = self.label_kwargs(axes, label)
        if kwargs is None:
            return
        transform = kwargs.pop('transform')

        try:
            mpl_label = self.omaps[layer][label]
        except KeyError:
            mpl_label = Text(**kwargs)
            self.omaps[layer][label] = mpl_label
            axes.texts.append(mpl_label)
        else:
            mpl_label.update(kwargs)

        mpl_label.set_transform(transform)

        
    def label_kwargs(self, axes, label):
        if label.x is None or label.y is None:
            logger.info("Label coordinates contains empty value. Skipped.")
            return None

        if label.system == 0:
            transform = axes.transData
        elif label.system == 1:
            transform = axes.transAxes
        elif label.system == 2:
            transform = self.figure.transFigure
        elif label.system == 3:
            transform = matplotlib.transforms.identity_transform()

        return {'x': label.x, 'y': label.y, 'text' : label.text,
                'horizontalalignment': 'center',
                'verticalalignment' : 'center',
                'transform' : transform}


    #----------------------------------------------------------------------
    # Legend
    #
    
    def update_legend(self, layer, axes=None, updateinfo={}):
        # updateinfo is ignored
        axes = axes or self.layer_to_axes[layer]
        legend = layer.legend
        if legend is None:
            if axes.legend_ is not None:
                axes.legend_ = None
            self.omaps[layer][legend] = None
        else:
            kw = self.legend_kwargs(legend, layer)
            border = kw.pop('border')
            visible = kw.pop('visible')
            handles, labels = kw.pop('handles'), kw.pop('labels')
            _legend = axes.legend(handles, labels, **kw)
            self.omaps[layer][legend] = _legend
            _legend.draw_frame(border)
            _legend.set_visible(visible)

        self.omaps[layer][legend] = axes.legend_

    
    def legend_kwargs(self, legend, layer):
        """
        'border' must be popped and set via legend.draw_frame
        'visible' must be popped and set via set_visible
        """

        visible = legend.visible
                    
        #:legend.label:TODO
        label = legend.label
        if label is not None:
            pass

        #:legend.border:OK
        # (see below but keep it here!)
        border = legend.border

        #:legend.position TODO
        position = legend.position
        if position == 'at position':
            position = (legend.x, legend.y)

        # create legend entries from line labels
        line_cache = self.line_caches[layer]
        labels = [l.get_label() for l in line_cache]

        rv =  {'handles' : line_cache,
                'labels' : labels,
                'loc' : position,
                'border' : border,
                'visible' : visible}
        print "LEGEND"
        print rv
        return rv
Exemplo n.º 24
0
class GuiBankrollGraphViewer(threading.Thread):
    def __init__(self, settings, db, querylist, config, parent, debug=True):
        """Constructor for GraphViewer"""
        self.settings = settings
        self.db = db
        self.sql = querylist
        self.conf = config
        self.debug = debug
        self.parent = parent
        #print "start of GraphViewer constructor"
        self.db = Database.Database(self.conf, sql=self.sql)

        view = None
        filters_display = {
            "Heroes": True,
            "Sites": True,
            "Games": False,
            "Limits": False,
            "LimitSep": False,
            "LimitType": False,
            "Type": False,
            "UseType": 'tour',
            "Seats": False,
            "SeatSep": False,
            "Dates": True,
            "Groups": False,
            "Button1": True,
            "Button2": True
        }

        self.filters = Filters.Filters(self.db,
                                       self.conf,
                                       self.sql,
                                       display=filters_display)
        self.filters.registerButton1Name(_("Refresh _Graph"))
        self.filters.registerButton1Callback(self.generateGraph)
        self.filters.registerButton2Name(_("_Export to File"))
        self.filters.registerButton2Callback(self.exportGraph)

        numeric_const_pattern = r"""
            [-+]? # optional sign
            (?:
                (?: \d* \. \d+ ) # .1 .12 .123 etc 9.1 etc 98.1 etc
                |
                (?: \d+ \.? ) # 1. 12. 123. etc 1 12 123 etc
            )
            # followed by optional exponent part if desired
            (?: [Ee] [+-]? \d+ ) ?
            """
        self.rx = re.compile(numeric_const_pattern, re.VERBOSE)

        self.mainHBox = gtk.HBox(False, 0)
        self.mainHBox.show()

        self.leftPanelBox = self.filters.get_vbox()

        #add a button to modify transferts
        ButtonTransfert = gtk.Button(_("ButtonTransfert"))
        ButtonTransfert.set_label(_("_Modify Transferts"))
        ButtonTransfert.connect("clicked", self.transfertsWindow, "clicked")
        ButtonTransfert.set_sensitive(True)

        self.filters.mainVBox.pack_start(ButtonTransfert, False)
        ButtonTransfert.show()

        self.hpane = gtk.HPaned()
        self.hpane.pack1(self.leftPanelBox)
        self.mainHBox.add(self.hpane)
        # hierarchy:  self.mainHBox / self.hpane / self.graphBox / self.canvas / self.fig / self.ax

        self.graphBox = gtk.VBox(False, 0)
        self.graphBox.show()
        self.hpane.pack2(self.graphBox)
        self.hpane.show()

        self.fig = None
        #self.exportButton.set_sensitive(False)
        self.canvas = None

        #update the graph at entry (simulate a «Refresh Graph» click)
        gobject.GObject.emit(self.filters.Button1, "clicked")

        self.db.rollback()
        #endinit
    def get_vbox(self):
        """returns the vbox of this thread"""
        return self.mainHBox

    #end def get_vbox

    def clearGraphData(self):
        try:
            if self.canvas:
                self.graphBox.remove(self.canvas)
        except:
            pass

        if self.fig != None:
            self.fig.clear()
        self.fig = Figure(figsize=(5, 4), dpi=100)
        if self.canvas is not None:
            self.canvas.destroy()

        self.canvas = FigureCanvas(self.fig)  # a gtk.DrawingArea

    def generateGraph(self, widget, data):
        self.clearGraphData()

        sitenos = []
        playerids = []

        sites = self.filters.getSites()
        heroes = self.filters.getHeroes()
        siteids = self.filters.getSiteIds()

        # Which sites are selected?
        for site in sites:
            if sites[site] == True:
                sitenos.append(siteids[site])
                _hname = Charset.to_utf8(heroes[site])
                result = self.db.get_player_id(self.conf, site, _hname)
                if result is not None:
                    playerids.append(int(result))

        if not sitenos:
            #Should probably pop up here.
            print _("No sites selected - defaulting to PokerStars")
            self.db.rollback()
            return

        if not playerids:
            print _("No player ids found")
            self.db.rollback()
            return

        #Set graph properties
        self.ax = self.fig.add_subplot(111)

        #Get graph data from DB
        starttime = time()
        (green, dates, transfersAmount, transfersDate,
         transferType) = self.getData(playerids, sitenos)
        print _("Graph generated in: %s") % (time() - starttime)

        #Set axis labels and grid overlay properites
        self.ax.set_ylabel("$", fontsize=12)
        self.ax.grid(color='g', linestyle=':', linewidth=0.2)

        if green == None or green == []:
            self.ax.set_title(_("No Data for Player(s) Found"))
            green = ([
                0., 0., 0., 0., 500., 1000., 900., 800., 700., 600., 500.,
                400., 300., 200., 100., 0., 500., 1000., 1000., 1000., 1000.,
                1000., 1000., 1000., 1000., 1000., 1000., 1000., 1000., 1000.,
                875., 750., 625., 500., 375., 250., 125., 0., 0., 0., 0., 500.,
                1000., 900., 800., 700., 600., 500., 400., 300., 200., 100.,
                0., 500., 1000., 1000.
            ])
            red = ([
                0., 0., 0., 0., 500., 1000., 900., 800., 700., 600., 500.,
                400., 300., 200., 100., 0., 0., 0., 0., 0., 0., 0., 125., 250.,
                375., 500., 500., 500., 500., 500., 500., 500., 500., 500.,
                375., 250., 125., 0., 0., 0., 0., 500., 1000., 900., 800.,
                700., 600., 500., 400., 300., 200., 100., 0., 500., 1000.,
                1000.
            ])
            blue = ([
                0., 0., 0., 0., 500., 1000., 900., 800., 700., 600., 500.,
                400., 300., 200., 100., 0., 0., 0., 0., 0., 0., 0., 125., 250.,
                375., 500., 625., 750., 875., 1000., 875., 750., 625., 500.,
                375., 250., 125., 0., 0., 0., 0., 500., 1000., 900., 800.,
                700., 600., 500., 400., 300., 200., 100., 0., 500., 1000.,
                1000.
            ])

            self.ax.plot(green,
                         color='green',
                         label=_('Bankroll') + _('Profit') +
                         ': $%.2f' % green[-1])
            self.graphBox.add(self.canvas)
            self.canvas.show()
            self.canvas.draw()

            #TODO: Do something useful like alert user
        else:
            self.ax.set_title(_("Bankroll Results"))
            useDates = True

            #nothing to draw
            if (len(green) == 0):
                return
            #Get the dates of the action (transfert / cg hand / tourney)
            #if it has no date, get the most ancient date and assume it's its one
            if dates[0] is None:
                i = 1
                while i < len(dates) and type(dates[i]) is None:
                    i = i + 1
                if i == len(dates):
                    print "Wow wow wow : no dates in your whole database"
                    useDates = False
                else:
                    dates[0] = dates[i]

            #now, convert date to dateTime format
            if useDates:
                for i in range(0, len(dates)):
                    if dates[i] is None:
                        dates[i] = dates[i - 1]
                    #~else:
                    #~dates[i] = datetime.datetime.strptime(dates[i], "%Y-%m-%d %H:%M:%S")

            for i in range(0, len(green) - 1):
                beneficeSinceStart = green[i + 1] - self.totalTransfer(
                    dates[i + 1], transfersAmount, transfersDate)
                mycolor = self.color(transferType[i + 1], beneficeSinceStart)

                self.ax.plot([i, i + 1], [green[i], green[i + 1]],
                             color=mycolor)
                #show date and gain only 5 times on X axis
                if (i % (len(green) / 5) == 1):
                    #the gain since start at this time
                    if (mycolor == 'cyan'): mycolor = 'green'
                    self.ax.annotate('%.2f' % beneficeSinceStart,
                                     xy=(i, 0),
                                     color=mycolor,
                                     xycoords=('data', 'axes fraction'),
                                     xytext=(0, 18),
                                     textcoords='offset points',
                                     va='top',
                                     ha='left')

                    #and show the date too if enabled
                    if useDates:
                        dateMMDD = datetime.datetime.strptime(
                            dates[i], "%Y-%m-%d %H:%M:%S").strftime('%d/%m')
                        self.ax.annotate(dateMMDD,
                                         xy=(i, 0),
                                         xycoords=('data', 'axes fraction'),
                                         xytext=(0, -18),
                                         textcoords='offset points',
                                         va='top',
                                         ha='left')

            #plot the last one and show the top corner legend
            i = len(green) - 1

            bankroll = float(green[i])
            profit = bankroll
            if len(transfersAmount) > 0:
                profit -= transfersAmount[len(transfersAmount) - 1]

            self.ax.plot([i, i + 1], [green[i], green[i]],
                         color=self.color(transferType[i], beneficeSinceStart),
                         label=_('Bankroll') + ': \$%.2f' % bankroll + '\n' +
                         _('Profit') + ': \$%.2f' % profit)

            legend = self.ax.legend(loc='upper left',
                                    fancybox=True,
                                    shadow=True,
                                    prop=FontProperties(size='smaller'))
            legend.draggable(True)

            self.graphBox.add(self.canvas)
            self.canvas.show()
            self.canvas.draw()

    #end of def showClicked

    #return total cash from transfer until «date»
    def totalTransfer(self, date, amounts, transfersDate):
        #~print transferts
        if len(amounts) == 0 or (date < transfersDate[0]):
            return 0

        i = 0
        while (i < len(amounts) - 1 and date > transfersDate[i]):
            i = i + 1
        return amounts[i]

    def color(self, typ, gain):
        # 0:play, 1:transfert
        if typ == 1:
            return 'cyan'
        elif gain < 0:
            return 'red'
        else:
            return 'green'

    def getData(self, names, sites):
        print "DEBUG: args are :"
        print names
        print sites

        tmp = self.rightRequest('getAllPrintIdSite', names, sites)
        tmp2 = self.rightRequest('getAllTransfer', names, sites)

        print "DEBUG: sql query:"
        print tmp
        self.db.cursor.execute(tmp)
        #returns (HandId,Winnings,Costs,Profit)
        winnings = self.db.cursor.fetchall()

        self.db.cursor.execute(tmp2)
        transfers = self.db.cursor.fetchall()
        self.db.rollback()

        if len(winnings) == 0:
            return None

        green = map(lambda x: float(x[0]), winnings)
        dates = map(lambda x: x[1], winnings)
        typeOf = map(lambda x: x[2], winnings)
        transferAmounts = map(lambda x: x[0], transfers)
        transferDates = map(lambda x: x[1], transfers)

        #blue  = map(lambda x: float(x[1]) if x[2] == True  else 0.0, winnings)
        #red   = map(lambda x: float(x[1]) if x[2] == False else 0.0, winnings)
        greenline = cumsum(green)

        #blueline  = cumsum(blue)
        #redline   = cumsum(red)

        transferAmounts = cumsum(transferAmounts)
        return (greenline / 100., dates, transferAmounts, transferDates,
                typeOf)

    def exportGraph(self, widget, data):
        if self.fig is None:
            return  # Might want to disable export button until something has been generated.

        dia_chooser = gtk.FileChooserDialog(
            title=_("Please choose the directory you wish to export to:"),
            action=gtk.FILE_CHOOSER_ACTION_SELECT_FOLDER,
            buttons=(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, gtk.STOCK_OK,
                     gtk.RESPONSE_OK))
        dia_chooser.set_destroy_with_parent(True)
        dia_chooser.set_transient_for(self.parent)
        try:
            dia_chooser.set_filename(
                self.exportFile
            )  # use previously chosen export path as default
        except:
            pass

        response = dia_chooser.run()

        if response <> gtk.RESPONSE_OK:
            print _('Closed, no graph exported')
            dia_chooser.destroy()
            return

        # generate a unique filename for export
        now = datetime.now()
        now_formatted = now.strftime("%Y%m%d%H%M%S")
        self.exportFile = dia_chooser.get_filename(
        ) + "/fpdb" + now_formatted + ".png"
        dia_chooser.destroy()

        #print "DEBUG: self.exportFile = %s" %(self.exportFile)
        self.fig.savefig(self.exportFile, format="png")

        #display info box to confirm graph created
        diainfo = gtk.MessageDialog(parent=self.parent,
                                    flags=gtk.DIALOG_DESTROY_WITH_PARENT,
                                    type=gtk.MESSAGE_INFO,
                                    buttons=gtk.BUTTONS_OK,
                                    message_format=_("Graph created"))
        diainfo.format_secondary_text(self.exportFile)
        diainfo.run()
        diainfo.destroy()

    #end of def exportGraph
    def transfertsWindow(self, widget, data):
        #if the window is already launched, put it in front
        if not self.settings['global_lock'].acquire(
                wait=False, source="GuiBankrollGraphViewer"):
            return

        #create the window …
        #first, check if there is at least one player on database, else quit
        if (len(self.filters.getHeroes()) == 0):
            print "No site/hero found, abort"
            return

        self.transferWindow = gtk.Window(gtk.WINDOW_TOPLEVEL)
        self.transferWindow.set_title("Transferts Management")
        self.transferWindow.set_position(gtk.WIN_POS_CENTER)
        self.transferWindow.set_transient_for(self.parent)
        self.transferWindow.connect("destroy", self.release)
        vbox = gtk.VBox(False, 0)
        self.transferWindow.add(vbox)

        #####
        #####
        #«new transfert» part
        hboxAdd = gtk.HBox(True, 0)
        vbox.pack_start(hboxAdd)

        #calendar
        cal = gtk.Calendar()
        vboxSelection = gtk.VBox(False, 0)

        #hour selection
        hourLabel = gtk.Label(_('Select hour:'))
        hourLabel.set_alignment(xalign=0.0, yalign=0.5)

        hboxHour = gtk.HBox(False, 0)

        timeHourPicker = gtk.SpinButton(None, 0, 0)
        timeHourPicker.set_increments(1, 6)
        timeHourPicker.set_range(0, 23)
        timeHourPicker.set_value(datetime.datetime.now().hour)  # current hour

        timeMinPicker = gtk.SpinButton(None, 0, 0)
        timeMinPicker.set_increments(1, 10)
        timeMinPicker.set_range(0, 59)
        timeMinPicker.set_value(datetime.datetime.now().minute)  # current hour

        #site/hero selection
        IDLabel = gtk.Label(_('Site - hero:'))
        IDLabel.set_alignment(xalign=0.0, yalign=0.5)

        IDSelection = gtk.combo_box_new_text()

        for site, hero in self.filters.getHeroes().items():
            IDSelection.append_text(site + " - " + hero)

        IDSelection.set_active(0)
        #amount of virement
        amountLabel = gtk.Label(_('Tranfert amount ($):'))
        amountLabel.set_alignment(xalign=0.0, yalign=0.5)

        amountEntry = gtk.Entry()
        amountEntry.set_text('10.00')
        amountEntry.connect('changed', self.on_changed, 'changed')

        #button add
        buttonAdd = gtk.ToolButton(gtk.STOCK_ADD)
        buttonAdd.connect('clicked', self.newTransfer, 'clicked', cal,
                          timeHourPicker, timeMinPicker, IDSelection,
                          amountEntry)
        buttonAdd.connect('clicked', self.destroyWindow)

        hboxAdd.pack_start(cal, 0)
        hboxAdd.pack_start(vboxSelection, 0)
        vboxSelection.pack_start(hourLabel, 0)
        vboxSelection.pack_start(hboxHour, 0)
        hboxHour.pack_start(timeHourPicker, 0)
        hboxHour.pack_start(timeMinPicker, 0)
        vboxSelection.pack_start(IDLabel, 0)
        vboxSelection.pack_start(IDSelection, 0)
        vboxSelection.pack_start(amountLabel, 0)
        vboxSelection.pack_start(amountEntry, 0)
        vboxSelection.pack_start(buttonAdd, -1)

        #end of "new transfert" part
        #####
        ####

        ####
        #start of "delete transfert" part

        hboxDelete = gtk.HBox(False, 0)
        vbox.pack_start(hboxDelete)

        #tab to create
        vboxTab = gtk.VBox(False, 0)
        self.createTab(vboxTab)

        buttonDelete = gtk.ToolButton(gtk.STOCK_DELETE)
        buttonDelete.connect('clicked', self.deleteTransfer, 'clicked')

        hboxDelete.pack_start(vboxTab, 1)
        hboxDelete.pack_start(buttonDelete, 1)
        #end of "delete transfert" part
        ####

        self.transferWindow.show_all()
        return

    #end of def transfertsWindow
    def release(self, widget, data=None):
        self.settings['global_lock'].release()
        self.transferWindow.destroy()
        return

    def on_changed(self, widget, data):
        #~text = widget.get_text().strip()
        #~widget.set_text(''.join([i for i in text if i in '0123456789']))
        entry_text = widget.get_text()
        newtext = self.rx.findall(entry_text)
        if len(newtext):
            widget.set_text(newtext[0])
        else:
            widget.set_text("")

    def destroyWindow(self, widget):
        self.transferWindow.destroy()
        return

    def newTransfer(self, widget, data, cal, timeHourPicker, timeMinPicker,
                    IDSelection, amountEntry):
        year, month, day = cal.get_date()
        month = month + 1  # because gtk gives it between 0 and 11 ?!
        hour = timeHourPicker.get_value()
        minute = timeMinPicker.get_value()
        (site, separator,
         hero) = IDSelection.get_active_text().partition(' - ')
        transfer = float(amountEntry.get_text())

        now = datetime.datetime(year, month, day, int(hour), int(minute), 0)

        #get siteID from siteName (table "sites")
        self.db.cursor.execute('SELECT id from sites where name LIKE "' +
                               site + '"')
        siteID = self.db.cursor.fetchall()[0][0]
        self.db.rollback()

        #get heroID from heroName and siteID (table "players")
        self.db.cursor.execute('select id from players where name LIKE "' +
                               hero + '" and siteId = ' + str(siteID))
        heroID = self.db.cursor.fetchall()[0][0]
        self.db.rollback()

        #insert it in the table now
        query = "INSERT INTO BankrollsManagement(siteId, playerId, transfer, startTime) VALUES (?, ?, ?, ?)"
        #~print "DEBUG:\n%s" % query
        self.db.cursor.execute(query,
                               (siteID, heroID, int(transfer * 100), now))
        self.db.commit()
        self.db.rollback()

        #update the graph
        gobject.GObject.emit(self.filters.Button1, "clicked")

    def deleteTransfer(self, widget, data):
        #get the active line of the array
        selected = self.view.get_cursor()[0]

        #if no row selected, abort
        if selected is None:
            return
        #else, retrieve the line ( /!\ rowNumber != Id from the table ),
        rowNumber = selected[0]
        line = self.liststore[0][rowNumber]

        id = line[0]

        #then delete it from table and refresh graph
        self.db.cursor.execute('DELETE FROM BankrollsManagement WHERE id=' +
                               str(id))
        self.db.commit()
        self.db.rollback()

        #destroy the window
        self.destroyWindow(widget)
        gobject.GObject.emit(self.filters.Button1, "clicked")

    def createTab(self, vbox):
        cols_to_show = [
            ["id", False, _("ID"), 0.0, "%s", "str"],
            ["siteName", True, _("Site"), 0.0, "%s",
             "str"]  # true not allowed for this line (set in code)
            ,
            ["playerName", True,
             _("Name"), 0.8, "%s",
             "str"]  # true not allowed for this line (set in code)
            ,
            ["amount", True, _("Amount"), 0.0, "%0.2f", "str"],
            ["date", True, _("Date"), 0.0, "%s", "str"]
        ]

        self.liststore = []
        self.liststore.append(gtk.ListStore(*([str] * len(cols_to_show))))
        self.view = gtk.TreeView(model=self.liststore[0])

        self.view.set_grid_lines(gtk.TREE_VIEW_GRID_LINES_BOTH)
        #vbox.pack_start(view, expand=False, padding=3)
        vbox.add(self.view)
        textcell = gtk.CellRendererText()
        textcell50 = gtk.CellRendererText()
        textcell50.set_property('xalign', 0.5)
        numcell = gtk.CellRendererText()
        numcell.set_property('xalign', 1.0)

        listcols = []
        listcols.append([])
        # Create header row   eg column: ("game",     True, "Game",     0.0, "%s")
        for i, col in enumerate(cols_to_show):
            listcols[0].append(gtk.TreeViewColumn(col[_COL_HEADING]))

            self.view.append_column(listcols[0][i])
            if col[_COL_FORMAT] == '%s':
                if col[_COL_XALIGN] == 0.0:
                    listcols[0][i].pack_start(textcell, expand=True)
                    listcols[0][i].add_attribute(textcell, 'text', i)
                    cellrend = textcell
                else:
                    listcols[0][i].pack_start(textcell50, expand=True)
                    listcols[0][i].add_attribute(textcell50, 'text', i)
                    cellrend = textcell50
                listcols[0][i].set_expand(True)
            else:
                listcols[0][i].pack_start(numcell, expand=True)
                listcols[0][i].add_attribute(numcell, 'text', i)
                listcols[0][i].set_expand(True)
                cellrend = numcell

        query = self.sql.query['getAllTransferInformations']

        #~print "DEBUG:\n%s" % query
        self.db.cursor.execute(query)

        result = self.db.cursor.fetchall()
        #~print "result of the big query in addGrid:",result
        colnames = [desc[0] for desc in self.db.cursor.description]

        #~for i in range(0, len(tab))
        rows = len(result)  # +1 for title row
        counter = 0
        row = 0
        sqlrow = 0
        while sqlrow < rows:
            treerow = []
            for col, column in enumerate(cols_to_show):
                if column[_COL_ALIAS] in colnames:
                    if column[_COL_ALIAS] == 'amount':
                        #convert $ cents to $
                        value = result[sqlrow][colnames.index(
                            column[_COL_ALIAS])] / 100.
                    else:
                        value = result[sqlrow][colnames.index(
                            column[_COL_ALIAS])]
                else:
                    value = 111

                if value != None and value != -999:
                    treerow.append(column[_COL_FORMAT] % value)
                else:
                    treerow.append(' ')
            #print "addGrid, just before end of big for. grid:",grid,"treerow:",treerow
            iter = self.liststore[0].append(treerow)
            sqlrow += 1
            row += 1
        vbox.show_all()

    def rightRequest(self, request, names, sites):
        tmp = self.sql.query[request]
        print "DEBUG: getData. :"
        start_date, end_date = self.filters.getDates()

        #Buggered if I can find a way to do this 'nicely' take a list of integers and longs
        # and turn it into a tuple readale by sql.
        # [5L] into (5) not (5,) and [5L, 2829L] into (5, 2829)
        nametest = str(tuple(names))
        sitetest = str(tuple(sites))

        #Must be a nicer way to deal with tuples of size 1 ie. (2,) - which makes sql barf
        tmp = tmp.replace("<player_test>", nametest)
        tmp = tmp.replace("<site_test>", sitetest)
        tmp = tmp.replace("<startdate_test>", start_date)
        tmp = tmp.replace("<enddate_test>", end_date)
        tmp = tmp.replace(",)", ")")

        return tmp
Exemplo n.º 25
0
class GuiGraphViewer(threading.Thread):
    def __init__(self, querylist, config, parent, debug=True):
        """Constructor for GraphViewer"""
        self.sql = querylist
        self.conf = config
        self.debug = debug
        self.parent = parent
        #print "start of GraphViewer constructor"
        self.db = Database.Database(self.conf, sql=self.sql)

        filters_display = {
            "Heroes": True,
            "Sites": True,
            "Games": True,
            "Currencies": True,
            "Limits": True,
            "LimitSep": True,
            "LimitType": True,
            "Type": False,
            "UseType": 'ring',
            "Seats": False,
            "SeatSep": False,
            "Dates": True,
            "GraphOps": True,
            "Groups": False,
            "Button1": True,
            "Button2": True
        }

        self.filters = Filters.Filters(self.db,
                                       self.conf,
                                       self.sql,
                                       display=filters_display)
        self.filters.registerButton1Name(_("Refresh _Graph"))
        self.filters.registerButton1Callback(self.generateGraph)
        self.filters.registerButton2Name(_("_Export to File"))
        self.filters.registerButton2Callback(self.exportGraph)

        self.mainHBox = gtk.HBox(False, 0)
        self.mainHBox.show()

        self.leftPanelBox = self.filters.get_vbox()

        self.hpane = gtk.HPaned()
        self.hpane.pack1(self.leftPanelBox)
        self.mainHBox.add(self.hpane)
        # hierarchy:  self.mainHBox / self.hpane / self.graphBox / self.canvas / self.fig / self.ax

        self.graphBox = gtk.VBox(False, 0)
        self.graphBox.show()
        self.hpane.pack2(self.graphBox)
        self.hpane.show()

        self.fig = None
        #self.exportButton.set_sensitive(False)
        self.canvas = None

        self.exportFile = None

        self.db.rollback()

    def get_vbox(self):
        """returns the vbox of this thread"""
        return self.mainHBox

    #end def get_vbox

    def clearGraphData(self):
        try:
            if self.canvas:
                self.graphBox.remove(self.canvas)
        except:
            pass

        if self.fig != None:
            self.fig.clear()
        self.fig = Figure(figsize=(5, 4), dpi=100)
        if self.canvas is not None:
            self.canvas.destroy()

        self.canvas = FigureCanvas(self.fig)  # a gtk.DrawingArea

    def generateGraph(self, widget, data):
        self.clearGraphData()

        sitenos = []
        playerids = []

        sites = self.filters.getSites()
        heroes = self.filters.getHeroes()
        siteids = self.filters.getSiteIds()
        limits = self.filters.getLimits()
        games = self.filters.getGames()
        currencies = self.filters.getCurrencies()
        graphops = self.filters.getGraphOps()
        names = ""

        for i in ('show', 'none'):
            if i in limits:
                limits.remove(i)
        # Which sites are selected?
        for site in sites:
            if sites[site] == True:
                sitenos.append(siteids[site])
                _hname = Charset.to_utf8(heroes[site])
                result = self.db.get_player_id(self.conf, site, _hname)
                if result is not None:
                    playerids.append(int(result))
                    names = names + "\n" + _hname + " on " + site

        if not sitenos:
            #Should probably pop up here.
            print _("No sites selected - defaulting to PokerStars")
            self.db.rollback()
            return

        if not playerids:
            print _("No player ids found")
            self.db.rollback()
            return

        if not limits:
            print _("No limits found")
            self.db.rollback()
            return

        #Set graph properties
        self.ax = self.fig.add_subplot(111)

        #Get graph data from DB
        starttime = time()
        (green, blue, red,
         orange) = self.getRingProfitGraph(playerids, sitenos, limits, games,
                                           currencies, graphops['dspin'])
        print _("Graph generated in: %s") % (time() - starttime)

        #Set axis labels and grid overlay properites
        self.ax.set_xlabel(_("Hands"))
        # SET LABEL FOR X AXIS
        self.ax.set_ylabel(graphops['dspin'])
        self.ax.grid(color='g', linestyle=':', linewidth=0.2)
        if green == None or green == []:
            self.ax.set_title(_("No Data for Player(s) Found"))
            green = ([
                0., 0., 0., 0., 500., 1000., 900., 800., 700., 600., 500.,
                400., 300., 200., 100., 0., 500., 1000., 1000., 1000., 1000.,
                1000., 1000., 1000., 1000., 1000., 1000., 1000., 1000., 1000.,
                875., 750., 625., 500., 375., 250., 125., 0., 0., 0., 0., 500.,
                1000., 900., 800., 700., 600., 500., 400., 300., 200., 100.,
                0., 500., 1000., 1000.
            ])
            red = ([
                0., 0., 0., 0., 500., 1000., 900., 800., 700., 600., 500.,
                400., 300., 200., 100., 0., 0., 0., 0., 0., 0., 0., 125., 250.,
                375., 500., 500., 500., 500., 500., 500., 500., 500., 500.,
                375., 250., 125., 0., 0., 0., 0., 500., 1000., 900., 800.,
                700., 600., 500., 400., 300., 200., 100., 0., 500., 1000.,
                1000.
            ])
            blue = ([
                0., 0., 0., 0., 500., 1000., 900., 800., 700., 600., 500.,
                400., 300., 200., 100., 0., 0., 0., 0., 0., 0., 0., 125., 250.,
                375., 500., 625., 750., 875., 1000., 875., 750., 625., 500.,
                375., 250., 125., 0., 0., 0., 0., 500., 1000., 900., 800.,
                700., 600., 500., 400., 300., 200., 100., 0., 500., 1000.,
                1000.
            ])

            self.ax.plot(green,
                         color='green',
                         label=_('Hands') + ': %d\n' % len(green) +
                         _('Profit') + ': %.2f' % green[-1])
            self.ax.plot(blue,
                         color='blue',
                         label=_('Showdown') + ': $%.2f' % (blue[-1]))
            self.ax.plot(red,
                         color='red',
                         label=_('Non-showdown') + ': $%.2f' % (red[-1]))
            self.graphBox.add(self.canvas)
            self.canvas.show()
            self.canvas.draw()
        else:
            self.ax.set_title((_("Profit graph for ring games") + names))

            #Draw plot
            self.ax.plot(green,
                         color='green',
                         label=_('Hands') + ': %d\n' % len(green) +
                         _('Profit') + ': (%s): %.2f' %
                         (graphops['dspin'], green[-1]))
            if graphops['showdown'] == 'ON':
                self.ax.plot(blue,
                             color='blue',
                             label=_('Showdown') + ' (%s): %.2f' %
                             (graphops['dspin'], blue[-1]))
            if graphops['nonshowdown'] == 'ON':
                self.ax.plot(red,
                             color='red',
                             label=_('Non-showdown') + ' (%s): %.2f' %
                             (graphops['dspin'], red[-1]))
            if graphops['ev'] == 'ON':
                self.ax.plot(orange,
                             color='orange',
                             label=_('All-in EV') + ' (%s): %.2f' %
                             (graphops['dspin'], orange[-1]))

            if sys.version[0:3] == '2.5':
                self.ax.legend(loc='upper left',
                               shadow=True,
                               prop=FontProperties(size='smaller'))
            else:
                self.ax.legend(loc='upper left',
                               fancybox=True,
                               shadow=True,
                               prop=FontProperties(size='smaller'))

            self.graphBox.add(self.canvas)
            self.canvas.show()
            self.canvas.draw()
            #self.exportButton.set_sensitive(True)

    #end of def showClicked

    def getRingProfitGraph(self, names, sites, limits, games, currencies,
                           units):
        #        tmp = self.sql.query['getRingProfitAllHandsPlayerIdSite']
        #        print "DEBUG: getRingProfitGraph"

        if units == '$':
            tmp = self.sql.query['getRingProfitAllHandsPlayerIdSiteInDollars']
        elif units == 'BB':
            tmp = self.sql.query['getRingProfitAllHandsPlayerIdSiteInBB']

        start_date, end_date = self.filters.getDates()

        #Buggered if I can find a way to do this 'nicely' take a list of integers and longs
        # and turn it into a tuple readale by sql.
        # [5L] into (5) not (5,) and [5L, 2829L] into (5, 2829)
        nametest = str(tuple(names))
        sitetest = str(tuple(sites))
        #nametest = nametest.replace("L", "")

        q = []
        for m in self.filters.display.items():
            if m[0] == 'Games' and m[1]:
                for n in games:
                    if games[n]:
                        q.append(n)
                if len(q) > 0:
                    gametest = str(tuple(q))
                    gametest = gametest.replace("L", "")
                    gametest = gametest.replace(",)", ")")
                    gametest = gametest.replace("u'", "'")
                    gametest = "and gt.category in %s" % gametest
                else:
                    gametest = "and gt.category IS NULL"
        tmp = tmp.replace("<game_test>", gametest)

        limittest = self.filters.get_limits_where_clause(limits)

        q = []
        for n in currencies:
            if currencies[n]:
                q.append(n)
        currencytest = str(tuple(q))
        currencytest = currencytest.replace(",)", ")")
        currencytest = currencytest.replace("u'", "'")
        currencytest = "AND gt.currency in %s" % currencytest

        if type == 'ring':
            limittest = limittest + " and gt.type = 'ring' "
        elif type == 'tour':
            limittest = limittest + " and gt.type = 'tour' "

        #Must be a nicer way to deal with tuples of size 1 ie. (2,) - which makes sql barf
        tmp = tmp.replace("<player_test>", nametest)
        tmp = tmp.replace("<site_test>", sitetest)
        tmp = tmp.replace("<startdate_test>", start_date)
        tmp = tmp.replace("<enddate_test>", end_date)
        tmp = tmp.replace("<limit_test>", limittest)
        tmp = tmp.replace("<currency_test>", currencytest)
        tmp = tmp.replace(",)", ")")

        #print "DEBUG: sql query:"
        #print tmp
        self.db.cursor.execute(tmp)
        #returns (HandId,Winnings,Costs,Profit)
        winnings = self.db.cursor.fetchall()
        self.db.rollback()

        if len(winnings) == 0:
            return (None, None, None)

        green = map(lambda x: float(x[1]), winnings)
        blue = map(lambda x: float(x[1]) if x[2] == True else 0.0, winnings)
        red = map(lambda x: float(x[1]) if x[2] == False else 0.0, winnings)
        orange = map(lambda x: float(x[3]), winnings)
        greenline = cumsum(green)
        blueline = cumsum(blue)
        redline = cumsum(red)
        orangeline = cumsum(orange)
        return (greenline / 100, blueline / 100, redline / 100,
                orangeline / 100)
        #end of def getRingProfitGraph

    def exportGraph(self, widget, data):
        if self.fig is None:
            return  # Might want to disable export button until something has been generated.

        png_filter = gtk.FileFilter()
        png_filter.add_pattern('*.png')
        dia_chooser = gtk.FileChooserDialog(
            title=_("Please choose the directory you wish to export to:"),
            action=gtk.FILE_CHOOSER_ACTION_SAVE,
            buttons=(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, gtk.STOCK_OK,
                     gtk.RESPONSE_OK))
        dia_chooser.set_filter(png_filter)
        dia_chooser.set_destroy_with_parent(True)
        dia_chooser.set_transient_for(self.parent)
        if self.exportFile is not None:
            dia_chooser.set_filename(
                self.exportFile
            )  # use previously chosen export path as default
        else:
            dia_chooser.set_current_name('fpdbgraph.png')

        response = dia_chooser.run()

        if response <> gtk.RESPONSE_OK:
            print _('Closed, no graph exported')
            dia_chooser.destroy()
            return

        self.exportFile = dia_chooser.get_filename()
        dia_chooser.destroy()

        self.fig.savefig(self.exportFile, format="png")

        # Display info box to confirm graph created.
        diainfo = gtk.MessageDialog(parent=self.parent,
                                    flags=gtk.DIALOG_DESTROY_WITH_PARENT,
                                    type=gtk.MESSAGE_INFO,
                                    buttons=gtk.BUTTONS_OK,
                                    message_format=_("Graph created"))
        diainfo.format_secondary_text(self.exportFile)
        diainfo.run()
        diainfo.destroy()
Exemplo n.º 26
0
class GuiGraphViewer (threading.Thread):

    def __init__(self, querylist, config, debug=True):
        """Constructor for GraphViewer"""
        self.sql = querylist
        self.conf = config
        self.debug = debug
        #print "start of GraphViewer constructor"
        self.db = Database.Database(self.conf, sql=self.sql)


        filters_display = { "Heroes"    : True,
                            "Sites"     : True,
                            "Games"     : True,
                            "Limits"    : True,
                            "LimitSep"  : True,
                            "LimitType" : True,
                            "Type"      : False,
                            "UseType"   : 'ring',
                            "Seats"     : False,
                            "SeatSep"   : False,
                            "Dates"     : True,
                            "Groups"    : False,
                            "Button1"   : True,
                            "Button2"   : True
                          }

        self.filters = Filters.Filters(self.db, self.conf, self.sql, display = filters_display)
        self.filters.registerButton1Name("Refresh _Graph")
        self.filters.registerButton1Callback(self.generateGraph)
        self.filters.registerButton2Name("_Export to File")
        self.filters.registerButton2Callback(self.exportGraph)

        self.mainHBox = gtk.HBox(False, 0)
        self.mainHBox.show()

        self.leftPanelBox = self.filters.get_vbox()

        self.hpane = gtk.HPaned()
        self.hpane.pack1(self.leftPanelBox)
        self.mainHBox.add(self.hpane)
        # hierarchy:  self.mainHBox / self.hpane / self.graphBox / self.canvas / self.fig / self.ax

        self.graphBox = gtk.VBox(False, 0)
        self.graphBox.show()
        self.hpane.pack2(self.graphBox)
        self.hpane.show()

        self.fig = None
        #self.exportButton.set_sensitive(False)
        self.canvas = None


        self.db.rollback()

    def get_vbox(self):
        """returns the vbox of this thread"""
        return self.mainHBox
    #end def get_vbox

    def clearGraphData(self):

        try:
            try:
                if self.canvas:
                    self.graphBox.remove(self.canvas)
            except:
                pass

            if self.fig != None:
                self.fig.clear()
            self.fig = Figure(figsize=(5,4), dpi=100)
            if self.canvas is not None:
                self.canvas.destroy()

            self.canvas = FigureCanvas(self.fig)  # a gtk.DrawingArea
        except:
            err = traceback.extract_tb(sys.exc_info()[2])[-1]
            print "***Error: "+err[2]+"("+str(err[1])+"): "+str(sys.exc_info()[1])
            raise

    def generateGraph(self, widget, data):
        try:
            self.clearGraphData()

            sitenos = []
            playerids = []

            sites   = self.filters.getSites()
            heroes  = self.filters.getHeroes()
            siteids = self.filters.getSiteIds()
            limits  = self.filters.getLimits()
            games   = self.filters.getGames()
            
            for i in ('show', 'none'):
                if i in limits:
                    limits.remove(i)
            # Which sites are selected?
            for site in sites:
                if sites[site] == True:
                    sitenos.append(siteids[site])
                    _hname = Charset.to_utf8(heroes[site])
                    result = self.db.get_player_id(self.conf, site, _hname)
                    if result is not None:
                        playerids.append(int(result))

            if not sitenos:
                #Should probably pop up here.
                print "No sites selected - defaulting to PokerStars"
                self.db.rollback()
                return

            if not playerids:
                print "No player ids found"
                self.db.rollback()
                return

            if not limits:
                print "No limits found"
                self.db.rollback()
                return

            #Set graph properties
            self.ax = self.fig.add_subplot(111)

            #Get graph data from DB
            starttime = time()
            (green, blue, red) = self.getRingProfitGraph(playerids, sitenos, limits, games)
            print "Graph generated in: %s" %(time() - starttime)


            #Set axis labels and grid overlay properites
            self.ax.set_xlabel("Hands", fontsize = 12)
            self.ax.set_ylabel("$", fontsize = 12)
            self.ax.grid(color='g', linestyle=':', linewidth=0.2)
            if green == None or green == []:
                self.ax.set_title("No Data for Player(s) Found")
                green = ([    0.,     0.,     0.,     0.,   500.,  1000.,   900.,   800.,
                            700.,   600.,   500.,   400.,   300.,   200.,   100.,     0.,
                            500.,  1000.,  1000.,  1000.,  1000.,  1000.,  1000.,  1000.,
                            1000., 1000.,  1000.,  1000.,  1000.,  1000.,   875.,   750.,
                            625.,   500.,   375.,   250.,   125.,     0.,     0.,     0.,
                            0.,   500.,  1000.,   900.,   800.,   700.,   600.,   500.,
                            400.,   300.,   200.,   100.,     0.,   500.,  1000.,  1000.])
                red   =  ([    0.,     0.,     0.,     0.,   500.,  1000.,   900.,   800.,
                            700.,   600.,   500.,   400.,   300.,   200.,   100.,     0.,
                            0.,   0.,     0.,     0.,     0.,     0.,   125.,   250.,
                            375.,   500.,   500.,   500.,   500.,   500.,   500.,   500.,
                            500.,   500.,   375.,   250.,   125.,     0.,     0.,     0.,
                            0.,   500.,  1000.,   900.,   800.,   700.,   600.,   500.,
                            400.,   300.,   200.,   100.,     0.,   500.,  1000.,  1000.])
                blue =    ([    0.,     0.,     0.,     0.,   500.,  1000.,   900.,   800.,
                              700.,   600.,   500.,   400.,   300.,   200.,   100.,     0.,
                              0.,     0.,     0.,     0.,     0.,     0.,   125.,   250.,
                              375.,   500.,   625.,   750.,   875.,  1000.,   875.,   750.,
                              625.,   500.,   375.,   250.,   125.,     0.,     0.,     0.,
                            0.,   500.,  1000.,   900.,   800.,   700.,   600.,   500.,
                            400.,   300.,   200.,   100.,     0.,   500.,  1000.,  1000.])

                self.ax.plot(green, color='green', label='Hands: %d\nProfit: $%.2f' %(len(green), green[-1]))
                self.ax.plot(blue, color='blue', label='Showdown: $%.2f' %(blue[-1]))
                self.ax.plot(red, color='red', label='Non-showdown: $%.2f' %(red[-1]))
                self.graphBox.add(self.canvas)
                self.canvas.show()
                self.canvas.draw()

                #TODO: Do something useful like alert user
                #print "No hands returned by graph query"
            else:
                self.ax.set_title("Profit graph for ring games")
                #text = "Profit: $%.2f\nTotal Hands: %d" %(green[-1], len(green))
                #self.ax.annotate(text,
                #                 xy=(10, -10),
                #                 xycoords='axes points',
                #                 horizontalalignment='left', verticalalignment='top',
                #                 fontsize=10)

                #Draw plot
                self.ax.plot(green, color='green', label='Hands: %d\nProfit: $%.2f' %(len(green), green[-1]))
                self.ax.plot(blue, color='blue', label='Showdown: $%.2f' %(blue[-1]))
                self.ax.plot(red, color='red', label='Non-showdown: $%.2f' %(red[-1]))
                if sys.version[0:3] == '2.5':
                    self.ax.legend(loc='best', shadow=True, prop=FontProperties(size='smaller'))
                else:
                    self.ax.legend(loc='best', fancybox=True, shadow=True, prop=FontProperties(size='smaller'))

                self.graphBox.add(self.canvas)
                self.canvas.show()
                self.canvas.draw()
                #self.exportButton.set_sensitive(True)
        except:
            err = traceback.extract_tb(sys.exc_info()[2])[-1]
            print "***Error: "+err[2]+"("+str(err[1])+"): "+str(sys.exc_info()[1])

    #end of def showClicked

    def getRingProfitGraph(self, names, sites, limits, games):
        tmp = self.sql.query['getRingProfitAllHandsPlayerIdSite']
#        print "DEBUG: getRingProfitGraph"
        start_date, end_date = self.filters.getDates()

        #Buggered if I can find a way to do this 'nicely' take a list of integers and longs
        # and turn it into a tuple readale by sql.
        # [5L] into (5) not (5,) and [5L, 2829L] into (5, 2829)
        nametest = str(tuple(names))
        sitetest = str(tuple(sites))
        #nametest = nametest.replace("L", "")

        q = []
        for m in self.filters.display.items():
            if m[0] == 'Games' and m[1]:
                for n in games:
                    if games[n]:
                        q.append(n)
                if len(q) > 0:
                    gametest = str(tuple(q))
                    gametest = gametest.replace("L", "")
                    gametest = gametest.replace(",)",")")
                    gametest = gametest.replace("u'","'")
                    gametest = "and gt.category in %s" % gametest
                else:
                    gametest = "and gt.category IS NULL"
        tmp = tmp.replace("<game_test>", gametest)
        
        lims = [int(x) for x in limits if x.isdigit()]
        potlims = [int(x[0:-2]) for x in limits if len(x) > 2 and x[-2:] == 'pl']
        nolims = [int(x[0:-2]) for x in limits if len(x) > 2 and x[-2:] == 'nl']
        limittest = "and ( (gt.limitType = 'fl' and gt.bigBlind in "
                 # and ( (limit and bb in()) or (nolimit and bb in ()) )
        if lims:
            blindtest = str(tuple(lims))
            blindtest = blindtest.replace("L", "")
            blindtest = blindtest.replace(",)",")")
            limittest = limittest + blindtest + ' ) '
        else:
            limittest = limittest + '(-1) ) '
        limittest = limittest + " or (gt.limitType = 'pl' and gt.bigBlind in "
        if potlims:
            blindtest = str(tuple(potlims))
            blindtest = blindtest.replace("L", "")
            blindtest = blindtest.replace(",)",")")
            limittest = limittest + blindtest + ' ) '
        else:
            limittest = limittest + '(-1) ) '
        limittest = limittest + " or (gt.limitType = 'nl' and gt.bigBlind in "
        if nolims:
            blindtest = str(tuple(nolims))
            blindtest = blindtest.replace("L", "")
            blindtest = blindtest.replace(",)",")")
            limittest = limittest + blindtest + ' ) )'
        else:
            limittest = limittest + '(-1) ) )'

        if type == 'ring':
            limittest = limittest + " and gt.type = 'ring' "
        elif type == 'tour':
            limittest = limittest + " and gt.type = 'tour' "

        #Must be a nicer way to deal with tuples of size 1 ie. (2,) - which makes sql barf
        tmp = tmp.replace("<player_test>", nametest)
        tmp = tmp.replace("<site_test>", sitetest)
        tmp = tmp.replace("<startdate_test>", start_date)
        tmp = tmp.replace("<enddate_test>", end_date)
        tmp = tmp.replace("<limit_test>", limittest)
        tmp = tmp.replace(",)", ")")

        #print "DEBUG: sql query:"
        #print tmp
        self.db.cursor.execute(tmp)
        #returns (HandId,Winnings,Costs,Profit)
        winnings = self.db.cursor.fetchall()
        self.db.rollback()

        if len(winnings) == 0:
            return (None, None, None)

        green = map(lambda x:float(x[1]), winnings)
        blue  = map(lambda x: float(x[1]) if x[2] == True  else 0.0, winnings)
        red   = map(lambda x: float(x[1]) if x[2] == False else 0.0, winnings)
        greenline = cumsum(green)
        blueline  = cumsum(blue)
        redline   = cumsum(red)
        return (greenline/100, blueline/100, redline/100)
        #end of def getRingProfitGraph

    def exportGraph (self, widget, data):
        if self.fig is None:
            return # Might want to disable export button until something has been generated.
        dia_chooser = gtk.FileChooserDialog(title="Please choose the directory you wish to export to:",
                                            action=gtk.FILE_CHOOSER_ACTION_OPEN,
                                            buttons=(gtk.STOCK_CANCEL,gtk.RESPONSE_CANCEL,gtk.STOCK_OPEN,gtk.RESPONSE_OK))
        #TODO: Suggest path and filename to start with

        response = dia_chooser.run()
        if response == gtk.RESPONSE_OK:
            self.exportDir = dia_chooser.get_filename()
            print "DEBUG: self.exportDir = %s" %(self.exportDir)
        elif response == gtk.RESPONSE_CANCEL:
            print 'Closed, no graph exported'
        dia_chooser.destroy()
        #TODO: Check to see if file exists
        #NOTE: Dangerous - will happily overwrite any file we have write access too
        #TODO: This asks for a directory but will take a filename and overwrite it.
        self.fig.savefig(self.exportDir, format="png")
Exemplo n.º 27
0
class GuiSessionViewer:
    def __init__(self, config, querylist, mainwin, owner, debug=True):
        self.debug = debug
        self.conf = config
        self.sql = querylist
        self.window = mainwin
        self.owner = owner

        self.liststore = None

        self.MYSQL_INNODB   = 2
        self.PGSQL          = 3
        self.SQLITE         = 4

        self.fig = None
        self.canvas = None
        self.ax = None
        self.graphBox = None
        
        # create new db connection to avoid conflicts with other threads
        self.db = Database.Database(self.conf, sql=self.sql)
        self.cursor = self.db.cursor

        settings = {}
        settings.update(self.conf.get_db_parameters())
        settings.update(self.conf.get_import_parameters())
        settings.update(self.conf.get_default_paths())

        # text used on screen stored here so that it can be configured
        self.filterText = {'handhead':_('Hand Breakdown for all levels listed above')}

        filters_display = { "Heroes"    : True,
                            "Sites"     : True,
                            "Games"     : True,
                            "Currencies": True,
                            "Limits"    : True,
                            "LimitSep"  : True,
                            "LimitType" : True,
                            "Type"      : False,
                            "Seats"     : True,
                            "SeatSep"   : False,
                            "Dates"     : True,
                            "Groups"    : False,
                            "GroupsAll" : False,
                            "Button1"   : True,
                            "Button2"   : False
                          }

        self.filters = Filters.Filters(self.db, self.conf, self.sql, display = filters_display)
        self.filters.registerButton1Name("_Refresh")
        self.filters.registerButton1Callback(self.refreshStats)

        # ToDo: store in config
        # ToDo: create popup to adjust column config
        # columns to display, keys match column name returned by sql, values in tuple are:
        #     is column displayed, column heading, xalignment, formatting
        self.columns = [ (1.0, "SID"   )
                       , (1.0, "Hands" )
                       , (0.5, "Start" )
                       , (0.5, "End"   )
                       , (1.0, "Rate"  )
                       , (1.0, "Open"  )
                       , (1.0, "Close" )
                       , (1.0, "Low"   )
                       , (1.0, "High"  )
                       , (1.0, "Range" )
                       , (1.0, "Profit")
                       ]

        self.detailFilters = []   # the data used to enhance the sql select

        self.main_hbox = gtk.HPaned()

        self.stats_frame = gtk.Frame()
        self.stats_frame.show()

        main_vbox = gtk.VPaned()
        main_vbox.show()
        self.graphBox = gtk.VBox(False, 0)
        self.graphBox.set_size_request(400,400)
        self.graphBox.show()
        self.stats_vbox = gtk.VBox(False, 0)
        self.stats_vbox.show()
        self.stats_frame.add(self.stats_vbox)

        self.main_hbox.pack1(self.filters.get_vbox())
        self.main_hbox.pack2(main_vbox)
        main_vbox.pack1(self.graphBox)
        main_vbox.pack2(self.stats_frame)
        self.main_hbox.show()

        # make sure Hand column is not displayed
        #[x for x in self.columns if x[0] == 'hand'][0][1] = False
        # if DEBUG == False:
        #     warning_string = _("Session Viewer is proof of concept code only, and contains many bugs.\n")
        #     warning_string += _("Feel free to use the viewer, but there is no guarantee that the data is accurate.\n")
        #     warning_string += _("If you are interested in developing the code further please contact us via the usual channels.\n")
        #     warning_string += _("Thank you")
        #     self.warning_box(warning_string)

    def warning_box(self, str, diatitle=_("FPDB WARNING")):
        diaWarning = gtk.Dialog(title=diatitle, parent=self.window, flags=gtk.DIALOG_DESTROY_WITH_PARENT, buttons=(gtk.STOCK_OK,gtk.RESPONSE_OK))

        label = gtk.Label(str)
        diaWarning.vbox.add(label)
        label.show()

        response = diaWarning.run()
        diaWarning.destroy()
        return response

    def get_vbox(self):
        """returns the vbox of this thread"""
        return self.main_hbox



    def refreshStats(self, widget, data):
        try: self.stats_vbox.destroy()
        except AttributeError: pass
        self.stats_vbox = gtk.VBox(False, 0)
        self.stats_vbox.show()
        self.stats_frame.add(self.stats_vbox)
        self.fillStatsFrame(self.stats_vbox)

    def fillStatsFrame(self, vbox):
        sites = self.filters.getSites()
        heroes = self.filters.getHeroes()
        siteids = self.filters.getSiteIds()
        games  = self.filters.getGames()
        currencies = self.filters.getCurrencies()
        limits  = self.filters.getLimits()
        seats  = self.filters.getSeats()
        sitenos = []
        playerids = []

        for i in ('show', 'none'):
            if i in limits:
                limits.remove(i)

        # Which sites are selected?
        for site in sites:
            if sites[site] == True:
                sitenos.append(siteids[site])
                _hname = Charset.to_utf8(heroes[site])
                result = self.db.get_player_id(self.conf, site, _hname)
                if result is not None:
                    playerids.append(result)

        if not sitenos:
            #Should probably pop up here.
            print _("No sites selected - defaulting to PokerStars")
            sitenos = [2]
        if not games:
            print _("No games found")
            return
        if not currencies:
            print _("No currencies found")
            return
        if not playerids:
            print _("No player ids found")
            return
        if not limits:
            print _("No limits found")
            return

        self.createStatsPane(vbox, playerids, sitenos, games, currencies, limits, seats)

    def createStatsPane(self, vbox, playerids, sitenos, games, currencies, limits, seats):
        starttime = time()

        (results, quotes) = self.generateDatasets(playerids, sitenos, games, currencies, limits, seats)

        if DEBUG:
            for x in quotes:
                print "start %s\tend %s  \thigh %s\tlow %s" % (x[1], x[2], x[3], x[4])

        self.generateGraph(quotes)

        heading = gtk.Label(self.filterText['handhead'])
        heading.show()
        vbox.pack_start(heading, expand=False, padding=3)

        # Scrolled window for detailed table (display by hand)
        swin = gtk.ScrolledWindow(hadjustment=None, vadjustment=None)
        swin.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
        swin.show()
        vbox.pack_start(swin, expand=True, padding=3)

        vbox1 = gtk.VBox(False, 0)
        vbox1.show()
        swin.add_with_viewport(vbox1)

        self.addTable(vbox1, results)

        self.db.rollback()
        print _("Stats page displayed in %4.2f seconds") % (time() - starttime)
    #end def fillStatsFrame(self, vbox):

    def generateDatasets(self, playerids, sitenos, games, currencies, limits, seats):
        if (DEBUG): print "DEBUG: Starting generateDatasets"
        THRESHOLD = 1800     # Min # of secs between consecutive hands before being considered a new session
        PADDING   = 5        # Additional time in minutes to add to a session, session startup, shutdown etc

        # Get a list of timestamps and profits

        q = self.sql.query['sessionStats']
        start_date, end_date = self.filters.getDates()
        q = q.replace("<datestest>", " BETWEEN '" + start_date + "' AND '" + end_date + "'")

        l = []
        for m in self.filters.display.items():
            if m[0] == 'Games' and m[1]:
                for n in games:
                    if games[n]:
                        l.append(n)
                if len(l) > 0:
                    gametest = str(tuple(l))
                    gametest = gametest.replace("L", "")
                    gametest = gametest.replace(",)",")")
                    gametest = gametest.replace("u'","'")
                    gametest = "AND gt.category in %s" % gametest
                else:
                    gametest = "AND gt.category IS NULL"
        q = q.replace("<game_test>", gametest)

        limittest = self.filters.get_limits_where_clause(limits)
        q = q.replace("<limit_test>", limittest)

        l = []
        for n in currencies:
            if currencies[n]:
                l.append(n)
        currencytest = str(tuple(l))
        currencytest = currencytest.replace(",)",")")
        currencytest = currencytest.replace("u'","'")
        currencytest = "AND gt.currency in %s" % currencytest
        q = q.replace("<currency_test>", currencytest)


        if seats:
            q = q.replace('<seats_test>',
                          'AND h.seats BETWEEN ' + str(seats['from']) +
                          ' AND ' + str(seats['to']))
        else:
            q = q.replace('<seats_test>', 'AND h.seats BETWEEN 0 AND 100')

        nametest = str(tuple(playerids))
        nametest = nametest.replace("L", "")
        nametest = nametest.replace(",)",")")
        q = q.replace("<player_test>", nametest)
        q = q.replace("<ampersand_s>", "%s")

        if DEBUG:
            hands = [ 
                ( u'10000',  10), ( u'10000',  20), ( u'10000',  30),
                ( u'20000', -10), ( u'20000', -20), ( u'20000', -30),
                ( u'30000',  40),
                ( u'40000',   0),
                ( u'50000', -40),
                ( u'60000',  10), ( u'60000',  30), ( u'60000', -20),
                ( u'70000', -20), ( u'70000',  10), ( u'70000',  30),
                ( u'80000', -10), ( u'80000', -30), ( u'80000',  20),
                ( u'90000',  20), ( u'90000', -10), ( u'90000', -30),
                (u'100000',  30), (u'100000', -50), (u'100000',  30),
                (u'110000', -20), (u'110000',  50), (u'110000', -20),
                (u'120000', -30), (u'120000',  50), (u'120000', -30),
                (u'130000',  20), (u'130000', -50), (u'130000',  20),
                (u'140000',  40), (u'140000', -40),
                (u'150000', -40), (u'150000',  40),
                (u'160000', -40), (u'160000',  80), (u'160000', -40),
                ]
        else:
            self.db.cursor.execute(q)
            hands = self.db.cursor.fetchall()

        #fixme - nasty hack to ensure that the hands.insert() works 
        # for mysql data.  mysql returns tuples which can't be inserted
        # into so convert explicity to list.
        hands = list(hands)

        if (not hands):
            return ([], [])

        hands.insert(0, (hands[0][0], 0))

        # Take that list and create an array of the time between hands
        times = map(lambda x:long(x[0]), hands)
        profits = map(lambda x:float(x[1]), hands)
        #print "DEBUG: times   : %s" % times
        #print "DEBUG: profits: %s" % profits
        #print "DEBUG: len(times) %s" %(len(times))
        diffs = diff(times)                      # This array is the difference in starttime between consecutive hands
        diffs2 = append(diffs,THRESHOLD + 1)     # Append an additional session to the end of the diffs, so the next line
                                                 # includes an index into the last 'session'
        index = nonzero(diffs2 > THRESHOLD)      # This array represents the indexes into 'times' for start/end times of sessions
                                                 # times[index[0][0]] is the end of the first session,
        #print "DEBUG: len(index[0]) %s" %(len(index[0]))
        if len(index[0]) > 0:
            #print "DEBUG: index[0][0] %s" %(index[0][0])
            #print "DEBUG: index %s" %(index)
            pass
        else:
            index = [[0]]
            #print "DEBUG: index %s" %(index)
            #print "DEBUG: index[0][0] %s" %(index[0][0])
            pass

        first_idx = 1
        quotes = []
        results = []
        cum_sum = cumsum(profits) / 100
        sid = 1

        total_hands = 0
        total_time = 0
        global_open = None
        global_lwm = None
        global_hwm = None

        self.times = []
        # Take all results and format them into a list for feeding into gui model.
        #print "DEBUG: range(len(index[0]): %s" % range(len(index[0]))
        for i in range(len(index[0])):
            last_idx = index[0][i]
            hds = last_idx - first_idx + 1                                           # Number of hands in session
            if hds > 0:
                stime = strftime("%d/%m/%Y %H:%M", localtime(times[first_idx]))      # Formatted start time
                etime = strftime("%d/%m/%Y %H:%M", localtime(times[last_idx]))       # Formatted end time
                self.times.append((times[first_idx], times[last_idx]))
                minutesplayed = (times[last_idx] - times[first_idx])/60
                minutesplayed = minutesplayed + PADDING
                if minutesplayed == 0:
                    minutesplayed = 1
                hph = hds*60/minutesplayed # Hands per hour
                end_idx = last_idx+1
                won = sum(profits[first_idx:end_idx])/100.0
                #print "DEBUG: profits[%s:%s]: %s" % (first_idx, end_idx, profits[first_idx:end_idx])
                hwm = max(cum_sum[first_idx-1:end_idx]) # include the opening balance,
                lwm = min(cum_sum[first_idx-1:end_idx]) # before we win/lose first hand
                open = (sum(profits[:first_idx]))/100
                close = (sum(profits[:end_idx]))/100
                #print "DEBUG: range: (%s, %s) - (min, max): (%s, %s) - (open,close): (%s, %s)" %(first_idx, end_idx, lwm, hwm, open, close)
            
                total_hands = total_hands + hds
                total_time = total_time + minutesplayed
                if (global_lwm == None or global_lwm > lwm):
                    global_lwm = lwm
                if (global_hwm == None or global_hwm < hwm):
                    global_hwm = hwm
                if (global_open == None):
                    global_open = open
                    global_stime = stime

                results.append([sid, hds, stime, etime, hph,
                                "%.2f" % open,
                                "%.2f" % close,
                                "%.2f" % lwm,
                                "%.2f" % hwm,
                                "%.2f" % (hwm - lwm),
                                "%.2f" % won])
                quotes.append((sid, open, close, hwm, lwm))
                #print "DEBUG: Hands in session %4s: %4s  Start: %s End: %s HPH: %s Profit: %s" %(sid, hds, stime, etime, hph, won)
                first_idx = end_idx
                sid = sid+1
            else:
                print "hds <= 0"
        global_close = close
        global_etime = etime
        results.append([''] * 11)
        results.append([_("all"), total_hands, global_stime, global_etime,
                        total_hands * 60 / total_time,
                        "%.2f" % global_open,
                        "%.2f" % global_close,
                        "%.2f" % global_lwm,
                        "%.2f" % global_hwm,
                        "%.2f" % (global_hwm - global_lwm),
                        "%.2f" % (global_close - global_open)])

        return (results, quotes)

    def clearGraphData(self):

        try:
            try:
                if self.canvas:
                    self.graphBox.remove(self.canvas)
            except:
                pass

            if self.fig is not None:
                self.fig.clear()
            self.fig = Figure(figsize=(5,4), dpi=100)
            if self.canvas is not None:
                self.canvas.destroy()

            self.canvas = FigureCanvas(self.fig)  # a gtk.DrawingArea
        except:
            err = traceback.extract_tb(sys.exc_info()[2])[-1]
            print _("Error:")+" "+err[2]+"("+str(err[1])+"): "+str(sys.exc_info()[1])
            raise


    def generateGraph(self, quotes):
        self.clearGraphData()

        #print "DEBUG:"
        #print "\tquotes = %s" % quotes

        #for i in range(len(highs)):
        #    print "DEBUG: (%s, %s, %s, %s)" %(lows[i], opens[i], closes[i], highs[i])
        #    print "DEBUG: diffs h/l: %s o/c: %s" %(lows[i] - highs[i], opens[i] - closes[i])

        self.ax = self.fig.add_subplot(111)

        self.ax.set_title(_("Session candlestick graph"))

        #Set axis labels and grid overlay properites
        self.ax.set_xlabel(_("Sessions"), fontsize = 12)
        self.ax.set_ylabel("$", fontsize = 12)
        self.ax.grid(color='g', linestyle=':', linewidth=0.2)

        candlestick(self.ax, quotes, width=0.50, colordown='r', colorup='g', alpha=1.00)
        self.graphBox.add(self.canvas)
        self.canvas.show()
        self.canvas.draw()

    def addTable(self, vbox, results):
        row = 0
        sqlrow = 0
        colxalign,colheading = range(2)

        self.liststore = gtk.ListStore(*([str] * len(self.columns)))
        for row in results:
            iter = self.liststore.append(row)

        view = gtk.TreeView(model=self.liststore)
        view.set_grid_lines(gtk.TREE_VIEW_GRID_LINES_BOTH)
        vbox.add(view)
        print view.connect("row-activated", self.row_activated)
        cell05 = gtk.CellRendererText()
        cell05.set_property('xalign', 0.5)
        cell10 = gtk.CellRendererText()
        cell10.set_property('xalign', 1.0)
        listcols = []

        # Create header row   eg column: ("game",     True, "Game",     0.0, "%s")
        for col, column in enumerate(self.columns):
            treeviewcolumn = gtk.TreeViewColumn(column[colheading])
            listcols.append(treeviewcolumn)
            treeviewcolumn.set_alignment(column[colxalign])
            view.append_column(listcols[col])
            if (column[colxalign] == 0.5):
                cell = cell05
            else:
                cell = cell10
            listcols[col].pack_start(cell, expand=True)
            listcols[col].add_attribute(cell, 'text', col)
            listcols[col].set_expand(True)

        vbox.show_all()

    def row_activated(self, view, path, column):
        if path[0] < len(self.times):
            replayer = None
            for tabobject in self.owner.threads:
                if isinstance(tabobject, GuiHandViewer.GuiHandViewer):
                    replayer = tabobject
                    self.owner.tab_hand_viewer(None)
                    break
            if replayer is None:
                self.owner.tab_hand_viewer(None)
                for tabobject in self.owner.threads:
                    if isinstance(tabobject, GuiHandViewer.GuiHandViewer):
                        replayer = tabobject
                        break
            # added the timezone offset ('+00:00') to make the db query work. Otherwise the hands
            # at the edges of the date range are not included. A better solution may be possible.
            # Optionally the end date in the call below, which is a Long gets a '+1'.
            reformat = lambda t: strftime("%Y-%m-%d %H:%M:%S+00:00", gmtime(t))
            handids = replayer.get_hand_ids_from_date_range(reformat(self.times[path[0]][0]), reformat(self.times[path[0]][1]), save_date = True)
            replayer.reload_hands(handids)
Exemplo n.º 28
0
class GuiSessionViewer(threading.Thread):
    def __init__(self, config, querylist, mainwin, debug=True):
        self.debug = debug
        self.conf = config
        self.sql = querylist

        self.liststore = None

        self.MYSQL_INNODB = 2
        self.PGSQL = 3
        self.SQLITE = 4

        self.fig = None
        self.canvas = None
        self.ax = None
        self.graphBox = None

        # create new db connection to avoid conflicts with other threads
        self.db = Database.Database(self.conf, sql=self.sql)
        self.cursor = self.db.cursor

        settings = {}
        settings.update(self.conf.get_db_parameters())
        settings.update(self.conf.get_import_parameters())
        settings.update(self.conf.get_default_paths())

        # text used on screen stored here so that it can be configured
        self.filterText = {
            'handhead': _('Hand Breakdown for all levels listed above')
        }

        filters_display = {
            "Heroes": True,
            "Sites": True,
            "Games": False,
            "Limits": False,
            "LimitSep": False,
            "LimitType": False,
            "Type": True,
            "Seats": False,
            "SeatSep": False,
            "Dates": True,
            "Groups": False,
            "GroupsAll": False,
            "Button1": True,
            "Button2": False
        }

        self.filters = Filters.Filters(self.db,
                                       self.conf,
                                       self.sql,
                                       display=filters_display)
        self.filters.registerButton1Name("_Refresh")
        self.filters.registerButton1Callback(self.refreshStats)

        # ToDo: store in config
        # ToDo: create popup to adjust column config
        # columns to display, keys match column name returned by sql, values in tuple are:
        #     is column displayed, column heading, xalignment, formatting
        self.columns = [
            ("sid", True, "SID", 0.0, "%s"),
            ("hand", False, "Hand", 0.0, "%s"
             )  # true not allowed for this line
            ,
            ("n", True, "Hds", 1.0, "%d"),
            ("start", True, "Start", 1.0, "%d"),
            ("end", True, "End", 1.0, "%d"),
            ("hph", True, "Hands/h", 1.0, "%d"),
            ("profit", True, "Profit", 1.0, "%s")
            #, ("avgseats", True,  "Seats",    1.0, "%3.1f")
            #, ("vpip",     True,  "VPIP",     1.0, "%3.1f")
            #, ("pfr",      True,  "PFR",      1.0, "%3.1f")
            #, ("pf3",      True,  "PF3",      1.0, "%3.1f")
            #, ("steals",   True,  "Steals",   1.0, "%3.1f")
            #, ("saw_f",    True,  "Saw_F",    1.0, "%3.1f")
            #, ("sawsd",    True,  "SawSD",    1.0, "%3.1f")
            #, ("wtsdwsf",  True,  "WtSDwsF",  1.0, "%3.1f")
            #, ("wmsd",     True,  "W$SD",     1.0, "%3.1f")
            #, ("flafq",    True,  "FlAFq",    1.0, "%3.1f")
            #, ("tuafq",    True,  "TuAFq",    1.0, "%3.1f")
            #, ("rvafq",    True,  "RvAFq",    1.0, "%3.1f")
            #, ("pofafq",   False, "PoFAFq",   1.0, "%3.1f")
            #, ("net",      True,  "Net($)",   1.0, "%6.2f")
            #, ("bbper100", True,  "BB/100",   1.0, "%4.2f")
            #, ("rake",     True,  "Rake($)",  1.0, "%6.2f")
            #, ("variance", True,  "Variance", 1.0, "%5.2f")
        ]

        self.stats_frame = None
        self.stats_vbox = None
        self.detailFilters = []  # the data used to enhance the sql select

        #self.main_hbox = gtk.HBox(False, 0)
        #self.main_hbox.show()
        self.main_hbox = gtk.HPaned()

        self.stats_frame = gtk.Frame()
        self.stats_frame.show()

        self.stats_vbox = gtk.VBox(False, 0)
        self.stats_vbox.show()
        self.stats_frame.add(self.stats_vbox)
        # self.fillStatsFrame(self.stats_vbox)

        #self.main_hbox.pack_start(self.filters.get_vbox())
        #self.main_hbox.pack_start(self.stats_frame, expand=True, fill=True)
        self.main_hbox.pack1(self.filters.get_vbox())
        self.main_hbox.pack2(self.stats_frame)
        self.main_hbox.show()

        # make sure Hand column is not displayed
        #[x for x in self.columns if x[0] == 'hand'][0][1] = False

    def get_vbox(self):
        """returns the vbox of this thread"""
        return self.main_hbox

    def refreshStats(self, widget, data):
        try:
            self.stats_vbox.destroy()
        except AttributeError:
            pass
        self.stats_vbox = gtk.VBox(False, 0)
        self.stats_vbox.show()
        self.stats_frame.add(self.stats_vbox)
        self.fillStatsFrame(self.stats_vbox)

    def fillStatsFrame(self, vbox):
        sites = self.filters.getSites()
        heroes = self.filters.getHeroes()
        siteids = self.filters.getSiteIds()
        limits = self.filters.getLimits()
        seats = self.filters.getSeats()
        sitenos = []
        playerids = []

        # Which sites are selected?
        for site in sites:
            if sites[site] == True:
                sitenos.append(siteids[site])
                _q = self.sql.query['getPlayerId']
                _name = Charset.to_utf8(heroes[site])
                #print 'DEBUG(_name) :: %s' % _name
                self.cursor.execute(_q, (_name, ))  # arg = tuple
                result = self.db.cursor.fetchall()
                if len(result) == 1:
                    playerids.append(result[0][0])

        if not sitenos:
            #Should probably pop up here.
            print _("No sites selected - defaulting to PokerStars")
            sitenos = [2]
        if not playerids:
            print _("No player ids found")
            return
        if not limits:
            print _("No limits found")
            return

        self.createStatsPane(vbox, playerids, sitenos, limits, seats)

    def createStatsPane(self, vbox, playerids, sitenos, limits, seats):
        starttime = time()

        (results, opens, closes, highs,
         lows) = self.generateDatasets(playerids, sitenos, limits, seats)

        self.graphBox = gtk.VBox(False, 0)
        self.graphBox.show()
        self.generateGraph(opens, closes, highs, lows)

        vbox.pack_start(self.graphBox)
        # Separator
        sep = gtk.HSeparator()
        vbox.pack_start(sep, expand=False, padding=3)
        sep.show_now()
        vbox.show_now()
        heading = gtk.Label(self.filterText['handhead'])
        heading.show()
        vbox.pack_start(heading, expand=False, padding=3)

        # Scrolled window for detailed table (display by hand)
        swin = gtk.ScrolledWindow(hadjustment=None, vadjustment=None)
        swin.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
        swin.show()
        vbox.pack_start(swin, expand=True, padding=3)

        vbox1 = gtk.VBox(False, 0)
        vbox1.show()
        swin.add_with_viewport(vbox1)

        self.addTable(vbox1, results)

        self.db.rollback()
        print _("Stats page displayed in %4.2f seconds") % (time() - starttime)

    #end def fillStatsFrame(self, vbox):

    def generateDatasets(self, playerids, sitenos, limits, seats):
        THRESHOLD = 1800  # Minimum number of seconds between consecutive hands before being considered a new session
        PADDING = 5  # Additional time in minutes to add to a session, session startup, shutdown etc (FiXME: user configurable)

        # Get a list of all handids and their timestampts
        #FIXME: Query still need to filter on blind levels

        q = self.sql.query['sessionStats']
        start_date, end_date = self.filters.getDates()
        q = q.replace("<datestest>",
                      " between '" + start_date + "' and '" + end_date + "'")

        nametest = str(tuple(playerids))
        nametest = nametest.replace("L", "")
        nametest = nametest.replace(",)", ")")
        q = q.replace("<player_test>", nametest)
        q = q.replace("<ampersand_s>", "%s")

        self.db.cursor.execute(q)
        hands = self.db.cursor.fetchall()

        # Take that list and create an array of the time between hands
        times = map(lambda x: long(x[0]), hands)
        handids = map(lambda x: int(x[1]), hands)
        winnings = map(lambda x: float(x[4]), hands)
        #print "DEBUG: len(times) %s" %(len(times))
        diffs = diff(
            times
        )  # This array is the difference in starttime between consecutive hands
        diffs2 = append(
            diffs, THRESHOLD + 1
        )  # Append an additional session to the end of the diffs, so the next line
        # includes an index into the last 'session'
        index = nonzero(
            diffs2 > THRESHOLD
        )  # This array represents the indexes into 'times' for start/end times of sessions
        # times[index[0][0]] is the end of the first session,
        #print "DEBUG: len(index[0]) %s" %(len(index[0]))
        if len(index[0]) > 0:
            #print "DEBUG: index[0][0] %s" %(index[0][0])
            #print "DEBUG: index %s" %(index)
            pass
        else:
            index = [[0]]
            #print "DEBUG: index %s" %(index)
            #print "DEBUG: index[0][0] %s" %(index[0][0])
            pass

        total = 0
        first_idx = 0
        lowidx = 0
        uppidx = 0
        opens = []
        closes = []
        highs = []
        lows = []
        results = []
        cum_sum = cumsum(winnings)
        cum_sum = cum_sum / 100
        sid = 1
        # Take all results and format them into a list for feeding into gui model.
        for i in range(len(index[0])):
            hds = index[0][i] - first_idx + 1  # Number of hands in session
            if hds > 0:
                stime = strftime("%d/%m/%Y %H:%M", localtime(
                    times[first_idx]))  # Formatted start time
                etime = strftime("%d/%m/%Y %H:%M", localtime(
                    times[index[0][i]]))  # Formatted end time
                minutesplayed = (times[index[0][i]] - times[first_idx]) / 60
                if minutesplayed == 0:
                    minutesplayed = 1
                minutesplayed = minutesplayed + PADDING
                hph = hds * 60 / minutesplayed  # Hands per hour
                won = sum(winnings[first_idx:index[0][i]]) / 100.0
                hwm = max(cum_sum[first_idx:index[0][i]])
                lwm = min(cum_sum[first_idx:index[0][i]])
                open = (sum(winnings[:first_idx])) / 100
                close = (sum(winnings[:index[0][i]])) / 100
                #print "DEBUG: range: (%s, %s) - (min, max): (%s, %s) - (open,close): (%s, %s)" %(first_idx, index[0][i], lwm, hwm, open, close)

                results.append([sid, hds, stime, etime, hph, won])
                opens.append(open)
                closes.append(close)
                highs.append(hwm)
                lows.append(lwm)
                #print "DEBUG: Hands in session %4s: %4s  Start: %s End: %s HPH: %s Profit: %s" %(sid, hds, stime, etime, hph, won)
                total = total + (index[0][i] - first_idx)
                first_idx = index[0][i] + 1
                sid = sid + 1
            else:
                print "hds <= 0"

        return (results, opens, closes, highs, lows)

    def clearGraphData(self):

        try:
            try:
                if self.canvas:
                    self.graphBox.remove(self.canvas)
            except:
                pass

            if self.fig is not None:
                self.fig.clear()
            self.fig = Figure(figsize=(5, 4), dpi=100)
            if self.canvas is not None:
                self.canvas.destroy()

            self.canvas = FigureCanvas(self.fig)  # a gtk.DrawingArea
        except:
            err = traceback.extract_tb(sys.exc_info()[2])[-1]
            print _("***Error: ") + err[2] + "(" + str(err[1]) + "): " + str(
                sys.exc_info()[1])
            raise

    def generateGraph(self, opens, closes, highs, lows):
        self.clearGraphData()

        #        print "DEBUG:"
        #        print "highs = %s" % highs
        #        print "lows = %s" % lows
        #        print "opens = %s" % opens
        #        print "closes = %s" % closes
        #        print "len(highs): %s == len(lows): %s" %(len(highs), len(lows))
        #        print "len(opens): %s == len(closes): %s" %(len(opens), len(closes))
        #
        #        for i in range(len(highs)):
        #            print "DEBUG: (%s, %s, %s, %s)" %(lows[i], opens[i], closes[i], highs[i])
        #            print "DEBUG: diffs h/l: %s o/c: %s" %(lows[i] - highs[i], opens[i] - closes[i])

        self.ax = self.fig.add_subplot(111)

        self.ax.set_title(_("Session candlestick graph"))

        #Set axis labels and grid overlay properites
        self.ax.set_xlabel(_("Sessions"), fontsize=12)
        self.ax.set_ylabel("$", fontsize=12)
        self.ax.grid(color='g', linestyle=':', linewidth=0.2)

        candlestick2(self.ax,
                     opens,
                     closes,
                     highs,
                     lows,
                     width=0.50,
                     colordown='r',
                     colorup='g',
                     alpha=1.00)
        self.graphBox.add(self.canvas)
        self.canvas.show()
        self.canvas.draw()

    def addTable(self, vbox, results):
        row = 0
        sqlrow = 0
        colalias, colshow, colheading, colxalign, colformat = 0, 1, 2, 3, 4

        # pre-fetch some constant values:
        cols_to_show = [x for x in self.columns if x[colshow]]

        self.liststore = gtk.ListStore(*([str] * len(cols_to_show)))
        for row in results:
            iter = self.liststore.append(row)

        view = gtk.TreeView(model=self.liststore)
        view.set_grid_lines(gtk.TREE_VIEW_GRID_LINES_BOTH)
        vbox.add(view)
        textcell = gtk.CellRendererText()
        textcell50 = gtk.CellRendererText()
        textcell50.set_property('xalign', 0.5)
        numcell = gtk.CellRendererText()
        numcell.set_property('xalign', 1.0)
        listcols = []

        # Create header row   eg column: ("game",     True, "Game",     0.0, "%s")
        for col, column in enumerate(cols_to_show):
            s = column[colheading]
            listcols.append(gtk.TreeViewColumn(s))
            view.append_column(listcols[col])
            if column[colformat] == '%s':
                if column[colxalign] == 0.0:
                    listcols[col].pack_start(textcell, expand=True)
                    listcols[col].add_attribute(textcell, 'text', col)
                else:
                    listcols[col].pack_start(textcell50, expand=True)
                    listcols[col].add_attribute(textcell50, 'text', col)
                listcols[col].set_expand(True)
            else:
                listcols[col].pack_start(numcell, expand=True)
                listcols[col].add_attribute(numcell, 'text', col)
                listcols[col].set_expand(True)

        vbox.show_all()
Exemplo n.º 29
0
class GuiApp(object):

    def __init__(self):
	global unit
	self.filename=None
	self.gladefile="/usr/share/freeceilo-%s/ceilo.glade" % VERSION
       	self.wTree=gtk.glade.XML(self.gladefile)
       	self.window=self.wTree.get_widget("FreeCeilo")
       	self.window.maximize()

	self.threadvar=0
      #--------buttons---------#
	self.Open=self.wTree.get_widget("Open")
      #-----cloud detection plotting button------#
	self.first_cld_plot_button=self.wTree.get_widget("first_cld_plot_button")
	self.second_cld_plot_button=self.wTree.get_widget("second_cld_plot_button")
	self.third_cld_plot_button=self.wTree.get_widget("third_cld_plot_button")
	self.cld_det_clear_button=self.wTree.get_widget("cld_det_clear_button")
	self.cld_det_save_button=self.wTree.get_widget("cld_det_save_button")
		
      #------------  gnuplot buttons -------------#
	self.gnu_plot_button=self.wTree.get_widget("gnu_plot_button")			
	self.gnuplot_zoom_in_button=self.wTree.get_widget("gnuplot_zoom_in_button")
	self.gnuplot_zoom_normal_button=self.wTree.get_widget("gnuplot_zoom_normal_button")
	self.gnuplot_zoom_out_button=self.wTree.get_widget("gnuplot_zoom_out_button")	
	self.gnuplot_save_button=self.wTree.get_widget("gnuplot_save_button")

      #--------buttons ends---------#

      #------progressbars------#

	self.progressbar1=self.wTree.get_widget("progressbar1")

	self.progressbar2=self.wTree.get_widget("progressbar2")

        self.progressbar1.set_fraction(0.0)
	self.datpbar=0

        self.progressbar2.set_fraction(0.0)
	self.gnupbar=0

	self.timer = gobject.timeout_add (100, progress_timeout, self)

     #------gnu plot image normal size ----#

	self.imagex= 810
	self.imagey=540
	self.gnuplot_image=self.wTree.get_widget("gnuplot_image")
	self.x=0

     #--------Handles events



	dic={"on_FreeCeilo_destroy":self.quitprogram,"on_Open_activate":self.openfile,
	"on_first_cld_plot_button_clicked":self.firstcloudshow,"on_second_cld_plot_button_clicked"
	:self.secondcloudshow,"on_third_cld_plot_button_clicked":self.thirdcloudshow,	
	"on_zoom_in_x_activate":self.clouddetectzoominx,"on_zoom_out_x_activate":
	self.clouddetectzoomoutx,"on_zoom_in_y_activate":self.clouddetectzoominy,
	"on_zoom_out_y_activate":self.clouddetectzoomouty,"on_cld_det_save_button_clicked"
	:self.clouddetectsave,"on_cld_det_clear_button_clicked":self.clouddetectgraphclear,
	"on_gnu_plot_button_clicked":self.gnuplotshow,"on_gnuplot_zoom_in_button_clicked":
	self.gnuplotzoomin,"on_gnuplot_zoom_normal_button_clicked":self.gnuplotzoomnormal,
	"on_gnuplot_zoom_out_button_clicked":self.gnuplotzoomout,"on_gnuplot_save_button_clicked"
	:self.gnuplotsave}
        self.wTree.signal_autoconnect(dic)


     #-----plotting area for graphs
	
	self.graphview = self.wTree.get_widget("hbox7")

     #-----plotting area for cloud detection graph
 
       	self.figure1 = Figure(figsize=(12,6),facecolor='y',dpi=55,edgecolor='black',linewidth=5.0)
	self.axis1 = self.figure1.add_subplot(111)
	self.axis1.grid(True)

	self.canvas1 = FigureCanvasGTK(self.figure1)
	self.graphview.pack_start(self.canvas1,True,True)
        self.canvas1.show()
	self.axis1.set_autoscale_on(True)

    #-----plotting area for back scatterprofile

	self.figure2 = Figure(figsize=(12,6),facecolor='y', dpi=55,edgecolor='black',linewidth=4.0)
	self.axis2 = self.figure2.add_subplot(111)
	self.axis2.grid(True)
        self.canvas2 = FigureCanvasGTK(self.figure2) 
	self.graphview.pack_end(self.canvas2,True,True)
        self.canvas2.show()

################################# File Openning and dataprocessing #######################
    def openfile(self,obj):
	self.filename=None
	if(self.threadvar==1):
		os.system("killall -9 gnuplot > /dev/zero")
		self.datpbar=0
		self.gnupbar=0
		self.datadecode_thread_obj.stop()
	dialog = gtk.FileChooserDialog("Open..",
                              None,
                              gtk.FILE_CHOOSER_ACTION_OPEN,
                              (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL,
                               gtk.STOCK_OPEN, gtk.RESPONSE_OK))
	dialog.set_default_response(gtk.RESPONSE_OK)
	filter = gtk.FileFilter()
	filter.set_name("DATA FILES")
	filter.add_pattern("*.dat")
	dialog.add_filter(filter)
	response=dialog.run()
	if response == gtk.RESPONSE_OK:
        	self.filename=dialog.get_filename()
		self.window.set_title("Free Ceilo 0.1 ( "+self.filename+")")
		self.datpbar=1
		self.gnupbar=1
    	     #---- Threads for datadecoding ,gnuplot ---#
		cond=Condition()
		self.datadecode_thread_obj=datadecodethreadlib.DataDecodeThread(cond,self.filename)
		self.datadecode_thread_obj.start()
		self.threadvar=1
             #---- Threads ends ------#
	elif response == gtk.RESPONSE_CANCEL:
       		print 'Closed, no files selected'
	dialog.destroy()

###############################Cloud Detection Graph Plotting #######################

   ##### Show the first cloud  ######

    def firstcloudshow(self,obj):
	
	self.x= getstatusobj.getdataobj()
        self.axis1.set_xlabel('Time')
        self.axis1.set_ylabel('Altitude'+","+unit)
        self.axis1.set_title('Cloud Detection Graph')
	self.axis1.grid(True)
	self.axis1.plot_date(self.x.lwst_time_index,self.x.lwst_cldbse_hgt,'b.',label=" First")
	self.axis1.xaxis.set_major_locator(MaxNLocator(6))

     ####-------for rotating the xticks------------------###########
	#labels = self.axis1.get_xticklabels()
	#setp(labels, rotation=90, fontsize=10)

	self.axis1.legend()
	self.canvas1.draw()

   ##### Show the second cloud  ######

    def secondcloudshow(self,obj):
	self.x= getstatusobj.getdataobj()
        self.axis1.set_xlabel('Time')
        self.axis1.set_ylabel('Altitude'+","+unit)
        self.axis1.set_title('Cloud Detection Graph')
	self.axis1.grid(True)
	self.axis1.plot_date(self.x.sec_time_index,self.x.sec_lwst_cldbse_hgt,'g.',label="Second")
	self.axis1.xaxis.set_major_locator(MaxNLocator(6))
	self.axis1.legend()
	self.canvas1.draw()

   ##### Show the third cloud  ######

    def thirdcloudshow(self,obj):
	self.x= getstatusobj.getdataobj()
        self.axis1.set_xlabel('Time')
        self.axis1.set_ylabel('Altitude'+","+unit)
        self.axis1.set_title('Cloud Detection Graph')
	self.axis1.grid(True)
	self.axis1.plot_date(self.x.higst_time_index,self.x.higst_cldbse_hgt,'r.',label="Third")
	self.axis1.xaxis.set_major_locator(MaxNLocator(6))
	self.axis1.legend()
	self.canvas1.draw()
    
   ####---------Zooming the figure--------########  

    def clouddetectzoominx(self,obj):
	self.axis1.zoomx(2)
	self.canvas1.draw()

    def clouddetectzoomoutx(self,obj):
	self.axis1.zoomx(-2)
	self.canvas1.draw()


    def clouddetectzoominy(self,obj):
	self.axis1.zoomy(2)
	self.canvas1.draw()

    def clouddetectzoomouty(self,obj):
	self.axis1.zoomy(-2)
	self.canvas1.draw()

    def clouddetectgraphclear(self,obj):
	self.axis1.clear()
	self.axis1.set_xlabel('Time')
        self.axis1.set_ylabel('Altitude'+","+unit)
        self.axis1.set_title('Cloud Detection Graph')
	self.axis1.grid(True)
	self.canvas1.draw()

  #############SAVE CLD DETECT#########

    def clouddetectsave(self,obj):
	dialog= gtk.FileChooserDialog("Save Cloud Detection Graph ",
                               None,
                               gtk.FILE_CHOOSER_ACTION_SAVE,
                               (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL,
                                gtk.STOCK_SAVE, gtk.RESPONSE_OK))
	dialog.set_default_response(gtk.RESPONSE_OK)
	dialog.set_current_folder(os.curdir)
	dialog.set_do_overwrite_confirmation(True)
	filter = gtk.FileFilter()
	filter.set_name("image(png) file")
	filter.add_pattern("*.png")
	dialog.add_filter(filter)
	response=dialog.run()
	if response == gtk.RESPONSE_OK:
         	plotimagefile=dialog.get_filename()
		dialog.destroy()
		#self.canvas1.print_figure1(plotimagefile, 72,'w', 'w','portrait')
	       	self.figure1.savefig(plotimagefile)
		self.canvas1.destroy()
		self.canvas1 = FigureCanvasGTK(self.figure1) 
		self.graphview.pack_start(self.canvas1, True,True)
        	self.canvas1.show()
	elif response == gtk.RESPONSE_CANCEL:
		print "no file is selected"
		dialog.destroy()
	self.canvas1.show()



##########################################GNUPLOT####################################

 #--------- The Functions to display Gnuplot image and zoom the images and save------#

    def gnuplotshow(self,obj):
	self.gnuplot_image.set_from_file("/tmp/FreeCeilo/.gnu.png")
	#----Functions to zoom the images----#
    def gnuplotzoomin(self,obj):
	self.imagex+=30
	self.imagey+=20
	self.gnuplotzoom()
    def gnuplotzoomout(self,obj):
	self.imagex-=30
	self.imagey-=20
	self.gnuplotzoom()
    def gnuplotzoomnormal(self,obj):
	self.imagex=810
	self.imagey=540
	self.gnuplotzoom()
    def gnuplotzoom(self):
	self.gnuplot_image.set_from_pixbuf(gtk.gdk.pixbuf_new_from_file("/tmp/FreeCeilo/.gnu.png").scale_simple(self.imagex,self.imagey,gtk.gdk.INTERP_BILINEAR))

	#---Function to save the gnuplot image in another location using save as option---#

    def gnuplotsave(self,obj):
	dialog= gtk.FileChooserDialog("Save as..",
                         None,
                         gtk.FILE_CHOOSER_ACTION_SAVE,
                         (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL,
                         gtk.STOCK_SAVE, gtk.RESPONSE_OK))
	dialog.set_default_response(gtk.RESPONSE_OK)
	dialog.set_do_overwrite_confirmation(True)
	filter = gtk.FileFilter()
	filter.set_name("image(png) file")
	filter.add_pattern("*.png")
	dialog.add_filter(filter)
	response=dialog.run()
	if response == gtk.RESPONSE_OK:
        	plotimagefile=dialog.get_filename()
		if not plotimagefile.endswith(".png"):
			k=plotimagefile.find(".")
			plotimagefile=plotimagefile[0:k]
			plotimagefile=plotimagefile.__add__(".png")
		shutil.copyfile("/tmp/FreeCeilo/.gnu.png",plotimagefile)
	elif response == gtk.RESPONSE_CANCEL:
		print "no file is selected"
	dialog.destroy()



#################################  Quit the Program #########################

    def quitprogram(self,obj):
	self.id1=os.getpid()
       	gobject.source_remove(self.timer)
       	self.timer = 0
	gtk.main_quit()
	os.system("killall -9 gnuplot > /dev/zero")
	os.popen("kill -9 "+str(self.id1))
	sys.exit(0)
Exemplo n.º 30
0
class GuiTourneyGraphViewer(threading.Thread):
    def __init__(self, querylist, config, parent, debug=True):
        """Constructor for GraphViewer"""
        self.sql = querylist
        self.conf = config
        self.debug = debug
        self.parent = parent
        #print "start of GraphViewer constructor"
        self.db = Database.Database(self.conf, sql=self.sql)

        filters_display = {
            "Heroes": True,
            "Sites": True,
            "Games": False,
            "Limits": False,
            "LimitSep": False,
            "LimitType": False,
            "Type": False,
            "UseType": 'tour',
            "Seats": False,
            "SeatSep": False,
            "Dates": True,
            "Groups": False,
            "Button1": True,
            "Button2": True
        }

        self.filters = Filters.Filters(self.db,
                                       self.conf,
                                       self.sql,
                                       display=filters_display)
        self.filters.registerButton1Name(_("Refresh _Graph"))
        self.filters.registerButton1Callback(self.generateGraph)
        self.filters.registerButton2Name(_("_Export to File"))
        self.filters.registerButton2Callback(self.exportGraph)

        self.mainHBox = gtk.HBox(False, 0)
        self.mainHBox.show()

        self.leftPanelBox = self.filters.get_vbox()

        self.hpane = gtk.HPaned()
        self.hpane.pack1(self.leftPanelBox)
        self.mainHBox.add(self.hpane)
        # hierarchy:  self.mainHBox / self.hpane / self.graphBox / self.canvas / self.fig / self.ax

        self.graphBox = gtk.VBox(False, 0)
        self.graphBox.show()
        self.hpane.pack2(self.graphBox)
        self.hpane.show()

        self.fig = None
        #self.exportButton.set_sensitive(False)
        self.canvas = None

        self.db.rollback()

    def get_vbox(self):
        """returns the vbox of this thread"""
        return self.mainHBox

    #end def get_vbox

    def clearGraphData(self):
        try:
            if self.canvas:
                self.graphBox.remove(self.canvas)
        except:
            pass

        if self.fig != None:
            self.fig.clear()
        self.fig = Figure(figsize=(5, 4), dpi=100)
        if self.canvas is not None:
            self.canvas.destroy()

        self.canvas = FigureCanvas(self.fig)  # a gtk.DrawingArea

    def generateGraph(self, widget, data):
        self.clearGraphData()

        sitenos = []
        playerids = []

        sites = self.filters.getSites()
        heroes = self.filters.getHeroes()
        siteids = self.filters.getSiteIds()

        # Which sites are selected?
        for site in sites:
            if sites[site] == True:
                sitenos.append(siteids[site])
                _hname = Charset.to_utf8(heroes[site])
                result = self.db.get_player_id(self.conf, site, _hname)
                if result is not None:
                    playerids.append(int(result))

        if not sitenos:
            #Should probably pop up here.
            print _("No sites selected - defaulting to PokerStars")
            self.db.rollback()
            return

        if not playerids:
            print _("No player ids found")
            self.db.rollback()
            return

        #Set graph properties
        self.ax = self.fig.add_subplot(111)

        #Get graph data from DB
        starttime = time()
        green = self.getData(playerids, sitenos)
        print _("Graph generated in: %s") % (time() - starttime)

        #Set axis labels and grid overlay properites
        self.ax.set_xlabel(_("Tournaments"), fontsize=12)
        self.ax.set_ylabel("$", fontsize=12)
        self.ax.grid(color='g', linestyle=':', linewidth=0.2)
        if green == None or green == []:
            self.ax.set_title(_("No Data for Player(s) Found"))
            green = ([
                0., 0., 0., 0., 500., 1000., 900., 800., 700., 600., 500.,
                400., 300., 200., 100., 0., 500., 1000., 1000., 1000., 1000.,
                1000., 1000., 1000., 1000., 1000., 1000., 1000., 1000., 1000.,
                875., 750., 625., 500., 375., 250., 125., 0., 0., 0., 0., 500.,
                1000., 900., 800., 700., 600., 500., 400., 300., 200., 100.,
                0., 500., 1000., 1000.
            ])
            red = ([
                0., 0., 0., 0., 500., 1000., 900., 800., 700., 600., 500.,
                400., 300., 200., 100., 0., 0., 0., 0., 0., 0., 0., 125., 250.,
                375., 500., 500., 500., 500., 500., 500., 500., 500., 500.,
                375., 250., 125., 0., 0., 0., 0., 500., 1000., 900., 800.,
                700., 600., 500., 400., 300., 200., 100., 0., 500., 1000.,
                1000.
            ])
            blue = ([
                0., 0., 0., 0., 500., 1000., 900., 800., 700., 600., 500.,
                400., 300., 200., 100., 0., 0., 0., 0., 0., 0., 0., 125., 250.,
                375., 500., 625., 750., 875., 1000., 875., 750., 625., 500.,
                375., 250., 125., 0., 0., 0., 0., 500., 1000., 900., 800.,
                700., 600., 500., 400., 300., 200., 100., 0., 500., 1000.,
                1000.
            ])

            self.ax.plot(green,
                         color='green',
                         label=_('Tournaments') + ': %d\n' % len(green) +
                         _('Profit') + ': $%.2f' % green[-1])
            self.graphBox.add(self.canvas)
            self.canvas.show()
            self.canvas.draw()

            #TODO: Do something useful like alert user
        else:
            self.ax.set_title(_("Tournament Results"))

            #Draw plot
            self.ax.plot(green,
                         color='green',
                         label=_('Tournaments') + ': %d\n' % len(green) +
                         _('Profit') + ': $%.2f' % green[-1])

            legend = self.ax.legend(loc='upper left',
                                    fancybox=True,
                                    shadow=True,
                                    prop=FontProperties(size='smaller'))
            legend.draggable(True)

            self.graphBox.add(self.canvas)
            self.canvas.show()
            self.canvas.draw()
            #self.exportButton.set_sensitive(True)

    #end of def showClicked

    def getData(self, names, sites):
        tmp = self.sql.query['tourneyResults']
        print "DEBUG: getData"
        start_date, end_date = self.filters.getDates()

        #Buggered if I can find a way to do this 'nicely' take a list of integers and longs
        # and turn it into a tuple readale by sql.
        # [5L] into (5) not (5,) and [5L, 2829L] into (5, 2829)
        nametest = str(tuple(names))
        sitetest = str(tuple(sites))

        #Must be a nicer way to deal with tuples of size 1 ie. (2,) - which makes sql barf
        tmp = tmp.replace("<player_test>", nametest)
        tmp = tmp.replace("<site_test>", sitetest)
        tmp = tmp.replace("<startdate_test>", start_date)
        tmp = tmp.replace("<enddate_test>", end_date)
        tmp = tmp.replace(",)", ")")

        print "DEBUG: sql query:"
        print tmp
        self.db.cursor.execute(tmp)
        #returns (HandId,Winnings,Costs,Profit)
        winnings = self.db.cursor.fetchall()
        self.db.rollback()

        if len(winnings) == 0:
            return None

        green = map(lambda x: float(x[1]), winnings)
        #blue  = map(lambda x: float(x[1]) if x[2] == True  else 0.0, winnings)
        #red   = map(lambda x: float(x[1]) if x[2] == False else 0.0, winnings)
        greenline = cumsum(green)
        #blueline  = cumsum(blue)
        #redline   = cumsum(red)
        return (greenline / 100)

    def exportGraph(self, widget, data):
        if self.fig is None:
            return  # Might want to disable export button until something has been generated.

        dia_chooser = gtk.FileChooserDialog(
            title=_("Please choose the directory you wish to export to:"),
            action=gtk.FILE_CHOOSER_ACTION_SELECT_FOLDER,
            buttons=(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, gtk.STOCK_OK,
                     gtk.RESPONSE_OK))
        dia_chooser.set_destroy_with_parent(True)
        dia_chooser.set_transient_for(self.parent)
        try:
            dia_chooser.set_filename(
                self.exportFile
            )  # use previously chosen export path as default
        except:
            pass

        response = dia_chooser.run()

        if response <> gtk.RESPONSE_OK:
            print _('Closed, no graph exported')
            dia_chooser.destroy()
            return

        # generate a unique filename for export
        now = datetime.now()
        now_formatted = now.strftime("%Y%m%d%H%M%S")
        self.exportFile = dia_chooser.get_filename(
        ) + "/fpdb" + now_formatted + ".png"
        dia_chooser.destroy()

        #print "DEBUG: self.exportFile = %s" %(self.exportFile)
        self.fig.savefig(self.exportFile, format="png")

        #display info box to confirm graph created
        diainfo = gtk.MessageDialog(parent=self.parent,
                                    flags=gtk.DIALOG_DESTROY_WITH_PARENT,
                                    type=gtk.MESSAGE_INFO,
                                    buttons=gtk.BUTTONS_OK,
                                    message_format=_("Graph created"))
        diainfo.format_secondary_text(self.exportFile)
        diainfo.run()
        diainfo.destroy()
Exemplo n.º 31
0
class Graphtemp(object):
    def __init__(self, tipo):
        self.cuento = 0
        self.magico = 800
        self.app = None
        self.tipo = tipo
        self.data = np.array([])
        self.fechas = np.array([])
        self.caldera = np.array([])
        self.dpi = 100
        self.f = Figure((3.0, 3.0), dpi=self.dpi)
        self.f.subplots_adjust(hspace=1, left=.05, right=.99, top=.92)
        self.a = self.f.add_subplot(111)
        self.a.set_axis_bgcolor('white')
        setp(self.a.get_xticklabels(), fontsize=8)
        setp(self.a.get_yticklabels(), fontsize=8)
        self.plot_data = self.a.plot(
            self.data,
            linewidth=1.4,
            color=tipo.color,
        )[0]
        self.plot_data2 = self.a.plot(
            np.array([]),
            linestyle="--",
            linewidth=1.4,
            color="g",
        )[0]
        self.plot_data3 = self.a.plot(
            np.array([]),
            linestyle="--",
            linewidth=1.4,
            color="r",
        )[0]
        self.a.grid(True)
        #        self.a.set_xlabel('Time')
        self.a.set_ylabel(tipo.formal)
        self.canvas = FigureCanvas(self.f)

    @inlineCallbacks
    def on_redraw_timer(self):
        from twisted.internet import reactor
        self.tiempo = time.time()
        if not self.app.is_stoped:
            # if paused do not add data, but still redraw the plot
            # (to respond to scale modifications, grid change, etc.)
            #
            #print "They have called me!"
            numero = self.tipo.actual
            if numero:
                self.data = np.append(
                    self.data,
                    float(numero))  # .append(float()) acá le agrega le dato
                self.fechas = np.append(self.fechas, self.cuento)
                self.caldera = np.append(self.caldera,
                                         40 if self.app.caldera.actual else 20)
                self.cuento += 1
                if self.fechas.size > self.magico:
                    self.data = np.delete(self.data, 0)
                    self.fechas = np.delete(self.fechas, 0)
                    self.caldera = np.delete(self.caldera, 0)
                xmax = self.fechas.max(
                ) if self.fechas.max() > self.magico else self.magico
                xmin = xmax - self.magico
                #ymin = round(self.data.min(), 0) - 1
                ymin = -.5
                ymax = 42  #round(self.data.max(), 0) + 1
                self.a.set_xbound(lower=xmin, upper=xmax)
                self.a.set_ybound(lower=ymin, upper=ymax)
                self.plot_data2.set_xdata(np.array([0, xmax]))
                yield
                self.plot_data2.set_ydata(np.array([self.tipo.medio] * 2))
            #self.fechas = np.append(self.fechas, datetime())
            yield
            setp(self.a.get_xticklabels(), visible=True)
            yield
            #print np.arange(self.data.size) == self.fechas
            self.plot_data.set_xdata(self.fechas)
            self.plot_data.set_ydata(self.data)
            yield
            self.plot_data3.set_ydata(self.caldera)
            self.plot_data3.set_xdata(self.fechas)
            yield
            d = Deferred()
            reactor.callLater(.1, d.callback, None)
            yield d
            self.canvas.draw()
            yield
        else:
            d = Deferred()
            reactor.callLater(.1, d.callback, None)
            yield d
        reactor.callLater(time.time() - self.tiempo - .1, self.on_redraw_timer)
Exemplo n.º 32
0
class MatPlotLibPlotter(Plotter):
	
	def __init__(self, module, mainWindow, preferredWidth, preferredHeight, startWithImage=True):
		"""
		Constructor for a Mat Plot Lib Plotter.
		
		module - the module using this plotter
		mainWindow - the MainWindow displaying this plotter
		preferredWidth - the default width of the plotter
		preferredHeight - the default height of the plotter
		startWithImage - a boolean, that if true will display the module's baseimage at first,
						and switch to the matplotlib plotter when setBaseImageVisible(False) or
						drawFigure() is called.
		"""
		
		# call the superclass constructor
		Plotter.__init__(self, module, mainWindow)
		
		self.preferredWidth = preferredWidth
		self.preferredHeight = preferredHeight
		
		self.imageVisible = startWithImage
		
		path = mainWindow.getPath()
		
		if (self.module.baseimage):
			self.imageFile = self.module.directory + os.sep + self.module.baseimage
		else:
			self.imageFile = path + os.sep + "img" + os.sep + "seatree.jpg"
		
		self.figure = matplotlib.figure.Figure()
		self.axis = self.figure.add_subplot(111)
		self.canvas = FigureCanvas(self.figure)
		
		self.bgColor = "white"
		
		self.colorMap = matplotlib.cm.Spectral
		
		self.evenAspectRatio = True
		self.climMin = None
		self.climMax = None
		self.image = None
		self.contourLines = False
		self.contourFills = False
		
		self.colorBarOrientation = VERTICAL
		
		self.gui = mplSettingsPanel.MPLSettingsPanel(self)
	
	def tellModuleToReplot(self):
		self.module.updatePlot()
	
	def setColorMapByName(self, name, reversed=False, updateGUI=True):
		self.colorMap = matplotlib.cm.get_cmap(name=name)
		#print "Reversing? " + str(reversed)
		# set our custom 'seatree_reversed' flag
		try:
			dummy = self.colorMap.seatree_reversed
#			print "it has a reversed flag!"
		except:
#			print "it doesn't have a reversed flag!"
			self.colorMap.seatree_reversed = False
#		print "Reversing? " + str(reversed)
#		print "Already Reversed? " + str(self.colorMap.seatree_reversed)
		if reversed != self.colorMap.seatree_reversed:
#			print "lets flip it!"
			self.colorMap = self.reverseColormap(self.colorMap)
		self.colorMap.seatree_reversed = reversed
		if updateGUI:
			self.gui.loadOptionsFromPlotter()
	
	def reverseColormap(self, cm):
#		print cm._segmentdata['red']
		#self.__reverseCMComponent(cm, 'red')
		#self.__reverseCMComponent(cm, 'blue')
		#self.__reverseCMComponent(cm, 'green')
		
		segData = dict()
		numSegs = len(cm._segmentdata['red'])
		reds = []
		for i in range(numSegs):
			index = numSegs - i - 1
			val = self.colorMap._segmentdata['red'][index]
			reds.append((1 - val[0], val[1], val[2]))
		numSegs = len(cm._segmentdata['blue'])
		blues = []
		for i in range(numSegs):
			index = numSegs - i - 1
			val = self.colorMap._segmentdata['blue'][index]
			blues.append((1 - val[0], val[1], val[2]))
		numSegs = len(cm._segmentdata['green'])
		greens = []
		for i in range(numSegs):
			index = numSegs - i - 1
			val = self.colorMap._segmentdata['green'][index]
			greens.append((1 - val[0], val[1], val[2]))
		
		segData = {'red': reds, 'blue': blues, 'green': greens}
		newCM = matplotlib.colors.LinearSegmentedColormap(cm.name,segData,1024)
		#cm._segmentdata = segData
#		print newCM._segmentdata['red']
		newCM.seatree_reversed = True
		return newCM
	
	def isColorMapReversed(self, colorMap=None):
		if colorMap == None:
			colorMap = self.colorMap
		try:
			if self.colorMap.seatree_reversed:
				return True
		except:
			self.colorMap.seatree_reversed = False
			return False
		return False
	
	def setColorMap(self, colorMap):
		self.colorMap = colorMap
		self.gui.loadOptionsFromPlotter()
	
	def getColorMap(self):
		return self.colorMap
	
	def setColorbarOrientation(self, orientation):
		self.colorBarOrientation = orientation
	
	def applyColorLimits(self):
		if self.image != None:
			try:
				self.image.set_clim(self.climMin, self.climMax)
			except:
				pass
	
	def setColorLimits(self, min, max, updateGUI=True):
		self.climMin = min
		self.climMax = max
		if updateGUI:
			self.gui.loadOptionsFromPlotter()
	
	def getColorLimits(self):
		return (self.climMin, self.climMax)
	
	def setContourFills(self, contour):
		"""
		Plot XYZ data contoured.
		
		contour - boolean that, if true, will contour plots
		"""
		self.contourFills = contour
	
	def getContourFills(self):
		return self.contourFills
	
	def setContourLines(self, contour):
		"""
		Plot XYZ data contour lines drawn.
		
		contour - boolean that, if true, will contour plots
		"""
		self.contourLines = contour
	
	def getContourLines(self):
		return self.contourLines
	
	def setBaseImageVisible(self, visible):
		if (self.imageVisible != visible):
			self.imageVisible = visible
			self.mainWindow.loadPlotter(self)
	
	def drawFigure(self, applyAspect=True):
		self.setBaseImageVisible(False)
		
		if applyAspect:
			self.applyAspectRatio()
		self.applyColorLimits()
		
		self.canvas.draw()
		
		self.mainWindow.setSaveActive(True)
	
	def addTextLabel(self, x, y, text, **kwargs):
		self.figure.text(x, y, text, **kwargs)
	
	def setAxis(self, axis):
		self.axis = axis
	
	def getAxis(self):
		return self.axis
	
	def getFigure(self):
		return self.figure
	
	def getLastImage(self):
		return self.image
	
	def clearFigure(self, subplot=111):
		self.figure.clear()
		if subplot != None:
			self.axis = self.figure.add_subplot(subplot)
		
		self.mainWindow.setSaveActive(False)
	
	def getAxisLimits(self, axis=None):
		"""
		Returns the limits of the axis as a tuple with this format:
		[xmin, xmax, ymin, ymax]
		"""
		if axis == None:
			axis = self.axis
		x = axis.get_xlim()
		y = axis.get_ylim()
		
		return (x[0], x[1], y[0], y[1])
	
	def limitAxis(self, minX, maxX, minY, maxY):
		self.minX = minX
		self.maxX = maxX
		self.minY = minY
		self.maxY = maxY
		
		self.axis.set_xlim(minX,maxX)
		self.axis.set_ylim(minY,maxY)
	
	def applyAspectRatio(self, axis=None):
		if axis == None:
			axis = self.axis
		if self.evenAspectRatio:
			axis._aspect = 'equal'
			axis.apply_aspect()
		else:
			axis._aspect = 'auto'
			axis.apply_aspect()
	
	def setAspectRatioEven(self, even):
		self.evenAspectRatio = even
	
	def plotXYZFromFile(self, xyzFile, numX, numY, title="", colorBar=False):
		"""

		Load data from a file and call plotXYZData

		"""
		a = matplotlib.mlab.load(xyzFile)
		n = numX # determine square size
		m = numY
		# determine geometry
		xmin, xmax = min(a[:,0]), max(a[:,0])
		ymin, ymax = min(a[:,1]), max(a[:,1])
		range = [ xmin , xmax, ymin, ymax ];

		# assign three columns to vectors
		x=a[:,0].reshape(n,m)
		y=a[:,1].reshape(n,m)
		z=a[:,2].reshape(n,m)
		self.plotXYZData(x,y,z,title,colorBar,range);
	
	def plotXYZFromSquareDataFile(self, xyzFile, title="", colorBar=False):
		"""

		Load data from a file assuming that the data is given on 
		an n by n "square" set of points and call plotXYZData

		"""
		a = matplotlib.mlab.load(xyzFile)
		n = int(math.sqrt(a.shape[0])) # determine square size
		m = n
		# determine geometry
		xmin, xmax = min(a[:,0]), max(a[:,0])
		ymin, ymax = min(a[:,1]), max(a[:,1])
		range = [ xmin , xmax, ymin, ymax ];

		# assign three columns to vectors
		x=a[:,0].reshape(n,m)
		y=a[:,1].reshape(n,m)
		z=a[:,2].reshape(n,m)
		self.plotXYZData(x,y,z,title,colorBar,range);

	def plotXYZData(self, x, y, z, title="", colorBar=False, range=None):
		"""
		Plot xyz data in vectors x y z
		if range is set, will expect four entry vector with limiting range for plot sorted 
		as [xmin, xmax,ymin,ymax]
		"""
		if self.contourFills:
			self.image = self.axis.contourf(x, y, z, cmap=self.colorMap, shading='flat', extend='both')
		else:
			self.image = self.axis.pcolor(x, y, z, cmap=self.colorMap, shading='flat')
		
		if self.contourLines:
			self.axis.contour(x, y, z, colors='black', linewidths=1, shading='flat', extend='both')
			
		if range != None:
			self.limitAxis(range[0],range[1],range[2],range[3]);
		
		if (colorBar):
			self.figure.colorbar(self.image, orientation=self.colorBarOrientation)
		
		if (title):
			self.axis.set_title(title)
	
	def plotRegularXYZData(self, data, title="", colorBar=False):
		"""
		Plot xyz data in vectors x y z
		if range is set, will expect four entry vector with limiting range for plot sorted 
		as [xmin, xmax,ymin,ymax]
		"""
		
		self.image = self.axis.imshow(data, cmap=self.colorMap)
		
		if self.contourLines:
			self.axis.contour(x, y, z, colors='black', linewidths=1, shading='flat', extend='both')
		
		if (colorBar):
			self.figure.colorbar(self.image, orientation=self.colorBarOrientation)
		
		if (title):
			self.axis.set_title(title)
	
	def addLine(self, xdata, ydata, color='b', **kwargs):
		"""
		Add a line to the current axis
		
		xdata - numpy array of x values
		ydata - numpy array of y values
		color - color of the line
		"""
		line = matplotlib.lines.Line2D(xdata,ydata,color=color,**kwargs)
		self.axis.add_line(line)
	
	def addArrow(self, x, y, dx, dy, width=1.0):
		arrow = matplotlib.patches.Arrow(x, y, dx, dy, width=width)
		
		self.axis.add_patch(arrow)
	
	def plotScatterData(self, x, y, type=None, color='b', colorMap=None, colorBar=False, size=30, globalWidth=0.2, linewidths=None, setAsImage=True):
		if type == None:
			type = CIRCLE
		
		if globalWidth != None and not linewidths:
			linewidths = []
			for i in range(0, len(x)):
				linewidths.append(globalWidth)
		image = self.axis.scatter(x, y, s=size, c=color, cmap=colorMap, marker=type, linewidths=linewidths)
		if setAsImage:
			self.image = image
		
		if (colorBar):
			self.figure.colorbar(self.image)

	def loadXYFile(self, file):
		fp = open(file, "r")
		
		lines = fp.readlines()
		
		x = []
		y = []
		
		for line in lines:
			line = line.strip(" \t\n")
			if line.startswith("#"):
				continue
			lineSplit = line.split()
			if len(lineSplit) < 2:
				continue
			
			x.append(float(lineSplit[0]))
			y.append(float(lineSplit[1]))
		
		return x, y
	
	def plotPolygon(self, polygon, arrows=False, fill=False):
		poly = matplotlib.patches.Polygon(polygon, fill=fill)
		
		self.axis.add_patch(poly)
	
	def loadGMTPolygonFile(self, polyFile):
		fp = open(polyFile, "r")
		
		lines = fp.readlines()
		
		fp.close()
		
		return self.loadGMTPolygons(lines)
	
	def loadGMTPolygons(self, lines):
		polys = []
		
		curPoly = []
		
		for line in lines:
			line = line.strip(" \t\n")
			if line.startswith(">"):
				if len(curPoly) > 0:
					#print curPoly
					polys.append(curPoly)
					curPoly = []
				continue
			lineSplit = line.split()
			if len(lineSplit) < 2:
				print "bad polygon line parse!"
				continue
			poly = []
			poly.append(float(lineSplit[0]))
			poly.append(float(lineSplit[1]))
			#print "added: " + str(poly)
			curPoly.append(poly)
		
		return polys
	
	def getMainWidget(self):
		if (self.imageVisible):
			# return the Image Event Box for this image plotter
			
			self.image = gtk.Image()
			self.image.show()
			
			self.imageBuffer = 7
			self.imageEB = gtk.EventBox()
			self.imageEB.add(self.image)
			self.imageEB.modify_bg(gtk.STATE_NORMAL, gtk.gdk.color_parse(self.bgColor))
			self.imageEB.set_size_request(self.preferredWidth + self.imageBuffer, self.preferredHeight + self.imageBuffer)
			
			self.image.set_from_file(self.imageFile)
			
			self.mainWindow.setSaveActive(False)
			
			self.imageEB.show_all()
			
			return self.imageEB
		else:
			self.plotBuffer = 10
			self.canvas.show_all()
			self.canvas.set_size_request(self.preferredWidth + self.plotBuffer, self.preferredHeight + self.plotBuffer)
			return self.canvas
			
	
	def getBottomPanel(self):
		return self.gui
	
	def getSaveTypes(self):
		saveTypes = []
		saveTypes.append(["png", "PNG Image"])
		#saveTypes.append(["ps", "PostScript Plot"]) # should work, but doesn't for some reason
		saveTypes.append(["pdf", "Portable Document Format"])
		saveTypes.append(["svg", "Scalable Vector Graphics Format"])
		return saveTypes
	
	def savePlot(self, typeExtension, fileName):
		# don't check for save types since we only have 1
		if self.figure != None:
			self.figure.savefig(fileName, format=typeExtension)
			"""
			For some reason matplotlib doesn't reset the pixmap to the on screen one after
			rendering, so you can't replot anything until an event like a resize happens. This
			will get around that limitation
			"""
			self.canvas._renderer_init()
			self.canvas._pixmap = gtk.gdk.Pixmap (self.canvas.window, self.canvas._pixmap_width,
                                       self.canvas._pixmap_height)
			self.canvas._renderer.set_pixmap (self.canvas._pixmap)
			return True
		return False
	
	def displayImage(self, imageFile, default=False):
		"""
		This method will display an image file
		
		imageFile - the file name of the image to be displayed
		"""
		self.imageFile = imageFile
		self.image.set_from_file(self.imageFile)
		
		if not default:
			self.mainWindow.setSaveActive(True)
Exemplo n.º 33
0
class GuiBankrollGraphViewer (threading.Thread):

    def __init__(self, settings, db, querylist, config, parent, debug=True):
        """Constructor for GraphViewer"""
        self.settings = settings
        self.db = db
        self.sql = querylist
        self.conf = config
        self.debug = debug
        self.parent = parent
        #print "start of GraphViewer constructor"
        self.db = Database.Database(self.conf, sql=self.sql)

        view = None
        filters_display = { "Heroes"    : True,
                            "Sites"     : True,
                            "Games"     : False,
                            "Limits"    : False,
                            "LimitSep"  : False,
                            "LimitType" : False,
                            "Type"      : False,
                            "UseType"   : 'tour',
                            "Seats"     : False,
                            "SeatSep"   : False,
                            "Dates"     : True,
                            "Groups"    : False,
                            "Button1"   : True,
                            "Button2"   : True
                          }

        self.filters = Filters.Filters(self.db, self.conf, self.sql, display = filters_display)
        self.filters.registerButton1Name(_("Refresh _Graph"))
        self.filters.registerButton1Callback(self.generateGraph)
        self.filters.registerButton2Name(_("_Export to File"))
        self.filters.registerButton2Callback(self.exportGraph)

        numeric_const_pattern = r"""
            [-+]? # optional sign
            (?:
                (?: \d* \. \d+ ) # .1 .12 .123 etc 9.1 etc 98.1 etc
                |
                (?: \d+ \.? ) # 1. 12. 123. etc 1 12 123 etc
            )
            # followed by optional exponent part if desired
            (?: [Ee] [+-]? \d+ ) ?
            """
        self.rx = re.compile(numeric_const_pattern, re.VERBOSE)




        self.mainHBox = gtk.HBox(False, 0)
        self.mainHBox.show()

        self.leftPanelBox = self.filters.get_vbox()

        #add a button to modify transferts
        ButtonTransfert=gtk.Button(_("ButtonTransfert"))
        ButtonTransfert.set_label(_("_Modify Transferts"))
        ButtonTransfert.connect("clicked", self.transfertsWindow, "clicked")
        ButtonTransfert.set_sensitive(True)

        self.filters.mainVBox.pack_start(ButtonTransfert, False)
        ButtonTransfert.show()

        self.hpane = gtk.HPaned()
        self.hpane.pack1(self.leftPanelBox)
        self.mainHBox.add(self.hpane)
        # hierarchy:  self.mainHBox / self.hpane / self.graphBox / self.canvas / self.fig / self.ax

        self.graphBox = gtk.VBox(False, 0)
        self.graphBox.show()
        self.hpane.pack2(self.graphBox)
        self.hpane.show()

        self.fig = None
        #self.exportButton.set_sensitive(False)
        self.canvas = None

        #update the graph at entry (simulate a «Refresh Graph» click)
        gobject.GObject.emit (self.filters.Button1, "clicked");

        self.db.rollback()
        #endinit
    def get_vbox(self):
        """returns the vbox of this thread"""
        return self.mainHBox
    #end def get_vbox

    def clearGraphData(self):
        try:
            if self.canvas:
                self.graphBox.remove(self.canvas)
        except:
            pass

        if self.fig != None:
            self.fig.clear()
        self.fig = Figure(figsize=(5,4), dpi=100)
        if self.canvas is not None:
            self.canvas.destroy()

        self.canvas = FigureCanvas(self.fig)  # a gtk.DrawingArea

    def generateGraph(self, widget, data):
        self.clearGraphData()

        sitenos = []
        playerids = []

        sites   = self.filters.getSites()
        heroes  = self.filters.getHeroes()
        siteids = self.filters.getSiteIds()

        # Which sites are selected?
        for site in sites:
            if sites[site] == True:
                sitenos.append(siteids[site])
                _hname = Charset.to_utf8(heroes[site])
                result = self.db.get_player_id(self.conf, site, _hname)
                if result is not None:
                    playerids.append(int(result))

        if not sitenos:
            #Should probably pop up here.
            print _("No sites selected - defaulting to PokerStars")
            self.db.rollback()
            return

        if not playerids:
            print _("No player ids found")
            self.db.rollback()
            return

        #Set graph properties
        self.ax = self.fig.add_subplot(111)

        #Get graph data from DB
        starttime = time()
        (green, dates, transfersAmount, transfersDate, transferType) = self.getData(playerids, sitenos)
        print _("Graph generated in: %s") %(time() - starttime)


        #Set axis labels and grid overlay properites
        self.ax.set_ylabel("$", fontsize = 12)
        self.ax.grid(color='g', linestyle=':', linewidth=0.2)

        if green == None or green == []:
            self.ax.set_title(_("No Data for Player(s) Found"))
            green = ([    0.,     0.,     0.,     0.,   500.,  1000.,   900.,   800.,
                        700.,   600.,   500.,   400.,   300.,   200.,   100.,     0.,
                        500.,  1000.,  1000.,  1000.,  1000.,  1000.,  1000.,  1000.,
                        1000., 1000.,  1000.,  1000.,  1000.,  1000.,   875.,   750.,
                        625.,   500.,   375.,   250.,   125.,     0.,     0.,     0.,
                        0.,   500.,  1000.,   900.,   800.,   700.,   600.,   500.,
                        400.,   300.,   200.,   100.,     0.,   500.,  1000.,  1000.])
            red   =  ([    0.,     0.,     0.,     0.,   500.,  1000.,   900.,   800.,
                        700.,   600.,   500.,   400.,   300.,   200.,   100.,     0.,
                        0.,   0.,     0.,     0.,     0.,     0.,   125.,   250.,
                        375.,   500.,   500.,   500.,   500.,   500.,   500.,   500.,
                        500.,   500.,   375.,   250.,   125.,     0.,     0.,     0.,
                        0.,   500.,  1000.,   900.,   800.,   700.,   600.,   500.,
                        400.,   300.,   200.,   100.,     0.,   500.,  1000.,  1000.])
            blue =    ([    0.,     0.,     0.,     0.,   500.,  1000.,   900.,   800.,
                          700.,   600.,   500.,   400.,   300.,   200.,   100.,     0.,
                          0.,     0.,     0.,     0.,     0.,     0.,   125.,   250.,
                          375.,   500.,   625.,   750.,   875.,  1000.,   875.,   750.,
                          625.,   500.,   375.,   250.,   125.,     0.,     0.,     0.,
                        0.,   500.,  1000.,   900.,   800.,   700.,   600.,   500.,
                        400.,   300.,   200.,   100.,     0.,   500.,  1000.,  1000.])

            self.ax.plot(green, color='green', label=_('Bankroll') + _('Profit') + ': $%.2f' % green[-1])
            self.graphBox.add(self.canvas)
            self.canvas.show()
            self.canvas.draw()

            #TODO: Do something useful like alert user
        else:
            self.ax.set_title(_("Bankroll Results"))
            useDates = True

            #nothing to draw
            if (len(green) == 0):
                return
            #Get the dates of the action (transfert / cg hand / tourney)
            #if it has no date, get the most ancient date and assume it's its one
            if dates[0] is None:
                i = 1
                while i < len(dates) and type(dates[i]) is None:
                    i = i+1
                if i == len(dates):
                    print "Wow wow wow : no dates in your whole database"
                    useDates = False
                else:
                    dates[0] = dates[i]

            #now, convert date to dateTime format
            if useDates:
                for i in range(0, len(dates)):
                    if dates[i] is None:
                        dates[i] = dates[i-1]
                    #~else:
                        #~dates[i] = datetime.datetime.strptime(dates[i], "%Y-%m-%d %H:%M:%S")

            for i in range(0,  len(green)-1):
                beneficeSinceStart=green[i+1]-self.totalTransfer(dates[i+1], transfersAmount, transfersDate)
                mycolor = self.color(transferType[i+1], beneficeSinceStart)

                self.ax.plot([i,i+1], [green[i],green[i+1]], color=mycolor)
                #show date and gain only 5 times on X axis
                if (i % (len(green)/5) == 1):
                    #the gain since start at this time
                    if (mycolor=='cyan'): mycolor='green'
                    self.ax.annotate('%.2f' % beneficeSinceStart, xy=(i, 0), color=mycolor, xycoords=('data', 'axes fraction'),
                    xytext=(0, 18), textcoords='offset points', va='top', ha='left')

                    #and show the date too if enabled
                    if useDates:
                        dateMMDD=datetime.datetime.strptime(dates[i], "%Y-%m-%d %H:%M:%S").strftime('%d/%m')
                        self.ax.annotate(dateMMDD, xy=(i, 0), xycoords=('data', 'axes fraction'),
                        xytext=(0, -18), textcoords='offset points', va='top', ha='left')


            #plot the last one and show the top corner legend
            i = len(green)-1

            bankroll = float(green[i])
            profit = bankroll
            if len(transfersAmount)>0:
                profit -= transfersAmount[len(transfersAmount)-1]

            self.ax.plot([i,i+1], [green[i],green[i]], color=self.color(transferType[i], beneficeSinceStart),
                label=_('Bankroll') + ': \$%.2f' % bankroll + '\n' + _('Profit') + ': \$%.2f' % profit)

            legend = self.ax.legend(loc='upper left', fancybox=True, shadow=True, prop=FontProperties(size='smaller'))
            legend.draggable(True)

            self.graphBox.add(self.canvas)
            self.canvas.show()
            self.canvas.draw()
    #end of def showClicked

    #return total cash from transfer until «date»
    def totalTransfer(self, date, amounts, transfersDate):
        #~print transferts
        if len(amounts) == 0 or (date < transfersDate[0]):
            return 0

        i=0
        while (i < len(amounts)-1 and date > transfersDate[i]):
            i = i + 1
        return amounts[i]

    def color(self, typ, gain):
        # 0:play, 1:transfert
        if typ == 1:
            return 'cyan'
        elif gain < 0:
            return 'red'
        else:
            return 'green'

    def getData(self, names, sites):
        print "DEBUG: args are :"
        print names
        print sites

        tmp = self.rightRequest('getAllPrintIdSite', names, sites)
        tmp2 = self.rightRequest('getAllTransfer', names, sites)

        print "DEBUG: sql query:"
        print tmp
        self.db.cursor.execute(tmp)
        #returns (HandId,Winnings,Costs,Profit)
        winnings = self.db.cursor.fetchall()

        self.db.cursor.execute(tmp2)
        transfers = self.db.cursor.fetchall()
        self.db.rollback()

        if len(winnings) == 0:
            return None

        green = map(lambda x:float(x[0]), winnings)
        dates = map(lambda x:x[1], winnings)
        typeOf = map(lambda x:x[2], winnings)
        transferAmounts = map(lambda x:x[0], transfers)
        transferDates = map(lambda x:x[1], transfers)

        #blue  = map(lambda x: float(x[1]) if x[2] == True  else 0.0, winnings)
        #red   = map(lambda x: float(x[1]) if x[2] == False else 0.0, winnings)
        greenline = cumsum(green)

        #blueline  = cumsum(blue)
        #redline   = cumsum(red)

        transferAmounts = cumsum(transferAmounts)
        return (greenline/100., dates, transferAmounts, transferDates, typeOf)

    def exportGraph (self, widget, data):
        if self.fig is None:
            return # Might want to disable export button until something has been generated.

        dia_chooser = gtk.FileChooserDialog(title=_("Please choose the directory you wish to export to:"),
                                            action=gtk.FILE_CHOOSER_ACTION_SELECT_FOLDER,
                                            buttons=(gtk.STOCK_CANCEL,gtk.RESPONSE_CANCEL,gtk.STOCK_OK,gtk.RESPONSE_OK))
        dia_chooser.set_destroy_with_parent(True)
        dia_chooser.set_transient_for(self.parent)
        try:
            dia_chooser.set_filename(self.exportFile) # use previously chosen export path as default
        except:
            pass

        response = dia_chooser.run()

        if response <> gtk.RESPONSE_OK:
            print _('Closed, no graph exported')
            dia_chooser.destroy()
            return

        # generate a unique filename for export
        now = datetime.now()
        now_formatted = now.strftime("%Y%m%d%H%M%S")
        self.exportFile = dia_chooser.get_filename() + "/fpdb" + now_formatted + ".png"
        dia_chooser.destroy()

        #print "DEBUG: self.exportFile = %s" %(self.exportFile)
        self.fig.savefig(self.exportFile, format="png")

        #display info box to confirm graph created
        diainfo = gtk.MessageDialog(parent=self.parent,
                                flags=gtk.DIALOG_DESTROY_WITH_PARENT,
                                type=gtk.MESSAGE_INFO,
                                buttons=gtk.BUTTONS_OK,
                                message_format=_("Graph created"))
        diainfo.format_secondary_text(self.exportFile)
        diainfo.run()
        diainfo.destroy()

    #end of def exportGraph
    def transfertsWindow (self, widget, data) :
        #if the window is already launched, put it in front
        if not self.settings['global_lock'].acquire(wait=False, source="GuiBankrollGraphViewer"):
            return

        #create the window …
        #first, check if there is at least one player on database, else quit
        if (len(self.filters.getHeroes()) == 0):
            print "No site/hero found, abort"
            return


        self.transferWindow = gtk.Window(gtk.WINDOW_TOPLEVEL)
        self.transferWindow.set_title("Transferts Management")
        self.transferWindow.set_position(gtk.WIN_POS_CENTER)
        self.transferWindow.set_transient_for(self.parent)
        self.transferWindow.connect("destroy", self.release)
        vbox = gtk.VBox(False, 0)
        self.transferWindow.add(vbox)

        #####
        #####
        #«new transfert» part
        hboxAdd = gtk.HBox(True, 0)
        vbox.pack_start(hboxAdd)

        #calendar
        cal = gtk.Calendar()
        vboxSelection = gtk.VBox(False, 0)

        #hour selection
        hourLabel = gtk.Label(_('Select hour:'))
        hourLabel.set_alignment(xalign=0.0, yalign=0.5)

        hboxHour = gtk.HBox(False, 0)

        timeHourPicker = gtk.SpinButton(None, 0, 0);
        timeHourPicker.set_increments(1, 6)
        timeHourPicker.set_range(0, 23)
        timeHourPicker.set_value(datetime.datetime.now().hour) # current hour

        timeMinPicker = gtk.SpinButton(None, 0, 0);
        timeMinPicker.set_increments(1, 10)
        timeMinPicker.set_range(0, 59)
        timeMinPicker.set_value(datetime.datetime.now().minute) # current hour

        #site/hero selection
        IDLabel = gtk.Label(_('Site - hero:'))
        IDLabel.set_alignment(xalign=0.0, yalign=0.5)

        IDSelection = gtk.combo_box_new_text()

        for site, hero in self.filters.getHeroes().items():
            IDSelection.append_text(site + " - " + hero)

        IDSelection.set_active(0)
        #amount of virement
        amountLabel = gtk.Label(_('Tranfert amount ($):'))
        amountLabel.set_alignment(xalign=0.0, yalign=0.5)


        amountEntry = gtk.Entry()
        amountEntry.set_text('10.00')
        amountEntry.connect('changed', self.on_changed, 'changed')

        #button add
        buttonAdd = gtk.ToolButton(gtk.STOCK_ADD)
        buttonAdd.connect('clicked', self.newTransfer, 'clicked', cal, timeHourPicker, timeMinPicker, IDSelection, amountEntry)
        buttonAdd.connect('clicked', self.destroyWindow)

        hboxAdd.pack_start(cal, 0)
        hboxAdd.pack_start(vboxSelection, 0)
        vboxSelection.pack_start(hourLabel, 0)
        vboxSelection.pack_start(hboxHour, 0)
        hboxHour.pack_start(timeHourPicker, 0)
        hboxHour.pack_start(timeMinPicker, 0)
        vboxSelection.pack_start(IDLabel, 0)
        vboxSelection.pack_start(IDSelection, 0)
        vboxSelection.pack_start(amountLabel, 0)
        vboxSelection.pack_start(amountEntry, 0)
        vboxSelection.pack_start(buttonAdd, -1)

        #end of "new transfert" part
        #####
        ####

        ####
        #start of "delete transfert" part

        hboxDelete = gtk.HBox(False, 0)
        vbox.pack_start(hboxDelete)

        #tab to create
        vboxTab = gtk.VBox(False, 0)
        self.createTab(vboxTab)

        buttonDelete = gtk.ToolButton(gtk.STOCK_DELETE)
        buttonDelete.connect('clicked', self.deleteTransfer, 'clicked')


        hboxDelete.pack_start(vboxTab, 1)
        hboxDelete.pack_start(buttonDelete, 1)
        #end of "delete transfert" part
        ####


        self.transferWindow.show_all()
        return
    #end of def transfertsWindow
    def release(self, widget, data=None):
        self.settings['global_lock'].release()
        self.transferWindow.destroy()
        return
    def on_changed(self, widget, data):
        #~text = widget.get_text().strip()
        #~widget.set_text(''.join([i for i in text if i in '0123456789']))
        entry_text = widget.get_text()
        newtext = self.rx.findall(entry_text)
        if len(newtext) :
            widget.set_text(newtext[0])
        else:
            widget.set_text("")

    def destroyWindow(self, widget):
        self.transferWindow.destroy()
        return
    def newTransfer(self, widget, data, cal, timeHourPicker, timeMinPicker, IDSelection, amountEntry):
        year, month, day = cal.get_date()
        month = month + 1 # because gtk gives it between 0 and 11 ?!
        hour = timeHourPicker.get_value()
        minute = timeMinPicker.get_value()
        (site, separator, hero) = IDSelection.get_active_text().partition(' - ')
        transfer = float(amountEntry.get_text())

        now = datetime.datetime(year, month, day, int(hour), int(minute), 0)

        #get siteID from siteName (table "sites")
        self.db.cursor.execute('SELECT id from sites where name LIKE "' + site + '"')
        siteID = self.db.cursor.fetchall()[0][0]
        self.db.rollback()

        #get heroID from heroName and siteID (table "players")
        self.db.cursor.execute('select id from players where name LIKE "' + hero + '" and siteId = ' + str(siteID))
        heroID = self.db.cursor.fetchall()[0][0]
        self.db.rollback()

        #insert it in the table now
        query = "INSERT INTO BankrollsManagement(siteId, playerId, transfer, startTime) VALUES (?, ?, ?, ?)"
        #~print "DEBUG:\n%s" % query
        self.db.cursor.execute(query, (siteID, heroID, int(transfer*100), now))
        self.db.commit()
        self.db.rollback()

        #update the graph
        gobject.GObject.emit (self.filters.Button1, "clicked");

    def deleteTransfer(self, widget, data):
        #get the active line of the array
        selected = self.view.get_cursor()[0]

        #if no row selected, abort
        if selected is None:
            return
        #else, retrieve the line ( /!\ rowNumber != Id from the table ),
        rowNumber = selected[0]
        line = self.liststore[0][rowNumber]

        id = line[0]

        #then delete it from table and refresh graph
        self.db.cursor.execute('DELETE FROM BankrollsManagement WHERE id=' + str(id))
        self.db.commit()
        self.db.rollback()

        #destroy the window
        self.destroyWindow(widget)
        gobject.GObject.emit (self.filters.Button1, "clicked");

    def createTab(self, vbox) :
        cols_to_show =  [ ["id",            False, _("ID"),    0.0, "%s", "str"]
                        , ["siteName",      True,  _("Site"),    0.0, "%s", "str"]   # true not allowed for this line (set in code)
                        , ["playerName",    True,  _("Name"),    0.8, "%s", "str"]   # true not allowed for this line (set in code)
                        , ["amount",        True,  _("Amount"),    0.0, "%0.2f", "str"]
                        , ["date",          True, _("Date"),       0.0, "%s", "str"]]

        self.liststore=[]
        self.liststore.append( gtk.ListStore(*([str] * len(cols_to_show))) )
        self.view = gtk.TreeView(model=self.liststore[0])

        self.view.set_grid_lines(gtk.TREE_VIEW_GRID_LINES_BOTH)
        #vbox.pack_start(view, expand=False, padding=3)
        vbox.add(self.view)
        textcell = gtk.CellRendererText()
        textcell50 = gtk.CellRendererText()
        textcell50.set_property('xalign', 0.5)
        numcell = gtk.CellRendererText()
        numcell.set_property('xalign', 1.0)

        listcols = []
        listcols.append( [] )
        # Create header row   eg column: ("game",     True, "Game",     0.0, "%s")
        for i, col in enumerate(cols_to_show):
            listcols[0].append(gtk.TreeViewColumn(col[_COL_HEADING]))

            self.view.append_column(listcols[0][i])
            if col[_COL_FORMAT] == '%s':
                if col[_COL_XALIGN] == 0.0:
                    listcols[0][i].pack_start(textcell, expand=True)
                    listcols[0][i].add_attribute(textcell, 'text', i)
                    cellrend = textcell
                else:
                    listcols[0][i].pack_start(textcell50, expand=True)
                    listcols[0][i].add_attribute(textcell50, 'text', i)
                    cellrend = textcell50
                listcols[0][i].set_expand(True)
            else:
                listcols[0][i].pack_start(numcell, expand=True)
                listcols[0][i].add_attribute(numcell, 'text', i)
                listcols[0][i].set_expand(True)
                cellrend = numcell

        query = self.sql.query['getAllTransferInformations']

        #~print "DEBUG:\n%s" % query
        self.db.cursor.execute(query)

        result = self.db.cursor.fetchall()
        #~print "result of the big query in addGrid:",result
        colnames = [desc[0] for desc in self.db.cursor.description]



        #~for i in range(0, len(tab))
        rows = len(result) # +1 for title row
        counter = 0
        row = 0
        sqlrow = 0
        while sqlrow < rows:
            treerow = []
            for col,column in enumerate(cols_to_show):
                if column[_COL_ALIAS] in colnames:
                    if column[_COL_ALIAS] == 'amount':
                        #convert $ cents to $
                        value = result[sqlrow][colnames.index(column[_COL_ALIAS])]/100.
                    else:
                        value = result[sqlrow][colnames.index(column[_COL_ALIAS])]
                else:
                    value = 111

                if value != None and value != -999:
                    treerow.append(column[_COL_FORMAT] % value)
                else:
                    treerow.append(' ')
            #print "addGrid, just before end of big for. grid:",grid,"treerow:",treerow
            iter = self.liststore[0].append(treerow)
            sqlrow += 1
            row += 1
        vbox.show_all()

    def rightRequest(self, request, names, sites):
        tmp = self.sql.query[request]
        print "DEBUG: getData. :"
        start_date, end_date = self.filters.getDates()

        #Buggered if I can find a way to do this 'nicely' take a list of integers and longs
        # and turn it into a tuple readale by sql.
        # [5L] into (5) not (5,) and [5L, 2829L] into (5, 2829)
        nametest = str(tuple(names))
        sitetest = str(tuple(sites))

        #Must be a nicer way to deal with tuples of size 1 ie. (2,) - which makes sql barf
        tmp = tmp.replace("<player_test>", nametest)
        tmp = tmp.replace("<site_test>", sitetest)
        tmp = tmp.replace("<startdate_test>", start_date)
        tmp = tmp.replace("<enddate_test>", end_date)
        tmp = tmp.replace(",)", ")")

        return tmp
Exemplo n.º 34
0
class GuiSessionViewer (threading.Thread):
    def __init__(self, config, querylist, mainwin, debug=True):
        self.debug = debug
        self.conf = config
        self.sql = querylist

        self.liststore = None

        self.MYSQL_INNODB   = 2
        self.PGSQL          = 3
        self.SQLITE         = 4

        self.fig = None
        self.canvas = None
        self.ax = None
        self.graphBox = None
        
        # create new db connection to avoid conflicts with other threads
        self.db = Database.Database(self.conf, sql=self.sql)
        self.cursor = self.db.cursor

        settings = {}
        settings.update(self.conf.get_db_parameters())
        settings.update(self.conf.get_import_parameters())
        settings.update(self.conf.get_default_paths())

        # text used on screen stored here so that it can be configured
        self.filterText = {'handhead':_('Hand Breakdown for all levels listed above')}

        filters_display = { "Heroes"    : True,
                            "Sites"     : True,
                            "Games"     : False,
                            "Limits"    : False,
                            "LimitSep"  : False,
                            "LimitType" : False,
                            "Type"      : True,
                            "Seats"     : False,
                            "SeatSep"   : False,
                            "Dates"     : True,
                            "Groups"    : False,
                            "GroupsAll" : False,
                            "Button1"   : True,
                            "Button2"   : False
                          }

        self.filters = Filters.Filters(self.db, self.conf, self.sql, display = filters_display)
        self.filters.registerButton1Name("_Refresh")
        self.filters.registerButton1Callback(self.refreshStats)

        # ToDo: store in config
        # ToDo: create popup to adjust column config
        # columns to display, keys match column name returned by sql, values in tuple are:
        #     is column displayed, column heading, xalignment, formatting
        self.columns = [ ("sid",      True,  "SID",      0.0, "%s")
                       , ("hand",     False, "Hand",     0.0, "%s")   # true not allowed for this line
                       , ("n",        True,  "Hds",      1.0, "%d")
                       , ("start",    True,  "Start",    1.0, "%d")
                       , ("end",      True,  "End",      1.0, "%d")
                       , ("hph",      True,  "Hands/h",  1.0, "%d")
                       , ("profit",   True,  "Profit",   1.0, "%s")
                       #, ("avgseats", True,  "Seats",    1.0, "%3.1f")
                       #, ("vpip",     True,  "VPIP",     1.0, "%3.1f")
                       #, ("pfr",      True,  "PFR",      1.0, "%3.1f")
                       #, ("pf3",      True,  "PF3",      1.0, "%3.1f")
                       #, ("steals",   True,  "Steals",   1.0, "%3.1f")
                       #, ("saw_f",    True,  "Saw_F",    1.0, "%3.1f")
                       #, ("sawsd",    True,  "SawSD",    1.0, "%3.1f")
                       #, ("wtsdwsf",  True,  "WtSDwsF",  1.0, "%3.1f")
                       #, ("wmsd",     True,  "W$SD",     1.0, "%3.1f")
                       #, ("flafq",    True,  "FlAFq",    1.0, "%3.1f")
                       #, ("tuafq",    True,  "TuAFq",    1.0, "%3.1f")
                       #, ("rvafq",    True,  "RvAFq",    1.0, "%3.1f")
                       #, ("pofafq",   False, "PoFAFq",   1.0, "%3.1f")
                       #, ("net",      True,  "Net($)",   1.0, "%6.2f")
                       #, ("bbper100", True,  "BB/100",   1.0, "%4.2f")
                       #, ("rake",     True,  "Rake($)",  1.0, "%6.2f")
                       #, ("variance", True,  "Variance", 1.0, "%5.2f")
                       ]

        self.stats_frame = None
        self.stats_vbox = None
        self.detailFilters = []   # the data used to enhance the sql select

        #self.main_hbox = gtk.HBox(False, 0)
        #self.main_hbox.show()
        self.main_hbox = gtk.HPaned()

        self.stats_frame = gtk.Frame()
        self.stats_frame.show()

        self.stats_vbox = gtk.VBox(False, 0)
        self.stats_vbox.show()
        self.stats_frame.add(self.stats_vbox)
        # self.fillStatsFrame(self.stats_vbox)

        #self.main_hbox.pack_start(self.filters.get_vbox())
        #self.main_hbox.pack_start(self.stats_frame, expand=True, fill=True)
        self.main_hbox.pack1(self.filters.get_vbox())
        self.main_hbox.pack2(self.stats_frame)
        self.main_hbox.show()

        # make sure Hand column is not displayed
        #[x for x in self.columns if x[0] == 'hand'][0][1] = False

    def get_vbox(self):
        """returns the vbox of this thread"""
        return self.main_hbox



    def refreshStats(self, widget, data):
        try: self.stats_vbox.destroy()
        except AttributeError: pass
        self.stats_vbox = gtk.VBox(False, 0)
        self.stats_vbox.show()
        self.stats_frame.add(self.stats_vbox)
        self.fillStatsFrame(self.stats_vbox)

    def fillStatsFrame(self, vbox):
        sites = self.filters.getSites()
        heroes = self.filters.getHeroes()
        siteids = self.filters.getSiteIds()
        limits  = self.filters.getLimits()
        seats  = self.filters.getSeats()
        sitenos = []
        playerids = []

        # Which sites are selected?
        for site in sites:
            if sites[site] == True:
                sitenos.append(siteids[site])
                _q = self.sql.query['getPlayerId']
                _name = Charset.to_utf8(heroes[site])
                #print 'DEBUG(_name) :: %s' % _name
                self.cursor.execute(_q, (_name,)) # arg = tuple
                result = self.db.cursor.fetchall()
                if len(result) == 1:
                    playerids.append(result[0][0])

        if not sitenos:
            #Should probably pop up here.
            print _("No sites selected - defaulting to PokerStars")
            sitenos = [2]
        if not playerids:
            print _("No player ids found")
            return
        if not limits:
            print _("No limits found")
            return

        self.createStatsPane(vbox, playerids, sitenos, limits, seats)

    def createStatsPane(self, vbox, playerids, sitenos, limits, seats):
        starttime = time()

        (results, opens, closes, highs, lows) = self.generateDatasets(playerids, sitenos, limits, seats)



        self.graphBox = gtk.VBox(False, 0)
        self.graphBox.show()
        self.generateGraph(opens, closes, highs, lows)

        vbox.pack_start(self.graphBox)
        # Separator
        sep = gtk.HSeparator()
        vbox.pack_start(sep, expand=False, padding=3)
        sep.show_now()
        vbox.show_now()
        heading = gtk.Label(self.filterText['handhead'])
        heading.show()
        vbox.pack_start(heading, expand=False, padding=3)

        # Scrolled window for detailed table (display by hand)
        swin = gtk.ScrolledWindow(hadjustment=None, vadjustment=None)
        swin.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
        swin.show()
        vbox.pack_start(swin, expand=True, padding=3)

        vbox1 = gtk.VBox(False, 0)
        vbox1.show()
        swin.add_with_viewport(vbox1)

        self.addTable(vbox1, results)

        self.db.rollback()
        print _("Stats page displayed in %4.2f seconds") % (time() - starttime)
    #end def fillStatsFrame(self, vbox):

    def generateDatasets(self, playerids, sitenos, limits, seats):
        THRESHOLD = 1800                    # Minimum number of seconds between consecutive hands before being considered a new session
        PADDING   = 5                       # Additional time in minutes to add to a session, session startup, shutdown etc (FiXME: user configurable)

        # Get a list of all handids and their timestampts
        #FIXME: Query still need to filter on blind levels

        q = self.sql.query['sessionStats']
        start_date, end_date = self.filters.getDates()
        q = q.replace("<datestest>", " between '" + start_date + "' and '" + end_date + "'")

        nametest = str(tuple(playerids))
        nametest = nametest.replace("L", "")
        nametest = nametest.replace(",)",")")
        q = q.replace("<player_test>", nametest)
        q = q.replace("<ampersand_s>", "%s")

        self.db.cursor.execute(q)
        hands = self.db.cursor.fetchall()

        # Take that list and create an array of the time between hands
        times = map(lambda x:long(x[0]), hands)
        handids = map(lambda x:int(x[1]), hands)
        winnings = map(lambda x:float(x[4]), hands)
        #print "DEBUG: len(times) %s" %(len(times))
        diffs = diff(times)                      # This array is the difference in starttime between consecutive hands
        diffs2 = append(diffs,THRESHOLD + 1)     # Append an additional session to the end of the diffs, so the next line
                                                 # includes an index into the last 'session'
        index = nonzero(diffs2 > THRESHOLD)      # This array represents the indexes into 'times' for start/end times of sessions
                                                 # times[index[0][0]] is the end of the first session,
        #print "DEBUG: len(index[0]) %s" %(len(index[0]))
        if len(index[0]) > 0:
            #print "DEBUG: index[0][0] %s" %(index[0][0])
            #print "DEBUG: index %s" %(index)
            pass
        else:
            index = [[0]]
            #print "DEBUG: index %s" %(index)
            #print "DEBUG: index[0][0] %s" %(index[0][0])
            pass

        total = 0
        first_idx = 0
        lowidx = 0
        uppidx = 0
        opens = []
        closes = []
        highs = []
        lows = []
        results = []
        cum_sum = cumsum(winnings)
        cum_sum = cum_sum/100
        sid = 1
        # Take all results and format them into a list for feeding into gui model.
        for i in range(len(index[0])):
            hds = index[0][i] - first_idx + 1                                        # Number of hands in session
            if hds > 0:
                stime = strftime("%d/%m/%Y %H:%M", localtime(times[first_idx]))      # Formatted start time
                etime = strftime("%d/%m/%Y %H:%M", localtime(times[index[0][i]]))   # Formatted end time
                minutesplayed = (times[index[0][i]] - times[first_idx])/60
                if minutesplayed == 0:
                    minutesplayed = 1
                minutesplayed = minutesplayed + PADDING
                hph = hds*60/minutesplayed # Hands per hour
                won = sum(winnings[first_idx:index[0][i]])/100.0
                hwm = max(cum_sum[first_idx:index[0][i]])
                lwm = min(cum_sum[first_idx:index[0][i]])
                open = (sum(winnings[:first_idx]))/100
                close = (sum(winnings[:index[0][i]]))/100
                #print "DEBUG: range: (%s, %s) - (min, max): (%s, %s) - (open,close): (%s, %s)" %(first_idx, index[0][i], lwm, hwm, open, close)
            
                results.append([sid, hds, stime, etime, hph, won])
                opens.append(open)
                closes.append(close)
                highs.append(hwm)
                lows.append(lwm)
                #print "DEBUG: Hands in session %4s: %4s  Start: %s End: %s HPH: %s Profit: %s" %(sid, hds, stime, etime, hph, won)
                total = total + (index[0][i] - first_idx)
                first_idx = index[0][i] + 1
                sid = sid+1
            else:
                print "hds <= 0"

        return (results, opens, closes, highs, lows)

    def clearGraphData(self):

        try:
            try:
                if self.canvas:
                    self.graphBox.remove(self.canvas)
            except:
                pass

            if self.fig is not None:
                self.fig.clear()
            self.fig = Figure(figsize=(5,4), dpi=100)
            if self.canvas is not None:
                self.canvas.destroy()

            self.canvas = FigureCanvas(self.fig)  # a gtk.DrawingArea
        except:
            err = traceback.extract_tb(sys.exc_info()[2])[-1]
            print _("***Error: ")+err[2]+"("+str(err[1])+"): "+str(sys.exc_info()[1])
            raise


    def generateGraph(self, opens, closes, highs, lows):
        self.clearGraphData()

#        print "DEBUG:"
#        print "highs = %s" % highs
#        print "lows = %s" % lows
#        print "opens = %s" % opens
#        print "closes = %s" % closes
#        print "len(highs): %s == len(lows): %s" %(len(highs), len(lows))
#        print "len(opens): %s == len(closes): %s" %(len(opens), len(closes))
#
#        for i in range(len(highs)):
#            print "DEBUG: (%s, %s, %s, %s)" %(lows[i], opens[i], closes[i], highs[i])
#            print "DEBUG: diffs h/l: %s o/c: %s" %(lows[i] - highs[i], opens[i] - closes[i])

        self.ax = self.fig.add_subplot(111)

        self.ax.set_title(_("Session candlestick graph"))

        #Set axis labels and grid overlay properites
        self.ax.set_xlabel(_("Sessions"), fontsize = 12)
        self.ax.set_ylabel("$", fontsize = 12)
        self.ax.grid(color='g', linestyle=':', linewidth=0.2)

        candlestick2(self.ax, opens, closes, highs, lows, width=0.50, colordown='r', colorup='g', alpha=1.00)
        self.graphBox.add(self.canvas)
        self.canvas.show()
        self.canvas.draw()

    def addTable(self, vbox, results):
        row = 0
        sqlrow = 0
        colalias,colshow,colheading,colxalign,colformat = 0,1,2,3,4

        # pre-fetch some constant values:
        cols_to_show = [x for x in self.columns if x[colshow]]

        self.liststore = gtk.ListStore(*([str] * len(cols_to_show)))
        for row in results:
            iter = self.liststore.append(row)

        view = gtk.TreeView(model=self.liststore)
        view.set_grid_lines(gtk.TREE_VIEW_GRID_LINES_BOTH)
        vbox.add(view)
        textcell = gtk.CellRendererText()
        textcell50 = gtk.CellRendererText()
        textcell50.set_property('xalign', 0.5)
        numcell = gtk.CellRendererText()
        numcell.set_property('xalign', 1.0)
        listcols = []

        # Create header row   eg column: ("game",     True, "Game",     0.0, "%s")
        for col, column in enumerate(cols_to_show):
            s = column[colheading]
            listcols.append(gtk.TreeViewColumn(s))
            view.append_column(listcols[col])
            if column[colformat] == '%s':
                if column[colxalign] == 0.0:
                    listcols[col].pack_start(textcell, expand=True)
                    listcols[col].add_attribute(textcell, 'text', col)
                else:
                    listcols[col].pack_start(textcell50, expand=True)
                    listcols[col].add_attribute(textcell50, 'text', col)
                listcols[col].set_expand(True)
            else:
                listcols[col].pack_start(numcell, expand=True)
                listcols[col].add_attribute(numcell, 'text', col)
                listcols[col].set_expand(True)

        vbox.show_all()
Exemplo n.º 35
0
class GuiTourneyGraphViewer (threading.Thread):

    def __init__(self, querylist, config, parent, debug=True):
        """Constructor for GraphViewer"""
        self.sql = querylist
        self.conf = config
        self.debug = debug
        self.parent = parent
        #print "start of GraphViewer constructor"
        self.db = Database.Database(self.conf, sql=self.sql)


        filters_display = { "Heroes"    : True,
                            "Sites"     : True,
                            "Games"     : False,
                            "Limits"    : False,
                            "LimitSep"  : False,
                            "LimitType" : False,
                            "Type"      : False,
                            "UseType"   : 'tour',
                            "Seats"     : False,
                            "SeatSep"   : False,
                            "Dates"     : True,
                            "Groups"    : False,
                            "Button1"   : True,
                            "Button2"   : True
                          }

        self.filters = Filters.Filters(self.db, self.conf, self.sql, display = filters_display)
        self.filters.registerButton1Name(_("Refresh _Graph"))
        self.filters.registerButton1Callback(self.generateGraph)
        self.filters.registerButton2Name(_("_Export to File"))
        self.filters.registerButton2Callback(self.exportGraph)

        self.mainHBox = gtk.HBox(False, 0)
        self.mainHBox.show()

        self.leftPanelBox = self.filters.get_vbox()

        self.hpane = gtk.HPaned()
        self.hpane.pack1(self.leftPanelBox)
        self.mainHBox.add(self.hpane)
        # hierarchy:  self.mainHBox / self.hpane / self.graphBox / self.canvas / self.fig / self.ax

        self.graphBox = gtk.VBox(False, 0)
        self.graphBox.show()
        self.hpane.pack2(self.graphBox)
        self.hpane.show()

        self.fig = None
        #self.exportButton.set_sensitive(False)
        self.canvas = None


        self.db.rollback()

    def get_vbox(self):
        """returns the vbox of this thread"""
        return self.mainHBox
    #end def get_vbox

    def clearGraphData(self):
        try:
            if self.canvas:
                self.graphBox.remove(self.canvas)
        except:
            pass

        if self.fig != None:
            self.fig.clear()
        self.fig = Figure(figsize=(5,4), dpi=100)
        if self.canvas is not None:
            self.canvas.destroy()

        self.canvas = FigureCanvas(self.fig)  # a gtk.DrawingArea

    def generateGraph(self, widget, data):
        self.clearGraphData()

        sitenos = []
        playerids = []

        sites   = self.filters.getSites()
        heroes  = self.filters.getHeroes()
        siteids = self.filters.getSiteIds()

        # Which sites are selected?
        for site in sites:
            if sites[site] == True:
                sitenos.append(siteids[site])
                _hname = Charset.to_utf8(heroes[site])
                result = self.db.get_player_id(self.conf, site, _hname)
                if result is not None:
                    playerids.append(int(result))

        if not sitenos:
            #Should probably pop up here.
            print _("No sites selected - defaulting to PokerStars")
            self.db.rollback()
            return

        if not playerids:
            print _("No player ids found")
            self.db.rollback()
            return

        #Set graph properties
        self.ax = self.fig.add_subplot(111)

        #Get graph data from DB
        starttime = time()
        green = self.getData(playerids, sitenos)
        print _("Graph generated in: %s") %(time() - starttime)


        #Set axis labels and grid overlay properites
        self.ax.set_xlabel(_("Tournaments"), fontsize = 12)
        self.ax.set_ylabel("$", fontsize = 12)
        self.ax.grid(color='g', linestyle=':', linewidth=0.2)
        if green == None or green == []:
            self.ax.set_title(_("No Data for Player(s) Found"))
            green = ([    0.,     0.,     0.,     0.,   500.,  1000.,   900.,   800.,
                        700.,   600.,   500.,   400.,   300.,   200.,   100.,     0.,
                        500.,  1000.,  1000.,  1000.,  1000.,  1000.,  1000.,  1000.,
                        1000., 1000.,  1000.,  1000.,  1000.,  1000.,   875.,   750.,
                        625.,   500.,   375.,   250.,   125.,     0.,     0.,     0.,
                        0.,   500.,  1000.,   900.,   800.,   700.,   600.,   500.,
                        400.,   300.,   200.,   100.,     0.,   500.,  1000.,  1000.])
            red   =  ([    0.,     0.,     0.,     0.,   500.,  1000.,   900.,   800.,
                        700.,   600.,   500.,   400.,   300.,   200.,   100.,     0.,
                        0.,   0.,     0.,     0.,     0.,     0.,   125.,   250.,
                        375.,   500.,   500.,   500.,   500.,   500.,   500.,   500.,
                        500.,   500.,   375.,   250.,   125.,     0.,     0.,     0.,
                        0.,   500.,  1000.,   900.,   800.,   700.,   600.,   500.,
                        400.,   300.,   200.,   100.,     0.,   500.,  1000.,  1000.])
            blue =    ([    0.,     0.,     0.,     0.,   500.,  1000.,   900.,   800.,
                          700.,   600.,   500.,   400.,   300.,   200.,   100.,     0.,
                          0.,     0.,     0.,     0.,     0.,     0.,   125.,   250.,
                          375.,   500.,   625.,   750.,   875.,  1000.,   875.,   750.,
                          625.,   500.,   375.,   250.,   125.,     0.,     0.,     0.,
                        0.,   500.,  1000.,   900.,   800.,   700.,   600.,   500.,
                        400.,   300.,   200.,   100.,     0.,   500.,  1000.,  1000.])

            self.ax.plot(green, color='green', label=_('Tournaments') + ': %d\n' % len(green) + _('Profit') + ': $%.2f' % green[-1])
            self.graphBox.add(self.canvas)
            self.canvas.show()
            self.canvas.draw()

            #TODO: Do something useful like alert user
        else:
            self.ax.set_title(_("Tournament Results"))

            #Draw plot
            self.ax.plot(green, color='green', label=_('Tournaments') + ': %d\n' % len(green) + _('Profit') + ': $%.2f' % green[-1])

            legend = self.ax.legend(loc='upper left', fancybox=True, shadow=True, prop=FontProperties(size='smaller'))
            legend.draggable(True)
            
            self.graphBox.add(self.canvas)
            self.canvas.show()
            self.canvas.draw()
            #self.exportButton.set_sensitive(True)

    #end of def showClicked

    def getData(self, names, sites):
        tmp = self.sql.query['tourneyResults']
        print "DEBUG: getData"
        start_date, end_date = self.filters.getDates()

        #Buggered if I can find a way to do this 'nicely' take a list of integers and longs
        # and turn it into a tuple readale by sql.
        # [5L] into (5) not (5,) and [5L, 2829L] into (5, 2829)
        nametest = str(tuple(names))
        sitetest = str(tuple(sites))

        #Must be a nicer way to deal with tuples of size 1 ie. (2,) - which makes sql barf
        tmp = tmp.replace("<player_test>", nametest)
        tmp = tmp.replace("<site_test>", sitetest)
        tmp = tmp.replace("<startdate_test>", start_date)
        tmp = tmp.replace("<enddate_test>", end_date)
        tmp = tmp.replace(",)", ")")

        print "DEBUG: sql query:"
        print tmp
        self.db.cursor.execute(tmp)
        #returns (HandId,Winnings,Costs,Profit)
        winnings = self.db.cursor.fetchall()
        self.db.rollback()

        if len(winnings) == 0:
            return None

        green = map(lambda x:float(x[1]), winnings)
        #blue  = map(lambda x: float(x[1]) if x[2] == True  else 0.0, winnings)
        #red   = map(lambda x: float(x[1]) if x[2] == False else 0.0, winnings)
        greenline = cumsum(green)
        #blueline  = cumsum(blue)
        #redline   = cumsum(red)
        return (greenline/100)

    def exportGraph (self, widget, data):
        if self.fig is None:
            return # Might want to disable export button until something has been generated.

        dia_chooser = gtk.FileChooserDialog(title=_("Please choose the directory you wish to export to:"),
                                            action=gtk.FILE_CHOOSER_ACTION_SELECT_FOLDER,
                                            buttons=(gtk.STOCK_CANCEL,gtk.RESPONSE_CANCEL,gtk.STOCK_OK,gtk.RESPONSE_OK))
        dia_chooser.set_destroy_with_parent(True)
        dia_chooser.set_transient_for(self.parent)
        try: 
            dia_chooser.set_filename(self.exportFile) # use previously chosen export path as default
        except:
            pass

        response = dia_chooser.run()
        
        if response <> gtk.RESPONSE_OK:
            print _('Closed, no graph exported')
            dia_chooser.destroy()
            return
            
        # generate a unique filename for export
        now = datetime.now()
        now_formatted = now.strftime("%Y%m%d%H%M%S")
        self.exportFile = dia_chooser.get_filename() + "/fpdb" + now_formatted + ".png"
        dia_chooser.destroy()
        
        #print "DEBUG: self.exportFile = %s" %(self.exportFile)
        self.fig.savefig(self.exportFile, format="png")

        #display info box to confirm graph created
        diainfo = gtk.MessageDialog(parent=self.parent,
                                flags=gtk.DIALOG_DESTROY_WITH_PARENT,
                                type=gtk.MESSAGE_INFO,
                                buttons=gtk.BUTTONS_OK,
                                message_format=_("Graph created"))
        diainfo.format_secondary_text(self.exportFile)          
        diainfo.run()
        diainfo.destroy()
Exemplo n.º 36
0
class ComponentChooser(gtk.Window):
    """Used for selecting components to use for remixing"""
    
    components = None # Contains the components to choose from
    data = None # Contains the original data
    choose_mask = []
    
    def __init__(self, _components = None, _data=None):
        self.components = _components
        self.data = _data
        
        gtk.Window.__init__(self,gtk.WINDOW_TOPLEVEL)
        self.set_default_size(700,500)
        self.set_title("Choose components to use...")
        self.connect("delete_event", self.delete_event)
        self.connect("destroy", self.delete_event)
        
        self.vbox = gtk.VBox()
        self.add(self.vbox)
        self.f = Figure(figsize=(5,4), dpi=100, subplotpars=SubplotParams(left=0.06, top=0.95, right=0.97, bottom=0.1))
        self.setupSubplots()
        self.plotAll()
        self.canvas = FigureCanvas(self.f)
        self.canvas.mpl_connect('button_press_event', self.cb_canvas)
        self.vbox.pack_start(self.canvas)
        self.toolbar = NavigationToolbar( self.canvas, self.window )
        self.vbox.pack_start(self.toolbar, False, False)
        self.show_all()
        
    def delete_event(self, widget, event, data=None):
        self.hide()
        return True
    
    def cb_canvas(self, event):
        """Called when the figure is clicked.""" 
        #print event.button
        if event.button == 3:   
            for i,a in enumerate(self.axs):
                if event.inaxes == a:
                    #print "Subplot %i geclickt" % i
                    self.choose_mask[i] = bool(True-self.choose_mask[i])
                    #print self.choose_mask[i]
                    #a.grid()
                    a.cla()
                    #TODO: plotte...
                    a.plot(self.components[:,i])
                    #
                    if not self.choose_mask[i]:
                        a.text(numpy.array(a.get_xlim()).mean(),numpy.array(a.get_ylim()).mean(),"X",horizontalalignment='center',verticalalignment='center',fontsize=20,color="red")
                    self.canvas.draw()
                    
        
    def setupSubplots(self):
        self.f.clear()
        try:
            ncols = 4
            nrows = self.components.shape[1]/ncols +1
            self.axs = []
            self.choose_mask = []
            for i in range(self.components.shape[1]):
                self.axs.append(self.f.add_subplot(nrows,ncols,i+1))
                self.choose_mask.append(True)
        except Exception, e:
            print "Error while setting up subplots", e
Exemplo n.º 37
0
class XYDialog:
    def __init__(self, title, parent, filename, tmpn, type):
        # create matplotlib figure
        self.figure = Figure()
        self.canvas = FigureCanvas(self.figure)
        self.mp = ManipulateXYData(filename,
                                   type,
                                   self.figure,
                                   self,
                                   tmpn=tmpn)

        # create GTK dialog
        self.dialog = gtk.Dialog(title=title,
                                 parent=parent,
                                 flags=gtk.DIALOG_MODAL
                                 | gtk.DIALOG_DESTROY_WITH_PARENT)
        self.dialog.set_default_size(500, 400)
        self.vBox = self.dialog.vbox

        # setup matplotlib events
        self.canvas.mpl_connect('button_press_event', self.mp.on_click)
        self.canvas.mpl_connect('button_release_event', self.mp.on_release)

        # create buttons
        self.buttonBox = gtk.HBox(homogeneous=True, spacing=5)
        self.saveButton = gtk.Button(label="Save and Use",
                                     stock=gtk.STOCK_SAVE)
        self.useButton = gtk.Button(label="Use")
        self.revertButton = gtk.Button(label="Revert")
        self.cancelButton = gtk.Button(label="Cancel")

        # pack buttons
        self.buttonBox.pack_start(self.saveButton, expand=False)
        self.buttonBox.pack_start(self.useButton, expand=False)
        self.buttonBox.pack_start(self.revertButton, expand=False)
        self.buttonBox.pack_end(self.cancelButton, expand=False)

        # connect buttons
        self.use = False
        self.save = False
        self.saveButton.connect("clicked", self.saveHandler)
        self.useButton.connect("clicked", self.useHandler)
        self.revertButton.connect("clicked", self.revertHandler)
        self.cancelButton.connect("clicked", self.cancelHandler)

        # pack and show dialog
        self.vBox.pack_start(self.canvas, expand=True)
        self.vBox.pack_start(gtk.HSeparator(), expand=False)
        self.vBox.pack_end(self.buttonBox, expand=False)
        self.dialog.show_all()

    def redraw(self):
        self.canvas.draw()

    def saveHandler(self, widget):
        self.mp.save_to_file()
        self.save = True
        self.exit()

    def useHandler(self, widget):
        self.mp.save_to_file()
        self.use = True
        self.save = False
        self.exit()

    def revertHandler(self, widget):
        self.mp.reset_data()

    def cancelHandler(self, widget):
        self.save = False
        self.use = False
        self.exit()

    def exit(self):
        self.dialog.hide()
        #self.dialog.response(0)
Exemplo n.º 38
0
class Backend( backend.Backend ):

    def init(self):
        
        self.layer_to_axes = {}
        self.axes_to_layer = {}
        self.layers_cache = [] # copy of self.plot.layers
        self.layer_signals = {}
        
        self.line_caches = {}
        self.omaps = {}
        
        
    def connect(self):
        logger.debug("Opening matplotlib session.")        

        self.figure = Figure(dpi=100, facecolor="white")  # figsize=(5,4), dpi=100)        
        self.canvas = FigureCanvas(self.figure)
        self.canvas.show()

        self.line_caches = {}
        self.layer_to_axes.clear()
        self.axes_to_layer.clear()

        backend.Backend.connect(self)
        logger.debug("Init finished")


    def set(self, project,plot):
        backend.Backend.set(self, project, plot)
        if self.project is not None:
            # TODO: connect to notify::layers of Plot
            pass

    def disconnect(self):
        logger.debug("Closing matplotlib session.")

        if not self.canvas is None:
            self.canvas.destroy()
            self.canvas = None
        if not self.figure is None:
            self.figure = None
        
        backend.Backend.disconnect(self)


        

    #----------------------------------------------------------------------

    def arrange(self, rows=1, cols=1):

        layers = self.plot.layers
        n = len(layers)

        if n > (rows*cols):
            rows = int((rows*cols) / n) + 1
            cols = rows * n
            #raise ValueError("Not enough rows and cols for all layers!")

        self.figure.clear()
        self.figure.axes = []
        
        self.layer_to_axes.clear()
        self.axes_to_layer.clear()
        self.layers_cache = []

        for signal_list in self.layer_signals.itervalues():
            for signal in signal_list:
                Signals.disconnect(signal)
        self.layer_signals = {}
        
        j = 1
        for layer in layers:
            print "Setting up layer", layer
            axes = self.figure.add_subplot("%d%d%d" % (rows,cols,j))
            self.layer_to_axes[layer] = axes
            self.axes_to_layer[axes] = layer
            self.layers_cache.append(layer)

            print "Connecting to notify of ", layer
            self.layer_signals[layer] = \
              [Signals.connect(layer, 'notify', self.on_update_sobject),
               Signals.connect(layer, 'notify::labels', self.on_update_labels)]

            j += 1

        
    def draw_layer(self, layer, group_info):

        ax = self.layer_to_axes[layer]
        logger.info ("drawing layer %s (axes %s)" % (layer, ax))

        omap = self.omaps[layer]
        
        ax.lines = []

        line_cache = self.line_caches[layer] = []
        last_cx = -1

        # Default values come in two flavors:
        # group-wise and single default values        
        group_styles = uwrap.get(layer, 'group_styles')
        group_markers = uwrap.get(layer, 'group_markers')        


   # def update_layer(self, layer):

        #:layer.axes
        for (key, axis) in layer.axes.iteritems():
            #:axis.label
            #:axis.scale
            #:axis.start
            #:axis.end
            label = uwrap.get(axis, 'label')            
            scale = uwrap.get(axis, 'scale')
            start = uwrap.get(axis, 'start')
            end = uwrap.get(axis, 'end')
            print "START = %s, END = %s" % (str(start), str(end))
            if key == 'x':
                set_label = ax.set_xlabel
                set_scale = ax.set_xscale
                set_start = (lambda l: ax.set_xlim(xmin=l))
                set_end = (lambda l: ax.set_xlim(xmax=l))
            elif key == 'y':
                set_label = ax.set_ylabel
                set_scale = ax.set_yscale
                set_start = (lambda l: ax.set_ylim(ymin=l))
                set_end = (lambda l: ax.set_ylim(ymax=l))
            else:
                raise RuntimeError("Invalid axis key '%s'" % key)

            if label is not None: set_label(label)
            if scale is not None: set_scale(scale)
            if start is not None: set_start(start)
            if end is not None: set_end(end)

            
        #:layer.visible
        if uwrap.get(layer, 'visible') is False:
            return

        # TODO
        #:layer.title
        title = uwrap.get(layer, 'title', None)
        if title is not None:
            ax.set_title(title)        

        # TODO
        #:layer.grid
        grid = uwrap.get(layer, 'grid')        
        ax.grid(grid)                         

        #:layer.lines:OK
        for line in layer.lines:
            self.update_line(line, layer, axes=ax)
                    
        #:layer.legend:OK
        self.update_legend(layer.legend, layer)

        #:layer.labels:OK
        ax.texts = []
        for label in layer.labels:
            self.update_textlabel(label, layer)


    def draw(self):
        self.check_connection()
        logger.debug("Matplotlib: draw()")                
             
        if self.plot.layers != self.layers_cache:
            self.arrange()

        self.omaps = {}
        for layer in self.plot.layers:
            self.omaps[layer] = {}
            self.line_caches[layer] = {}
            group_info = {}
            self.draw_layer(layer, group_info)
        self.canvas.draw()



    #----------------------------------------------------------------------
        
    def on_update_sobject(self, sender, sobject, **kwargs):
        logger.debug("Updating %s with args %s" % (sobject,str(kwargs)))
        return
    
        try:
            if isinstance(sobject, objects.TextLabel):
                self.update_textlabel(sobject, sender, **kwargs)
            elif isinstance(sobject, objects.Legend):
                self.update_legend(sobject, **kwargs)
            elif isinstance(sobject, objects.Line):
                self.update_line(sobject, **kwargs)
                self.update_legend(sobject, **kwargs)
        except Exception, msg:
            logger.info("Exception raised during sobject update.")
            logger.info(str(inspect.trace()))
        else: