Monday, March 31, 2008

Addendum to RhoZeta source

To add to my RhoZeta post from a few weeks back, I thought I'd add an example CellManager. This code demonstrates how to make a Non-Blocking cell manager on a RhoZeta sheet, and how to spawn such a thread for the ActiveSheet in Excel. If you add this to the RhoZeta.py, run the code, and then type "NBCM = NBActiveSheet()" into the PythonWin interactive console you will create a non-blocking style cell manager in the active sheet.

If the CellManager thread craps out (there's a bug when the dictionary changes size in the middle of computation) you can just recreate it by typing "NBCM = NBActiveSheet()" into the console. (start the thread with NBCM.start())

To determine the iteration time, put "=time.clock()" into Cell A1, "=A1" into Cell A2, and "=A1-A2" into cell A3. you can create a simple shift register struction by setting A4 to "=A3" and A5 to "=A4" and so on. This allows you to take the average over a series of tests.

You can also create a counter by initializing B1 to "=0" and then changing it's formula to "=B1 +1" for example.

Non-blocking means all computed assignments are deferred so that all the inputs are read from the previous iteration, as opposed to blocking assignments which read values from the current iteration and assign new values as they are computed. Changing this code to blocking mode iteration is easy to do in terms of number of keystrokes (change eval to exec + a little more massaging, or update valdic as you eval), though I'll leave that as an exercise for you. This Python interpreted modes are slow because of the dynamic eval of strings in Python, compilation is required to accelerated the function calls. JIT compilation to FPGA/GPU/Multicore is what is really required to accelerate spreadsheet iteration... hence a start-up.

#start copying here:

def SheetNonBlockingAssignments(Sh):
    valdic = {}
    for key,value in Sh.Cells.iteritems():
        valdic[key]=value.Value

    for cell in Sh.Cells.values():
        try:
            if (cell.Formula == ''):
                cell.Value = None
            elif (cell.Formula[0:1] == "'=") or (cell.Formula[0] == "="):
                cell.Value = eval(cell.Formula[1:].lstrip('='),globals(),valdic)
            else:
                cell.Value = cell.Value
        except Exception,e:
            cell.Value=e

class NonBlockingCellManager(Timeout):
    def __init__(self, Sheet):
        Timeout.__init__(target=SheetNonBlockingAssignments, kwargs={'Sh':Sheet})
        self.set_run_forever()

def NBActiveSheet():
    as = RZ.UISession.app.ActiveSheet
    NBCM = NonBlockingCellManager(RZ[as.Parent.Name][as.Name])
    return NBCM





#End copy


Another useful change to the FrontendSynchronizer class looks like this:

if xl.ActiveWindow.DisplayFormulas:
setv = RangeMap(Excel.strifnotnone, self.RhoZetaSession.RangeFromTuple(vrtuple).Formula)
else:
setv = RangeMap(Excel.strifnotnone, self.RhoZetaSession.RangeFromTuple(vrtuple).Value)


Press CTRL-` to toggle the DisplayFormulas variable in Excel.

We'll put up source control soon. Feel free to email me at amirh at mit dot edu with questions comments or if you want to help.

No comments: