| 1 | # |
|---|
| 2 | # Copyright (c) 2007 Helmut Merz helmutm@cy55.de |
|---|
| 3 | # |
|---|
| 4 | # This program is free software; you can redistribute it and/or modify |
|---|
| 5 | # it under the terms of the GNU General Public License as published by |
|---|
| 6 | # the Free Software Foundation; either version 2 of the License, or |
|---|
| 7 | # (at your option) any later version. |
|---|
| 8 | # |
|---|
| 9 | # This program is distributed in the hope that it will be useful, |
|---|
| 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
|---|
| 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|---|
| 12 | # GNU General Public License for more details. |
|---|
| 13 | # |
|---|
| 14 | # You should have received a copy of the GNU General Public License |
|---|
| 15 | # along with this program; if not, write to the Free Software |
|---|
| 16 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
|---|
| 17 | # |
|---|
| 18 | |
|---|
| 19 | """ |
|---|
| 20 | Working transparently with the R statistics package. |
|---|
| 21 | |
|---|
| 22 | $Id$ |
|---|
| 23 | """ |
|---|
| 24 | |
|---|
| 25 | import os |
|---|
| 26 | |
|---|
| 27 | import rpy2.robjects |
|---|
| 28 | from rpy2.robjects import r |
|---|
| 29 | rpy2.robjects.__allow_access_to_unprotected_subobjects__ = 1 |
|---|
| 30 | |
|---|
| 31 | from zope.proxy import removeAllProxies |
|---|
| 32 | from zope.traversing.browser import absoluteURL |
|---|
| 33 | |
|---|
| 34 | from plot import registerImage |
|---|
| 35 | |
|---|
| 36 | |
|---|
| 37 | # not used (yet?): |
|---|
| 38 | class RWrapper(object): |
|---|
| 39 | |
|---|
| 40 | def __init__(self, context): |
|---|
| 41 | self.context = context |
|---|
| 42 | |
|---|
| 43 | def __getattr__(self, attr): |
|---|
| 44 | value = getattr(self.context, attr) |
|---|
| 45 | return removeAllProxies(value) |
|---|
| 46 | |
|---|
| 47 | def __call__(self, *args, **kw): |
|---|
| 48 | value = self.context.__call__(*args, **kw) |
|---|
| 49 | value = removeAllProxies(value) |
|---|
| 50 | return RWrapper(value) |
|---|
| 51 | |
|---|
| 52 | rx = RWrapper(r) |
|---|
| 53 | |
|---|
| 54 | #with_mode = RWrapper(rpy2.with_mode) |
|---|
| 55 | #as_py = RWrapper(rpy2.as_py) |
|---|
| 56 | |
|---|
| 57 | |
|---|
| 58 | def gdd(**kw): |
|---|
| 59 | r.library('GDD') |
|---|
| 60 | filename = os.tempnam(None, 'rplot') |
|---|
| 61 | robj = r.GDD(filename, type='jpg', **kw) |
|---|
| 62 | return filename + '.jpg', robj |
|---|
| 63 | |
|---|
| 64 | |
|---|
| 65 | class RStat(object): |
|---|
| 66 | |
|---|
| 67 | def __init__(self, context, request): |
|---|
| 68 | self.context = context |
|---|
| 69 | self.request = request |
|---|
| 70 | |
|---|
| 71 | def graphics(self, **kw): |
|---|
| 72 | request = self.request |
|---|
| 73 | context = self.context |
|---|
| 74 | fn, robj = gdd(**kw) |
|---|
| 75 | key = registerImage(fn) |
|---|
| 76 | return '%s/@@plot?image=%s.jpg' % (absoluteURL(context, request), key) |
|---|
| 77 | |
|---|
| 78 | def getDataFrame(self, data): |
|---|
| 79 | """ Return an R data.frame. |
|---|
| 80 | |
|---|
| 81 | The ``data`` argument is a sequence of tuples |
|---|
| 82 | (rowId, columnId, value). Elements with a columnId |
|---|
| 83 | that is not present in all rows is omitted. |
|---|
| 84 | """ |
|---|
| 85 | def checkId(mapping, id): |
|---|
| 86 | for element in mapping.values(): |
|---|
| 87 | if id not in element: |
|---|
| 88 | return False |
|---|
| 89 | return True |
|---|
| 90 | data = sorted(data) |
|---|
| 91 | rows = {} |
|---|
| 92 | columns = {} |
|---|
| 93 | dataMapping = {} |
|---|
| 94 | for rowId, columnId, value in data: |
|---|
| 95 | rows.setdefault(rowId, []).append(columnId) |
|---|
| 96 | columns.setdefault(columnId, []).append(rowId) |
|---|
| 97 | dataMapping[(rowId, columnId)] = value |
|---|
| 98 | columnsToOmit = [] |
|---|
| 99 | for rowId, row in rows.items(): |
|---|
| 100 | for columnId in row: |
|---|
| 101 | if not checkId(rows, columnId): |
|---|
| 102 | columnsToOmit.append(columnId) |
|---|
| 103 | rowsToOmit = [] |
|---|
| 104 | for columnId, column in columns.items(): |
|---|
| 105 | for rowId in column: |
|---|
| 106 | if not checkId(columns, rowId): |
|---|
| 107 | rowsToOmit.append(rowId) |
|---|
| 108 | r.library('ltm') |
|---|
| 109 | result = {} |
|---|
| 110 | #for rowId, columnId, value in data: |
|---|
| 111 | #if columnId not in columnsToOmit: |
|---|
| 112 | # if rowId not in rowsToOmit: |
|---|
| 113 | # result.setdefault(rowId, []).append(value) |
|---|
| 114 | for (rowId, columnId), value in sorted(dataMapping.items()): |
|---|
| 115 | if rowId not in rowsToOmit: |
|---|
| 116 | result.setdefault(rowId, []).append(value) |
|---|
| 117 | self.intermediateData = result |
|---|
| 118 | matrix = rpy.with_mode(rpy.NO_CONVERSION, r.data_frame)(**result) |
|---|
| 119 | return matrix |
|---|