db.py revision 2183:4420c8fadbf5
17322Sgblack@eecs.umich.edu# Copyright (c) 2003-2004 The Regents of The University of Michigan
27322Sgblack@eecs.umich.edu# All rights reserved.
37322Sgblack@eecs.umich.edu#
47322Sgblack@eecs.umich.edu# Redistribution and use in source and binary forms, with or without
57322Sgblack@eecs.umich.edu# modification, are permitted provided that the following conditions are
67322Sgblack@eecs.umich.edu# met: redistributions of source code must retain the above copyright
77322Sgblack@eecs.umich.edu# notice, this list of conditions and the following disclaimer;
87322Sgblack@eecs.umich.edu# redistributions in binary form must reproduce the above copyright
97322Sgblack@eecs.umich.edu# notice, this list of conditions and the following disclaimer in the
107322Sgblack@eecs.umich.edu# documentation and/or other materials provided with the distribution;
117322Sgblack@eecs.umich.edu# neither the name of the copyright holders nor the names of its
127322Sgblack@eecs.umich.edu# contributors may be used to endorse or promote products derived from
137322Sgblack@eecs.umich.edu# this software without specific prior written permission.
147322Sgblack@eecs.umich.edu#
157322Sgblack@eecs.umich.edu# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
167322Sgblack@eecs.umich.edu# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
177322Sgblack@eecs.umich.edu# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
187322Sgblack@eecs.umich.edu# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
197322Sgblack@eecs.umich.edu# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
207322Sgblack@eecs.umich.edu# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
217322Sgblack@eecs.umich.edu# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
227322Sgblack@eecs.umich.edu# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
237322Sgblack@eecs.umich.edu# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
247322Sgblack@eecs.umich.edu# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
257322Sgblack@eecs.umich.edu# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
267322Sgblack@eecs.umich.edu
277322Sgblack@eecs.umich.eduimport MySQLdb, re, string
287322Sgblack@eecs.umich.edu
297322Sgblack@eecs.umich.edudef statcmp(a, b):
307322Sgblack@eecs.umich.edu    v1 = a.split('.')
317322Sgblack@eecs.umich.edu    v2 = b.split('.')
327322Sgblack@eecs.umich.edu
337322Sgblack@eecs.umich.edu    last = min(len(v1), len(v2)) - 1
347322Sgblack@eecs.umich.edu    for i,j in zip(v1[0:last], v2[0:last]):
357322Sgblack@eecs.umich.edu        if i != j:
367322Sgblack@eecs.umich.edu            return cmp(i, j)
377322Sgblack@eecs.umich.edu
387322Sgblack@eecs.umich.edu    # Special compare for last element.
397322Sgblack@eecs.umich.edu    if len(v1) == len(v2):
407376Sgblack@eecs.umich.edu        return cmp(v1[last], v2[last])
417376Sgblack@eecs.umich.edu    else:
427376Sgblack@eecs.umich.edu        return cmp(len(v1), len(v2))
437376Sgblack@eecs.umich.edu
447376Sgblack@eecs.umich.educlass RunData:
457376Sgblack@eecs.umich.edu    def __init__(self, row):
467376Sgblack@eecs.umich.edu        self.run = int(row[0])
477376Sgblack@eecs.umich.edu        self.name = row[1]
487376Sgblack@eecs.umich.edu        self.user = row[2]
497376Sgblack@eecs.umich.edu        self.project = row[3]
507376Sgblack@eecs.umich.edu
517376Sgblack@eecs.umich.educlass SubData:
527376Sgblack@eecs.umich.edu    def __init__(self, row):
537376Sgblack@eecs.umich.edu        self.stat = int(row[0])
547376Sgblack@eecs.umich.edu        self.x = int(row[1])
557376Sgblack@eecs.umich.edu        self.y = int(row[2])
567376Sgblack@eecs.umich.edu        self.name = row[3]
577376Sgblack@eecs.umich.edu        self.descr = row[4]
587376Sgblack@eecs.umich.edu
597376Sgblack@eecs.umich.educlass Data:
607376Sgblack@eecs.umich.edu    def __init__(self, row):
617376Sgblack@eecs.umich.edu        if len(row) != 5:
627376Sgblack@eecs.umich.edu            raise 'stat db error'
637376Sgblack@eecs.umich.edu        self.stat = int(row[0])
647376Sgblack@eecs.umich.edu        self.run = int(row[1])
657376Sgblack@eecs.umich.edu        self.x = int(row[2])
667376Sgblack@eecs.umich.edu        self.y = int(row[3])
677376Sgblack@eecs.umich.edu        self.data = float(row[4])
687376Sgblack@eecs.umich.edu
697376Sgblack@eecs.umich.edu    def __repr__(self):
707376Sgblack@eecs.umich.edu        return '''Data(['%d', '%d', '%d', '%d', '%f'])''' % ( self.stat,
717376Sgblack@eecs.umich.edu            self.run, self.x, self.y, self.data)
727376Sgblack@eecs.umich.edu
737376Sgblack@eecs.umich.educlass StatData(object):
747376Sgblack@eecs.umich.edu    def __init__(self, row):
757376Sgblack@eecs.umich.edu        self.stat = int(row[0])
767376Sgblack@eecs.umich.edu        self.name = row[1]
777376Sgblack@eecs.umich.edu        self.desc = row[2]
787376Sgblack@eecs.umich.edu        self.type = row[3]
797376Sgblack@eecs.umich.edu        self.prereq = int(row[5])
807376Sgblack@eecs.umich.edu        self.precision = int(row[6])
817376Sgblack@eecs.umich.edu
827376Sgblack@eecs.umich.edu        import flags
837376Sgblack@eecs.umich.edu        self.flags = 0
847376Sgblack@eecs.umich.edu        if int(row[4]): self.flags |= flags.printable
857376Sgblack@eecs.umich.edu        if int(row[7]): self.flags |= flags.nozero
867376Sgblack@eecs.umich.edu        if int(row[8]): self.flags |= flags.nonan
877376Sgblack@eecs.umich.edu        if int(row[9]): self.flags |= flags.total
887376Sgblack@eecs.umich.edu        if int(row[10]): self.flags |= flags.pdf
897376Sgblack@eecs.umich.edu        if int(row[11]): self.flags |= flags.cdf
907376Sgblack@eecs.umich.edu
917376Sgblack@eecs.umich.edu        if self.type == 'DIST' or self.type == 'VECTORDIST':
927376Sgblack@eecs.umich.edu            self.min = float(row[12])
937376Sgblack@eecs.umich.edu            self.max = float(row[13])
947376Sgblack@eecs.umich.edu            self.bktsize = float(row[14])
957376Sgblack@eecs.umich.edu            self.size = int(row[15])
967376Sgblack@eecs.umich.edu
977376Sgblack@eecs.umich.edu        if self.type == 'FORMULA':
987376Sgblack@eecs.umich.edu            self.formula = self.db.allFormulas[self.stat]
997376Sgblack@eecs.umich.edu
1007376Sgblack@eecs.umich.educlass Node(object):
1017376Sgblack@eecs.umich.edu    def __init__(self, name):
1027376Sgblack@eecs.umich.edu        self.name = name
1037376Sgblack@eecs.umich.edu    def __str__(self):
1047376Sgblack@eecs.umich.edu        return self.name
1057376Sgblack@eecs.umich.edu
1067376Sgblack@eecs.umich.educlass Result(object):
1077376Sgblack@eecs.umich.edu    def __init__(self, x, y):
1087376Sgblack@eecs.umich.edu        self.data = {}
1097376Sgblack@eecs.umich.edu        self.x = x
1107376Sgblack@eecs.umich.edu        self.y = y
1117376Sgblack@eecs.umich.edu
1127376Sgblack@eecs.umich.edu    def __contains__(self, run):
1137376Sgblack@eecs.umich.edu        return run in self.data
1147376Sgblack@eecs.umich.edu
1157376Sgblack@eecs.umich.edu    def __getitem__(self, run):
1167376Sgblack@eecs.umich.edu        if run not in self.data:
1177376Sgblack@eecs.umich.edu            self.data[run] = [ [ 0.0 ] * self.y for i in xrange(self.x) ]
1187376Sgblack@eecs.umich.edu        return self.data[run]
1197376Sgblack@eecs.umich.edu
1207376Sgblack@eecs.umich.educlass Database(object):
1217376Sgblack@eecs.umich.edu    def __init__(self):
1227376Sgblack@eecs.umich.edu        self.host = 'zizzer.pool'
1237376Sgblack@eecs.umich.edu        self.user = ''
1247376Sgblack@eecs.umich.edu        self.passwd = ''
1257376Sgblack@eecs.umich.edu        self.db = 'm5stats'
1267376Sgblack@eecs.umich.edu        self.cursor = None
1277376Sgblack@eecs.umich.edu
1287376Sgblack@eecs.umich.edu        self.allStats = []
1297376Sgblack@eecs.umich.edu        self.allStatIds = {}
1307376Sgblack@eecs.umich.edu        self.allStatNames = {}
1317376Sgblack@eecs.umich.edu
1327376Sgblack@eecs.umich.edu        self.allSubData = {}
1337376Sgblack@eecs.umich.edu
1347376Sgblack@eecs.umich.edu        self.allRuns = []
1357376Sgblack@eecs.umich.edu        self.allRunIds = {}
1367376Sgblack@eecs.umich.edu        self.allRunNames = {}
1377376Sgblack@eecs.umich.edu
1387376Sgblack@eecs.umich.edu        self.allBins = []
1397376Sgblack@eecs.umich.edu        self.allBinIds = {}
1407376Sgblack@eecs.umich.edu        self.allBinNames = {}
1417376Sgblack@eecs.umich.edu
1427376Sgblack@eecs.umich.edu        self.allFormulas = {}
1437376Sgblack@eecs.umich.edu
1447376Sgblack@eecs.umich.edu        self.stattop = {}
1457376Sgblack@eecs.umich.edu        self.statdict = {}
1467376Sgblack@eecs.umich.edu        self.statlist = []
1477376Sgblack@eecs.umich.edu
1487376Sgblack@eecs.umich.edu        self.mode = 'sum';
1497376Sgblack@eecs.umich.edu        self.runs = None
1507376Sgblack@eecs.umich.edu        self.bins = None
1517376Sgblack@eecs.umich.edu        self.ticks = None
1527376Sgblack@eecs.umich.edu        self.method = 'sum'
1537376Sgblack@eecs.umich.edu        self._method = type(self).sum
1547376Sgblack@eecs.umich.edu
1557376Sgblack@eecs.umich.edu    def get(self, job, stat, system=None):
1567376Sgblack@eecs.umich.edu        run = self.allRunNames.get(str(job), None)
1577376Sgblack@eecs.umich.edu        if run is None:
1587376Sgblack@eecs.umich.edu            return None
1597376Sgblack@eecs.umich.edu
1607376Sgblack@eecs.umich.edu        from info import ProxyError, scalar, vector, value, values, total, len
1617376Sgblack@eecs.umich.edu        if system is None and hasattr(job, 'system'):
1627376Sgblack@eecs.umich.edu            system = job.system
1637376Sgblack@eecs.umich.edu
1647376Sgblack@eecs.umich.edu        if system is not None:
1657376Sgblack@eecs.umich.edu            stat.system = self[system]
1667376Sgblack@eecs.umich.edu        try:
1677376Sgblack@eecs.umich.edu            if scalar(stat):
1687376Sgblack@eecs.umich.edu                return value(stat, run.run)
1697376Sgblack@eecs.umich.edu            if vector(stat):
1707376Sgblack@eecs.umich.edu                return values(stat, run.run)
1717376Sgblack@eecs.umich.edu        except ProxyError:
1727376Sgblack@eecs.umich.edu            return None
1737376Sgblack@eecs.umich.edu
1747376Sgblack@eecs.umich.edu        return None
1757376Sgblack@eecs.umich.edu
1767376Sgblack@eecs.umich.edu    def query(self, sql):
1777376Sgblack@eecs.umich.edu        self.cursor.execute(sql)
1787376Sgblack@eecs.umich.edu
1797376Sgblack@eecs.umich.edu    def update_dict(self, dict):
1807376Sgblack@eecs.umich.edu        dict.update(self.stattop)
1817376Sgblack@eecs.umich.edu
1827376Sgblack@eecs.umich.edu    def append(self, stat):
1837376Sgblack@eecs.umich.edu        statname = re.sub(':', '__', stat.name)
1847376Sgblack@eecs.umich.edu        path = string.split(statname, '.')
1857376Sgblack@eecs.umich.edu        pathtop = path[0]
1867376Sgblack@eecs.umich.edu        fullname = ''
1877376Sgblack@eecs.umich.edu
1887322Sgblack@eecs.umich.edu        x = self
1897322Sgblack@eecs.umich.edu        while len(path) > 1:
1907322Sgblack@eecs.umich.edu            name = path.pop(0)
1917322Sgblack@eecs.umich.edu            if not x.__dict__.has_key(name):
1927322Sgblack@eecs.umich.edu                x.__dict__[name] = Node(fullname + name)
1937322Sgblack@eecs.umich.edu            x = x.__dict__[name]
1947396Sgblack@eecs.umich.edu            fullname = '%s%s.' % (fullname, name)
1957322Sgblack@eecs.umich.edu
1967322Sgblack@eecs.umich.edu        name = path.pop(0)
1977396Sgblack@eecs.umich.edu        x.__dict__[name] = stat
1987396Sgblack@eecs.umich.edu
1997322Sgblack@eecs.umich.edu        self.stattop[pathtop] = self.__dict__[pathtop]
2007324Sgblack@eecs.umich.edu        self.statdict[statname] = stat
2017396Sgblack@eecs.umich.edu        self.statlist.append(statname)
2027324Sgblack@eecs.umich.edu
2037324Sgblack@eecs.umich.edu    def connect(self):
2047396Sgblack@eecs.umich.edu        # connect
2057396Sgblack@eecs.umich.edu        self.thedb = MySQLdb.connect(db=self.db,
2067324Sgblack@eecs.umich.edu                                     host=self.host,
2077333Sgblack@eecs.umich.edu                                     user=self.user,
2087392Sgblack@eecs.umich.edu                                     passwd=self.passwd)
2097396Sgblack@eecs.umich.edu
2107392Sgblack@eecs.umich.edu        # create a cursor
2117392Sgblack@eecs.umich.edu        self.cursor = self.thedb.cursor()
2127396Sgblack@eecs.umich.edu
2137396Sgblack@eecs.umich.edu        self.query('''select rn_id,rn_name,rn_sample,rn_user,rn_project
2147392Sgblack@eecs.umich.edu                   from runs''')
2157392Sgblack@eecs.umich.edu        for result in self.cursor.fetchall():
2167333Sgblack@eecs.umich.edu            run = RunData(result);
2177333Sgblack@eecs.umich.edu            self.allRuns.append(run)
2187333Sgblack@eecs.umich.edu            self.allRunIds[run.run] = run
2197396Sgblack@eecs.umich.edu            self.allRunNames[run.name] = run
2207333Sgblack@eecs.umich.edu
2217333Sgblack@eecs.umich.edu        self.query('select * from bins')
2227396Sgblack@eecs.umich.edu        for id,name in self.cursor.fetchall():
2237396Sgblack@eecs.umich.edu            self.allBinIds[int(id)] = name
2247333Sgblack@eecs.umich.edu            self.allBinNames[name] = int(id)
2257333Sgblack@eecs.umich.edu
2267333Sgblack@eecs.umich.edu        self.query('select sd_stat,sd_x,sd_y,sd_name,sd_descr from subdata')
2277333Sgblack@eecs.umich.edu        for result in self.cursor.fetchall():
2287333Sgblack@eecs.umich.edu            subdata = SubData(result)
2297333Sgblack@eecs.umich.edu            if self.allSubData.has_key(subdata.stat):
2307396Sgblack@eecs.umich.edu                self.allSubData[subdata.stat].append(subdata)
2317333Sgblack@eecs.umich.edu            else:
2327333Sgblack@eecs.umich.edu                self.allSubData[subdata.stat] = [ subdata ]
2337396Sgblack@eecs.umich.edu
2347396Sgblack@eecs.umich.edu        self.query('select * from formulas')
2357333Sgblack@eecs.umich.edu        for id,formula in self.cursor.fetchall():
2367333Sgblack@eecs.umich.edu            self.allFormulas[int(id)] = formula.tostring()
2377333Sgblack@eecs.umich.edu
2387333Sgblack@eecs.umich.edu        StatData.db = self
2397333Sgblack@eecs.umich.edu        self.query('select * from stats')
2407333Sgblack@eecs.umich.edu        import info
2417333Sgblack@eecs.umich.edu        for result in self.cursor.fetchall():
2427333Sgblack@eecs.umich.edu            stat = info.NewStat(self, StatData(result))
2437396Sgblack@eecs.umich.edu            self.append(stat)
2447333Sgblack@eecs.umich.edu            self.allStats.append(stat)
2457333Sgblack@eecs.umich.edu            self.allStatIds[stat.stat] = stat
2467396Sgblack@eecs.umich.edu            self.allStatNames[stat.name] = stat
2477396Sgblack@eecs.umich.edu
2487333Sgblack@eecs.umich.edu    # Name: listbins
2497333Sgblack@eecs.umich.edu    # Desc: Prints all bins matching regex argument, if no argument
2507333Sgblack@eecs.umich.edu    #       is given all bins are returned
2517333Sgblack@eecs.umich.edu    def listBins(self, regex='.*'):
2527333Sgblack@eecs.umich.edu        print '%-50s %-10s' % ('bin name', 'id')
2537396Sgblack@eecs.umich.edu        print '-' * 61
2547333Sgblack@eecs.umich.edu        names = self.allBinNames.keys()
2557333Sgblack@eecs.umich.edu        names.sort()
2567396Sgblack@eecs.umich.edu        for name in names:
2577396Sgblack@eecs.umich.edu            id = self.allBinNames[name]
2587333Sgblack@eecs.umich.edu            print '%-50s %-10d' % (name, id)
2597333Sgblack@eecs.umich.edu
2607333Sgblack@eecs.umich.edu    # Name: listruns
2617333Sgblack@eecs.umich.edu    # Desc: Prints all runs matching a given user, if no argument
2627333Sgblack@eecs.umich.edu    #       is given all runs are returned
2637333Sgblack@eecs.umich.edu    def listRuns(self, user=None):
2647396Sgblack@eecs.umich.edu        print '%-40s %-10s %-5s' % ('run name', 'user', 'id')
2657333Sgblack@eecs.umich.edu        print '-' * 62
2667333Sgblack@eecs.umich.edu        for run in self.allRuns:
2677396Sgblack@eecs.umich.edu            if user == None or user == run.user:
2687396Sgblack@eecs.umich.edu                print '%-40s %-10s %-10d' % (run.name, run.user, run.run)
2697333Sgblack@eecs.umich.edu
2707333Sgblack@eecs.umich.edu    # Name: listTicks
2717333Sgblack@eecs.umich.edu    # Desc: Prints all samples for a given run
2727333Sgblack@eecs.umich.edu    def listTicks(self, runs=None):
2737333Sgblack@eecs.umich.edu        print "tick"
2747333Sgblack@eecs.umich.edu        print "----------------------------------------"
2757333Sgblack@eecs.umich.edu        sql = 'select distinct dt_tick from data where dt_stat=1180 and ('
2767333Sgblack@eecs.umich.edu        if runs != None:
2777396Sgblack@eecs.umich.edu            first = True
2787333Sgblack@eecs.umich.edu            for run in runs:
2797333Sgblack@eecs.umich.edu               if first:
2807396Sgblack@eecs.umich.edu            #       sql += ' where'
2817396Sgblack@eecs.umich.edu                   first = False
2827333Sgblack@eecs.umich.edu               else:
2837333Sgblack@eecs.umich.edu                   sql += ' or'
2847333Sgblack@eecs.umich.edu               sql += ' dt_run=%s' % run.run
2857333Sgblack@eecs.umich.edu            sql += ')'
2867333Sgblack@eecs.umich.edu        self.query(sql)
2877396Sgblack@eecs.umich.edu        for r in self.cursor.fetchall():
2887333Sgblack@eecs.umich.edu            print r[0]
2897333Sgblack@eecs.umich.edu
2907396Sgblack@eecs.umich.edu    # Name: retTicks
2917396Sgblack@eecs.umich.edu    # Desc: Prints all samples for a given run
2927333Sgblack@eecs.umich.edu    def retTicks(self, runs=None):
2937333Sgblack@eecs.umich.edu        sql = 'select distinct dt_tick from data where dt_stat=1180 and ('
2947333Sgblack@eecs.umich.edu        if runs != None:
2957333Sgblack@eecs.umich.edu            first = True
2967333Sgblack@eecs.umich.edu            for run in runs:
2977396Sgblack@eecs.umich.edu               if first:
2987333Sgblack@eecs.umich.edu                   first = False
2997333Sgblack@eecs.umich.edu               else:
3007396Sgblack@eecs.umich.edu                   sql += ' or'
3017396Sgblack@eecs.umich.edu               sql += ' dt_run=%s' % run.run
3027333Sgblack@eecs.umich.edu            sql += ')'
3037333Sgblack@eecs.umich.edu        self.query(sql)
3047333Sgblack@eecs.umich.edu        ret = []
3057333Sgblack@eecs.umich.edu        for r in self.cursor.fetchall():
3067333Sgblack@eecs.umich.edu            ret.append(r[0])
3077396Sgblack@eecs.umich.edu        return ret
3087333Sgblack@eecs.umich.edu
3097333Sgblack@eecs.umich.edu    # Name: liststats
3107396Sgblack@eecs.umich.edu    # Desc: Prints all statistics that appear in the database,
3117396Sgblack@eecs.umich.edu    #         the optional argument is a regular expression that can
3127333Sgblack@eecs.umich.edu    #         be used to prune the result set
3137333Sgblack@eecs.umich.edu    def listStats(self, regex=None):
3147333Sgblack@eecs.umich.edu        print '%-60s %-8s %-10s' % ('stat name', 'id', 'type')
3157333Sgblack@eecs.umich.edu        print '-' * 80
3167333Sgblack@eecs.umich.edu
3177396Sgblack@eecs.umich.edu        rx = None
3187333Sgblack@eecs.umich.edu        if regex != None:
3197333Sgblack@eecs.umich.edu            rx = re.compile(regex)
3207396Sgblack@eecs.umich.edu
3217396Sgblack@eecs.umich.edu        stats = [ stat.name for stat in self.allStats ]
3227333Sgblack@eecs.umich.edu        stats.sort(statcmp)
3237333Sgblack@eecs.umich.edu        for stat in stats:
3247333Sgblack@eecs.umich.edu            stat = self.allStatNames[stat]
3257333Sgblack@eecs.umich.edu            if rx == None or rx.match(stat.name):
3267333Sgblack@eecs.umich.edu                print '%-60s %-8s %-10s' % (stat.name, stat.stat, stat.type)
3277396Sgblack@eecs.umich.edu
3287333Sgblack@eecs.umich.edu    # Name: liststats
3297333Sgblack@eecs.umich.edu    # Desc: Prints all statistics that appear in the database,
3307396Sgblack@eecs.umich.edu    #         the optional argument is a regular expression that can
3317396Sgblack@eecs.umich.edu    #         be used to prune the result set
3327333Sgblack@eecs.umich.edu    def listFormulas(self, regex=None):
3337333Sgblack@eecs.umich.edu        print '%-60s %s' % ('formula name', 'formula')
3347333Sgblack@eecs.umich.edu        print '-' * 80
3357333Sgblack@eecs.umich.edu
3367333Sgblack@eecs.umich.edu        rx = None
3377396Sgblack@eecs.umich.edu        if regex != None:
3387333Sgblack@eecs.umich.edu            rx = re.compile(regex)
3397333Sgblack@eecs.umich.edu
3407396Sgblack@eecs.umich.edu        stats = [ stat.name for stat in self.allStats ]
3417396Sgblack@eecs.umich.edu        stats.sort(statcmp)
3427333Sgblack@eecs.umich.edu        for stat in stats:
3437333Sgblack@eecs.umich.edu            stat = self.allStatNames[stat]
3447333Sgblack@eecs.umich.edu            if stat.type == 'FORMULA' and (rx == None or rx.match(stat.name)):
3457333Sgblack@eecs.umich.edu                print '%-60s %s' % (stat.name, self.allFormulas[stat.stat])
3467333Sgblack@eecs.umich.edu
3477396Sgblack@eecs.umich.edu    def getStat(self, stats):
3487333Sgblack@eecs.umich.edu        if type(stats) is not list:
3497333Sgblack@eecs.umich.edu            stats = [ stats ]
3507396Sgblack@eecs.umich.edu
3517396Sgblack@eecs.umich.edu        ret = []
3527333Sgblack@eecs.umich.edu        for stat in stats:
3537333Sgblack@eecs.umich.edu            if type(stat) is int:
3547333Sgblack@eecs.umich.edu                ret.append(self.allStatIds[stat])
3557333Sgblack@eecs.umich.edu
3567333Sgblack@eecs.umich.edu            if type(stat) is str:
3577396Sgblack@eecs.umich.edu                rx = re.compile(stat)
3587333Sgblack@eecs.umich.edu                for stat in self.allStats:
3597333Sgblack@eecs.umich.edu                    if rx.match(stat.name):
3607396Sgblack@eecs.umich.edu                        ret.append(stat)
3617396Sgblack@eecs.umich.edu        return ret
3627333Sgblack@eecs.umich.edu
3637333Sgblack@eecs.umich.edu    def getBin(self, bins):
3647333Sgblack@eecs.umich.edu        if type(bins) is not list:
3657333Sgblack@eecs.umich.edu            bins = [ bins ]
3667333Sgblack@eecs.umich.edu
3677333Sgblack@eecs.umich.edu        ret = []
3687396Sgblack@eecs.umich.edu        for bin in bins:
3697333Sgblack@eecs.umich.edu            if type(bin) is int:
3707333Sgblack@eecs.umich.edu                ret.append(bin)
3717396Sgblack@eecs.umich.edu            elif type(bin) is str:
3727396Sgblack@eecs.umich.edu                ret.append(self.allBinNames[bin])
3737333Sgblack@eecs.umich.edu            else:
3747333Sgblack@eecs.umich.edu                for name,id in self.allBinNames.items():
3757333Sgblack@eecs.umich.edu                    if bin.match(name):
3767333Sgblack@eecs.umich.edu                        ret.append(id)
3777333Sgblack@eecs.umich.edu
3787333Sgblack@eecs.umich.edu        return ret
3797396Sgblack@eecs.umich.edu
3807333Sgblack@eecs.umich.edu    def getNotBin(self, bin):
3817333Sgblack@eecs.umich.edu        map = {}
3827396Sgblack@eecs.umich.edu        for bin in getBin(bin):
3837396Sgblack@eecs.umich.edu            map[bin] = 1
3847333Sgblack@eecs.umich.edu
3857381Sgblack@eecs.umich.edu        ret = []
3867381Sgblack@eecs.umich.edu        for bin in self.allBinIds.keys():
3877381Sgblack@eecs.umich.edu            if not map.has_key(bin):
3887381Sgblack@eecs.umich.edu                ret.append(bin)
3897381Sgblack@eecs.umich.edu
3907381Sgblack@eecs.umich.edu        return ret
3917381Sgblack@eecs.umich.edu
3927364Sgblack@eecs.umich.edu    #########################################
3937396Sgblack@eecs.umich.edu    # get the data
3947396Sgblack@eecs.umich.edu    #
3957396Sgblack@eecs.umich.edu    def inner(self, op, stat, bins, ticks, group=False):
3967396Sgblack@eecs.umich.edu        sql = 'select '
3977364Sgblack@eecs.umich.edu        sql += 'dt_stat as stat, '
3987396Sgblack@eecs.umich.edu        sql += 'dt_run as run, '
3997396Sgblack@eecs.umich.edu        sql += 'dt_x as x, '
4007396Sgblack@eecs.umich.edu        sql += 'dt_y as y, '
4017396Sgblack@eecs.umich.edu        if group:
4027396Sgblack@eecs.umich.edu            sql += 'dt_tick as tick, '
4037396Sgblack@eecs.umich.edu        sql += '%s(dt_data) as data ' % op
4047396Sgblack@eecs.umich.edu        sql += 'from data '
4057396Sgblack@eecs.umich.edu        sql += 'where '
4067396Sgblack@eecs.umich.edu
4077396Sgblack@eecs.umich.edu        if isinstance(stat, list):
4087396Sgblack@eecs.umich.edu            val = ' or '.join([ 'dt_stat=%d' % s.stat for s in stat ])
4097396Sgblack@eecs.umich.edu            sql += ' (%s)' % val
4107396Sgblack@eecs.umich.edu        else:
4117396Sgblack@eecs.umich.edu            sql += ' dt_stat=%d' % stat.stat
4127396Sgblack@eecs.umich.edu
4137396Sgblack@eecs.umich.edu        if self.runs != None and len(self.runs):
4147396Sgblack@eecs.umich.edu            val = ' or '.join([ 'dt_run=%d' % r for r in self.runs ])
4157396Sgblack@eecs.umich.edu            sql += ' and (%s)' % val
4167396Sgblack@eecs.umich.edu
4177364Sgblack@eecs.umich.edu        if bins != None and len(bins):
4187396Sgblack@eecs.umich.edu            val = ' or '.join([ 'dt_bin=%d' % b for b in bins ])
4197396Sgblack@eecs.umich.edu            sql += ' and (%s)' % val
4207365Sgblack@eecs.umich.edu
4217396Sgblack@eecs.umich.edu        if ticks != None and len(ticks):
4227396Sgblack@eecs.umich.edu            val = ' or '.join([ 'dt_tick=%d' % s for s in ticks ])
4237396Sgblack@eecs.umich.edu            sql += ' and (%s)' % val
4247396Sgblack@eecs.umich.edu
4257396Sgblack@eecs.umich.edu        sql += ' group by dt_stat,dt_run,dt_x,dt_y'
4267396Sgblack@eecs.umich.edu        if group:
4277396Sgblack@eecs.umich.edu            sql += ',dt_tick'
4287396Sgblack@eecs.umich.edu        return sql
4297365Sgblack@eecs.umich.edu
4307396Sgblack@eecs.umich.edu    def outer(self, op_out, op_in, stat, bins, ticks):
4317396Sgblack@eecs.umich.edu        sql = self.inner(op_in, stat, bins, ticks, True)
4327366Sgblack@eecs.umich.edu        sql = 'select stat,run,x,y,%s(data) from (%s) as tb ' % (op_out, sql)
4337396Sgblack@eecs.umich.edu        sql += 'group by stat,run,x,y'
4347396Sgblack@eecs.umich.edu        return sql
4357396Sgblack@eecs.umich.edu
4367396Sgblack@eecs.umich.edu    # Name: sum
4377366Sgblack@eecs.umich.edu    # Desc: given a run, a stat and an array of samples and bins,
4387396Sgblack@eecs.umich.edu    #        sum all the bins and then get the standard deviation of the
4397396Sgblack@eecs.umich.edu    #        samples for non-binned runs. This will just return the average
4407396Sgblack@eecs.umich.edu    #        of samples, however a bin array still must be passed
4417396Sgblack@eecs.umich.edu    def sum(self, stat, bins, ticks):
4427367Sgblack@eecs.umich.edu        return self.inner('sum', stat, bins, ticks)
4437396Sgblack@eecs.umich.edu
4447396Sgblack@eecs.umich.edu    # Name: avg
4457396Sgblack@eecs.umich.edu    # Desc: given a run, a stat and an array of samples and bins,
4467396Sgblack@eecs.umich.edu    #        sum all the bins and then average the samples for non-binned
4477367Sgblack@eecs.umich.edu    #        runs this will just return the average of samples, however
4487396Sgblack@eecs.umich.edu    #        a bin array still must be passed
4497396Sgblack@eecs.umich.edu    def avg(self, stat, bins, ticks):
4507396Sgblack@eecs.umich.edu        return self.outer('avg', 'sum', stat, bins, ticks)
4517396Sgblack@eecs.umich.edu
4527396Sgblack@eecs.umich.edu    # Name: stdev
4537396Sgblack@eecs.umich.edu    # Desc: given a run, a stat and an array of samples and bins,
4547396Sgblack@eecs.umich.edu    #        sum all the bins and then get the standard deviation of the
4557396Sgblack@eecs.umich.edu    #        samples for non-binned runs. This will just return the average
4567368Sgblack@eecs.umich.edu    #        of samples, however a bin array still must be passed
4577396Sgblack@eecs.umich.edu    def stdev(self, stat, bins, ticks):
4587396Sgblack@eecs.umich.edu        return self.outer('stddev', 'sum', stat, bins, ticks)
4597368Sgblack@eecs.umich.edu
4607396Sgblack@eecs.umich.edu    def __setattr__(self, attr, value):
4617396Sgblack@eecs.umich.edu        super(Database, self).__setattr__(attr, value)
4627396Sgblack@eecs.umich.edu        if attr != 'method':
4637396Sgblack@eecs.umich.edu            return
4647369Sgblack@eecs.umich.edu
4657396Sgblack@eecs.umich.edu        if value == 'sum':
4667369Sgblack@eecs.umich.edu            self._method = self.sum
4677396Sgblack@eecs.umich.edu        elif value == 'avg':
4687396Sgblack@eecs.umich.edu            self._method = self.avg
4697396Sgblack@eecs.umich.edu        elif value == 'stdev':
4707396Sgblack@eecs.umich.edu            self._method = self.stdev
4717369Sgblack@eecs.umich.edu        else:
4727396Sgblack@eecs.umich.edu            raise AttributeError, "can only set get to: sum | avg | stdev"
4737396Sgblack@eecs.umich.edu
4747396Sgblack@eecs.umich.edu    def data(self, stat, bins=None, ticks=None):
4757396Sgblack@eecs.umich.edu        if bins is None:
4767396Sgblack@eecs.umich.edu            bins = self.bins
4777396Sgblack@eecs.umich.edu        if ticks is None:
4787369Sgblack@eecs.umich.edu            ticks = self.ticks
4797396Sgblack@eecs.umich.edu        sql = self._method(self, stat, bins, ticks)
4807396Sgblack@eecs.umich.edu        self.query(sql)
4817396Sgblack@eecs.umich.edu
4827396Sgblack@eecs.umich.edu        runs = {}
4837396Sgblack@eecs.umich.edu        xmax = 0
4847396Sgblack@eecs.umich.edu        ymax = 0
4857396Sgblack@eecs.umich.edu        for x in self.cursor.fetchall():
4867396Sgblack@eecs.umich.edu            data = Data(x)
4877396Sgblack@eecs.umich.edu            if not runs.has_key(data.run):
4887396Sgblack@eecs.umich.edu                runs[data.run] = {}
4897396Sgblack@eecs.umich.edu            if not runs[data.run].has_key(data.x):
4907396Sgblack@eecs.umich.edu                runs[data.run][data.x] = {}
4917381Sgblack@eecs.umich.edu
4927381Sgblack@eecs.umich.edu            xmax = max(xmax, data.x)
4937381Sgblack@eecs.umich.edu            ymax = max(ymax, data.y)
4947381Sgblack@eecs.umich.edu            runs[data.run][data.x][data.y] = data.data
4957381Sgblack@eecs.umich.edu
4967381Sgblack@eecs.umich.edu        results = Result(xmax + 1, ymax + 1)
4977381Sgblack@eecs.umich.edu        for run,data in runs.iteritems():
4987370Sgblack@eecs.umich.edu            result = results[run]
4997370Sgblack@eecs.umich.edu            for x,ydata in data.iteritems():
5007396Sgblack@eecs.umich.edu                for y,data in ydata.iteritems():
5017396Sgblack@eecs.umich.edu                    result[x][y] = data
5027396Sgblack@eecs.umich.edu        return results
5037396Sgblack@eecs.umich.edu
5047396Sgblack@eecs.umich.edu    def __getitem__(self, key):
5057370Sgblack@eecs.umich.edu        return self.stattop[key]
5067396Sgblack@eecs.umich.edu