
#---------------------------------------------------------------
#**************************************************************-
#-*                   Photon Design                           *-
#-*            Complex Matrix class for Python scripts        *-
#-*                Written by Klearchos Chaloulos             *-
#-*                   2006-2007                               *-
#-*************************************************************-
#---------------------------------------------------------------
from string import *
import math
from cmath import *
from array import *
from pdPythonLib import *
from PDMatrix import *


def stringToArray(str):
    strTemp=""
    L=len(str)    
    a=array('d')
    k=-1
    fNumberInStr=0
    for i in range(0,L):
        q=str[i]
        if (q==' ' or q=='\t' or q=='\n' or q=='{' or q=='}' or q==')' or q=='(' or q=='+' or q=='-')and fNumberInStr==1:
            k=k+1
            w=float(strTemp)
            a.append(w)
            strTemp=""
            fNumberInStr=0
            if q=='-':
                strTemp="-"
                fNumberInStr=1   
        elif (q=="e" or q==".") and fNumberInStr==1:
            strTemp=strTemp+q   
        elif q.isdigit() or q=="-":
            strTemp=strTemp+q
            fNumberInStr=1               
        continue
    if fNumberInStr==1:
        w=float(strTemp)
        a.append(w)
    return a

def isWhite(a):
    if (a==" " or a=='\t' or a=='\n'):
        return 1
    else:
        return 0
def eatwhite(str, indStart,fReverse=1):
    i=indStart
    L=len(str)
    while i<L and (isWhite(str[i])==fReverse) :
        i=i+1
        continue
    if i<L+1:
        return i
    else:
        return -1

def StringToNumberArray(str):
    a=array('d')
    L=len(str)
    i=0
    while i<L:
        inS=eatwhite(str,i)
        inEnd=eatwhite(str,inS,0)
        q=str[inS:inEnd]
        if q.isdigit():
            qn=float(q)
            a.append(qn)
        i=inEnd+1
        continue
    return a




class pdcmatrix:
    def __init__(self, dataType,rows,cols):
        self.m_dataRe=array(dataType,cols*rows*[0])
        self.m_dataIm=array(dataType,cols*rows*[0])
        self.m_rows=rows
        self.m_cols=cols
        self.m_dataType=dataType
    def get(self,row,col):
        aRe=self.m_dataRe[row*self.m_cols+col]
        aIm=self.m_dataIm[row*self.m_cols+col]
        return complex(aRe,aIm)   
    def set(self,row,col,value):
        self.m_dataRe[row*self.m_cols+col]=value.real
        self.m_dataIm[row*self.m_cols+col]=value.imag
        return
    def setRI(self,row,col,re,im):
        self.m_dataRe[row*self.m_cols+col]=re
        self.m_dataIm[row*self.m_cols+col]=im
        return
    def setAP(self,row,col,ab,phase):
        self.m_dataRe[row*self.m_cols+col]=ab*math.cos(phase)
        self.m_dataIm[row*self.m_cols+col]=ab*math.sin(phase)
        return
    def resize(self,rows,cols):
        del self.m_dataRe
        del self.m_dataIm
        self.m_dataRe=array(self.m_dataType,cols*rows*[0])
        self.m_dataIm=array(self.m_dataType,cols*rows*[0])
        self.m_rows=rows
        self.m_cols=cols
    def SetLine(self,row,a):
        for j in range(0,self.m_cols):
            self.set(row,j,a[j])
            continue
        return
    def rows(self):
        return self.m_rows
    def cols(self):
        return self.m_cols
    def strLine(self,row,AddNewLine,separator):
        strTemp=""
        for j in range(0,self.m_cols):
                temp=self.get(row,j)
                strTemp=strTemp+repr(temp)+separator               
                continue
        if AddNewLine:
            strTemp=strTemp+'\n'
        return strTemp
    def strLineRI(self,row,AddNewLine,separator):
        strTemp=""
        for j in range(0,self.m_cols):
                temp=self.get(row,j)
                Re=temp.real
                Im=temp.imag
                strTemp=strTemp+repr(Re)+separator+repr(Im)+separator               
                continue
        if AddNewLine:
            strTemp=strTemp+'\n'
        return strTemp
    def __repr__(self):
        strTemp=""
        for i in range(0,self.m_rows):
            for j in range(0,self.m_cols):
                temp=self.get(i,j)
                strTemp=strTemp+repr(temp)+'\t'                
                continue
            strTemp=strTemp+'\n'
            continue
        return strTemp
    def PrintToConsole(self):
        for i in range(0,self.m_rows):
            strTemp=self.strLine(i,1)
            print(strTemp)
            continue        
        return
    def WriteToTextFileF(self,fileObj,separator='\t'):
        for i in range(0,self.m_rows):
            strTemp=self.strLine(i,1,separator)
            fileObj.write(strTemp)
            continue
        return
    def WriteToTextFile(self,filename,separator='\t'):
        fileObj=file(filename,'w+')
        for i in range(0,self.m_rows):
            strTemp=self.strLine(i,1,separator)
            fileObj.write(strTemp)
            continue
        fileObj.close()
        return
    def FillFromTextFile(self,fileObj):
        for i in range(0,self.m_rows):
            strTemp=fileObj.readline()
            a=stringToArray(strTemp)
            L=len(a)
            for j in range(0,self.m_cols):
                self.m_data[i*self.m_cols+j]=a[j]
                continue
            continue        
        return
    def SetLineFromFile(self,fileObj):
        strTemp=fileObj.readline()
        a=stringToArray(strTemp)
        L=len(a)
        for j in range(0,self.m_cols):
            self.m_data[i*self.m_cols+j]=a[j]
            continue
        return
    def WriteLineToTextFile(self,fileObj,row,separator):
        strTemp=self.strLine(row,1,separator)
        fileObj.write(strTemp)
        return
    def WriteLineToTextFileRI(self,fileObj,row,separator):
        strTemp=self.strLineRI(row,1,separator)
        fileObj.write(strTemp)
        return
    def Diff1DCols(self,dx):
        #differentiate between columns (with respect to x)
        dm=matrix('d',self.rows(),self.cols()-1)
        for i in range (0,self.rows()):
            for j in range (0,self.cols()-1):
                dm.set(i,j,(self.get(i,j+1)-self.get(i,j))/dx)
                continue
            continue
        return dm
    def Diff1DRows(self,dy):
        #differentiate between rows (with respct to y)
        dm=matrix('d',self.rows()-1,self.cols())
        for i in range (0,self.rows()-1):
            for j in range (0,self.cols()):
                dm.set(i,j,(self.get(i+1,j)-self.get(i,j))/dy)
                continue
            continue
        return dm
    def ReadFrom2DCHTFile(self,strFileName):
        f=file(strFileName)
        f.readline()#Signature
        f.readline()#title
        f.readline()#x title
        f.readline()#y title
        f.readline()#z title
        #read nx and ny
        strTemp=f.readline()
        a=StringToNumberArray(strTemp)
        self.m_rows=int(a[1])
        self.m_cols=int(a[0])
        x=matrix('d',1,self.cols())
        y=matrix('d',1,self.rows())
        f.readline()#x-data? y-data?
        f.readline()#//----------------------------------------------------------
        x.FillFromTextFile(f)
        strTemp=f.readline()
        for i in range (0,self.rows()):
            strTemp=f.readline()
            a=stringToArray(strTemp)
            y.set(0,i,a[0])
            self.SetLine(i,a[1:self.cols()+1])
            continue
        a=list()
        a.append(x)
        a.append(y)
        f.close()
        return a
    def ReadFrom1DOmniSimExportFile(self,strFileName):
        i=0
        f=file(strFileName,'r')
        strTemp=f.readline()
        while len(strTemp)>0:            
            strTemp=f.readline()
            i=i+1
            continue
        f.close()
        self.resize(i-4,1)
        x=matrix('d',i-4,1)
        f=file(strFileName,'r')
        for i in range (0,4):
            strTemp=f.readline()
            continue
        i=0
        strTemp=f.readline()
        while len(strTemp)>0:
            q=stringToArray(strTemp)
            x.set(0,i,q[0])
            self.setAP(i,0,q[1],q[2]*3.14/180)
            strTemp=f.readline()
            i=i+1
            continue
        f.close()
        return x
    def ReadFrom2DOmniSimExportFile(self,strFileName):
        i=0
        f=file(strFileName,'r')
        strTemp=f.readline()
        while len(strTemp)>0:            
            strTemp=f.readline()
            i=i+1
            continue
        f.close()
        
        ww=matrix('d',i-4,2)
        f=file(strFileName,'r')
        for i in range (0,4):
            strTemp=f.readline()
            continue
        i=0
        strTemp=f.readline()
        while len(strTemp)>0:
            q=stringToArray(strTemp)
            ww.set(i,0,q[0])
            ww.set(i,1,q[1])
            strTemp=f.readline()
            i=i+1
            continue
        f.close()
        temp=0
        tempPrev=ww.get(0,0)
        i=0
        while  i < ww.rows():
            i=i+1
            temp=ww.get(i,0)
            if temp!=tempPrev:
                M=i
                i=ww.rows()
            continue
        N=ww.rows()/M
        y=matrix('d',N,1)
        x=matrix('d',M,1)
        for i in range (0,ww.rows(),M):
            y.set(i/M,0,ww.get(i,0))
            continue
        for i in range (0,M):
            x.set(i,0,ww.get(i,1))
            continue
        self.resize(N,M)
        f=file(strFileName,'r')
        for i in range (0,4):
            strTemp=f.readline()
            continue
        for i in range (0,N):
            for j in range (0,M):
                strTemp=f.readline()
                q=stringToArray(strTemp)
                self.setAP(i,j,q[2],q[3])
                continue
            continue                
        a=list()
        a.append(x)
        a.append(y)
        del ww
        return a
    def ReadScatteringMatrix(self,strFileName):
        f=file(strFileName,'r')
        strTemp=f.readline()
        strTemp=f.readline()
        q=stringToArray(strTemp)
        self.resize(int(round(q[0])),int(round(q[1])))
        f.readline()
        for i in range (0, self.rows()):
            strTemp=f.readline()
            q=stringToArray(strTemp)
            for j in range (0, self.cols()):
                self.setAP(i,j,q[2*j+1],q[2*j+2])
                continue
            continue
        return    
    def abs(self):
        ret=matrix('d',self.rows(),self.cols())
        for i in range (0,self.rows()):
            for j in range (0, self.cols()):
                a=self.get(i,j)
                ret.set(i,j,abs(a))
                continue
            continue
        return ret            
    def minus(self,m):
        res=pdcmatrix('d',self.rows(),self.cols())
        for i in range (0,self.rows()):
            for j in range (0,self.cols()):
                res.set(i,j,self.get(i,j)-m.get(i,j))
                continue
            continue
        return res
    def plus(self,m):
        res=pdcmatrix('d',self.rows(),self.cols())
        for i in range (0,self.rows()):
            for j in range (0,self.cols()):
                res.set(i,j,self.get(i,j)+m.get(i,j))
                continue
            continue
        return res
    def mult(self,a):
        #multiplication by scalar
        res=pdcmatrix('d',self.rows(),self.cols())
        for i in range (0,self.rows()):
            for j in range (0,self.cols()):
                res.set(i,j,self.get(i,j)*a)
                continue
            continue
        return res
    def mmult(self,a):
        res=pdcmatrix('d',self.rows(),a.cols())
        for i in range (0,res.rows()):
            for j in range (0,res.cols()):
                temp=0
                for k in range (0,self.cols()):
                    temp=temp+self.get(i,k)*a.get(k,j)
                    continue
                res.set(i,j,temp)
                continue
            continue
        return res    
    def div(self,a):
        #division by scalar
        res=pdcmatrix('d',self.rows(),self.cols())
        for i in range (0,self.rows()):
            for j in range (0,self.cols()):
                res.set(i,j,self.get(i,j)/a)
                continue
            continue
        return res
    def sum(self,rowDown=-1,rowUp=-1,colDown=-1,colUp=-1):
        sum=0
        if rowDown==-1:
            rowDown=0
        if rowUp==-1:
            rowUp=self.rows()
        if colDown==-1:
            colDown=0
        if colUp==-1:
            colUp=self.cols()
        for i in range(rowDown,rowUp):
            for j in range (colDown,colUp):
                sum=sum+self.get(i,j)
                continue
            continue
        return sum
    def maxminAmpl(self,row=-1):
        if row==-1:
            rowDown=0
            rowUp=self.rows()
        else:
            rowDown=row
            rowUp=row+1
        tempMax=abs(self.get(rowDown,0))
        maxIndex=list()
        maxIndex.append(0)
        maxIndex.append(0)
        tempMin=abs(self.get(rowDown,0))
        minIndex=list()
        minIndex.append(0)
        minIndex.append(0)
        for i in range (rowDown, rowUp):
            for j in range (0, self.cols()):
                if abs(self.get(i,j))>tempMax:
                    tempMax=abs(self.get(i,j))
                    maxIndex[0]=i
                    maxIndex[1]=j
                elif abs(self.get(i,j))<tempMin:
                    tempMin=abs(self.get(i,j))
                    minIndex[0]=i
                    minIndex[1]=j
                continue
            continue
        ret=list()
        ret.append(tempMax)
        ret.append(maxIndex)
        ret.append(tempMin)
        ret.append(minIndex)
        return ret
   

 
def WriteCHTFile(strFileName,x,y,m, strTitle,strListAxisTitles):
    f=file(strFileName,'w+')
    strlist=[]
    strlist.append("SGCHART2D(1.0) // signature"+'\n')
    strlist.append("\""+strTitle+"\""+"   // title"+'\n')
    strlist.append("\""+strListAxisTitles[0]+"\""+"  // x-title"+'\n')
    strlist.append("\""+strListAxisTitles[1]+"\""+"   // y-title"+'\n')
    strlist.append("\""+strListAxisTitles[2]+"\""+"    // z-title"+'\n')
    strlist.append(repr(m.cols())+" "+repr(m.rows())+"    // nx ny"+'\n')
    strlist.append("1 1    // x-data? y-data?"+'\n')
    strlist.append("//----------------------------------------------------------"+'\n')
    f.writelines(strlist)
    f.write("    ")
    x.WriteToTextFile(f,"    ")
    f.write("//----------------------------------------------------------"+'\n')
    for i in range(0,m.rows()):
        f.write("   "+repr(y.get(0,i))+"    ")
        m.WriteLineToTextFile(f,i,"   ")
        continue
    f.write("//----------------------------------------------------------"+'\n')
    f.close()
    return

