Numeric Python, COM and Eigenvalues

Stefano clubdelpelosuperfluo at yahoo.it
Tue Apr 23 03:29:14 EDT 2002


Fernando Pérez <fperez528 at yahoo.com> wrote in message news:<aa1ft2$mn7$2 at peabody.colorado.edu>...
> Stefano wrote:
> 
> > I am working with Numpy and trying to create a COM server.
> > I managed to call this server by Excel and get results like Inverse
> > matrix or Cholesky decomposition but the server doesn't work as I ask
> > for Eigenvalues/vectors (Excel does not respond anymore).
> > Has anyone heard of a problem of this kind?
> 
> Well, with zero example code and details provided that's going to be a hard 
> one to get help on ;)
> 
> Do you know for a fact you're feeding it a diagonalizable matrix? Does numpy 
> compute the eigenvals/vects nicely if you test it with the same matrix on its 
> own (not via excel)? Start testing with a symmetric 2x2 real matrix for which 
> you can hand-compute the eigenvalues trivially, that might tell you where the 
> problem is.
> 
> Good luck,
> 
> f.

I have already tried with a trivial matrix via Shell.
The same matrix makes Excel freeze.

I have walked two path to use numeric via com
1. making a client that talks with Mark Hammond's doubletalk (do you
know?)
2. making a server and a client by my own (actually with the help of
Poulsen)
I have problems only with eigenvalues (I can invert, i can decompose à
la Cholesky...) with both the codes!

1.
doubletalk server: http://starship.python.net/crew/mhammond/ppw32/ppw32_samples.zip
chapter 6
the client:
Const txtStartupScript = ""
Public BookServer As Object
'    public methods
                'double',
                'interpretString',  # tries exec, then eval
                'execFile',
                'importFile',
                'beginTrappingOutput',
                'endTrappingOutput',
                'getStandardOutput',
                'getViewData',
                'count',
                'createTransaction',
                'getTransaction','getTransactionString',
                'getOneLineDescription',
                'load', 'loadFromText', 'loadFromString',
                'save', 'saveAsText', 'asString',
                'edit','add',
                'getAccountDetails',
                'getAccountList',
                'drawAccountChart',
                'doDelphiCallbackDemo'



Sub InitCOMServer()
    Dim startupScript As String
    
    'called when the program starts
    On Error GoTo InitCOMServer_error
    
    Set BookServer = CreateObject("Doubletalk.BookServer",
RemoteMachine)
    
    On Error GoTo 0
    
    'tell it to capture output for the console
    BookServer.beginTrappingOutput
    
    'if there is an init script, run it
    If txtStartupScript <> "" Then
        On Error GoTo InitCOMServer_StartupScriptError
        BookServer.execFile txtStartupScript
        On Error GoTo 0
    End If
    
    'grab any standard output for the console
    
    Exit Sub
    
InitCOMServer_error:
    Dim msg As String
    msg = "There was an error trying to initialize the BookServer." +
_
            "Please check that it is properly registered and try the
Python " + _
            "test functions first.  The program will now abort."
    MsgBox msg
    End
    
InitCOMServer_StartupScriptError:
    MsgBox "An error occurred running your startup script '" + _
        txtStartupScript + "'. " + _
        "Please check it is present and correct."
End Sub

Sub CloseCOMServer()
    Set BookServer = Nothing
End Sub

Sub TestCOMServer()
    'just to check it is alive
    Dim hopefully_four As Integer
    hopefully_four = BookServer.Double(2)
    MsgBox "2 x 2 = " & hopefully_four & ", so your server is alive"
End Sub

Sub ScriptRun(FileName)
    BookServer.execFile FileName
    On Error GoTo mnuScriptRun_Error:
    Exit Sub
    
mnuScriptRun_Error:
    MsgBox "Error running script:" + vbCrLf + vbCrLf + Err.Description
End Sub
Sub ScriptImport(FileName)
    BookServer.importFile FileName
End Sub
Function ProcessPythonCode(expr As String) As String
    'passes a chunk of text to the server's interpretString
    'method, and returns the result.  If an error occurs,
    'returns the error message.
    
    On Error GoTo mnuProcessPythonCode_Error
    ProcessPythonCode = BookServer.interpretString(expr)
    Exit Function

mnuProcessPythonCode_Error:
    ProcessPythonCode = Err.Description
End Function

Sub ProcessCommand(txtInput As String)
    'gets a one-line string from the input text box.
    'if there is a result, appends it to the output box.
    'Also copy the input command to output to keep a command history
    Dim strInput As String
    Dim strResult As String
    Dim strStandardOutput As String
    Dim strOutText As String  'for building the final textbox data
    
    'VB puts CRLF pairs in the input for multi-line
    'statements; Python just wants line feeds
    strInput = Replace(txtInput, vbCrLf, vbLf)
    
    'multi-line statements need a final line-feed; this is optional
    'fopr one liners.  WE'll add it anyway.
    If Right(strInput, 1) <> vbLf Then strInput = strInput + vbLf
           
    'process it
    strResult = ProcessPythonCode(strInput)
    Debug.Print strResult
    'get output
    strStandardOutput = BookServer.getStandardOutput()
    strStandardOutput = Replace(strStandardOutput, vbLf, vbCrLf)
    Debug.Print strStandardOutput
    
End Sub

Sub InitializeNumeric()
    Dim s As String
    s = "from LinearAlgebra import *"
    ProcessPythonCode s
    s = "from Numeric import *"
    ProcessPythonCode s
End Sub
Sub testNumerical()
    Call InitCOMServer
    Call InitializeNumeric
    Dim s As String
    s = "a = array(([2,1],[1,2]))"
    ProcessCommand s
    s = "inverse(a)"
    ' s = "eigenvalues(a)" Excel freezes
    ProcessCommand s
    CloseCOMServer
End Sub

2.
Python server (assigning the _reg_clsid_ with pythoncom, imported and
then registered with win32com.server.register.UseCommandLine...)
# PythonNumeric.py 
 
class PythonNumeric:
    _reg_clsid_ = "{E34C200E-D95A-49C6-A0F9-F29FF8FF903A}"
    _reg_desc_ = "Python Numeric COM Server"
    _reg_progid_ = "PythonNumeric.Utilities" #for external calling
    _reg_class_spec_ = "PythonNumeric.PythonNumeric"
    _public_methods_ = [ 'InvertMatrix', 'Eigenvalues' ]
    
       
    # Use "print pythoncom.CreateGuid()" to make a new one.
    
    
    def InvertMatrix(self, val):
        import Numeric
        import LinearAlgebra
                        
        return (LinearAlgebra.inverse(Numeric.array(val))).tolist()
 
    def Eigenvalues(self, val):
        import Numeric
        import LinearAlgebra
                        
        return (LinearAlgebra.eigenvalues(Numeric.array(val))).tolist()



VBA Client
Function NumpyMatInverse(mynum As Range)
    Dim numpy As Object
    Dim matrice As Variant
    Range2Array2 matrice, mynum
    Set numpy = CreateObject("PythonNumeric.Utilities")
    NumpyMatInverse = numpy.InvertMatrix(matrice)
    Set numpy = Nothing
End Function
Function NumpyMatEigen(mynum As Range)
    Dim numpy As Object
    Dim matrice As Variant
    Range2Array2 matrice, mynum
    Set numpy = CreateObject("PythonNumeric.Utilities")
    NumpyMatEigen = numpy.Eigenvalues(matrice)
    Set numpy = Nothing
End Function
Sub Range2Array2(arr As Variant, r As Range, Optional base As Integer)
Dim n(1 To 2) As Integer, i As Integer, j As Integer, k As Integer

n(1) = r.Rows.Count + (base - 1)
n(2) = r.Columns.Count + (base - 1)

Select Case n(2)
    Case 0
        ReDim arr(base To n(1))
        For i = base To n(1)
             arr(i) = r.Cells(i - base + 1, 1 - base + 1)
        Next i
    Case Else
        ReDim arr(base To n(1), base To n(2))
        For i = base To n(1)
            For j = base To n(2)
                 arr(i, j) = r.Cells(i - base + 1, j - base + 1)
            Next j
        Next i
End Select

End Sub



More information about the Python-list mailing list