
#---------------------------------------------------------------
#**************************************************************-
#-*                   Photon Design                           *-
#-*            Real Matrix class for Python scripts           *-
#-*                Written by Klearchos Chaloulos             *-
#-*                   2006-2007                               *-
#-*************************************************************-
#---------------------------------------------------------------
from string import *
from cmath import *
from array import *
from pdPythonLib 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')and fNumberInStr==1:
            k=k+1
            w=float(strTemp)
            a.append(w)
            strTemp=""
            fNumberInStr=0
        elif q.isdigit() or q=="." 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 pdmatrix:
    def __init__(self, dataType,rows,cols):
        self.m_data=array(dataType,cols*rows*[0])
        self.m_rows=rows
        self.m_cols=cols
        self.m_dataType=dataType
    def resize(self,rows,cols):
        del self.m_data
        self.m_data=array(self.m_dataType,cols*rows*[0])        
        self.m_rows=rows
        self.m_cols=cols
    def get(self,row,col):
        a=self.m_data[row*self.m_cols+col]
        return a
    def set(self,row,col,value):
        self.m_data[row*self.m_cols+col]=value
        return
    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):
                strTemp=strTemp+repr(self.m_data[row*self.m_cols+j])+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):
                strTemp=strTemp+repr(self.m_data[i*self.m_cols+j])+'\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 Diff1DCols(self,dx):
        #differentiate between columns (with respect to x)
        dm=pdmatrix('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=pdmatrix('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):
        #The user still has to manually open the file and see the nx and ny values and construct x(1,ny) y(1,ny)
        #and m(ny,nx) matrices. Also has to count the lines of the file up to where the data starts and put that
        #to LinesToJump
        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=pdmatrix('d',1,self.cols())
        y=pdmatrix('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 ReadFrom1DCHTFile(self,strFileName):
        #The user still has to manually open the file and see the nx and ny values and construct x(1,ny) y(1,ny)
        #and m(ny,nx) matrices. Also has to count the lines of the file up to where the data starts and put that
        #to LinesToJump
        f=file(strFileName)
        f.readline()#Signature
        f.readline()#title
        #read nx and ny
        strTemp=f.readline()
        a=StringToNumberArray(strTemp)
        self.m_rows=1
        self.m_cols=int(a[0])
        x=pdmatrix('d',1,self.cols())

        f.readline()#//----------------------------------------------------------        
        f.readline()#x axis
        f.readline()#y yaxis
        f.readline()#//----------------------------------------------------------

        for i in range (0,self.rows()):
            strTemp=f.readline()
            a=stringToArray(strTemp)
            x.set(0,i,a[0])
            self.set(0,i,a[1])
            continue
        
        f.close()
        return x
    def minus(self,m):
        res=pdmatrix('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=pdmatrix('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=pdmatrix('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 div(self,a):
        #division by scalar
        res=pdmatrix('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 maxmin(self,row=-1):
        if row==-1:
            rowDown=0
            rowUp=self.rows()
        else:
            rowDown=row
            rowUp=row+1
        tempMax=self.get(rowDown,0)
        maxIndex=list()
        maxIndex.append(0)
        maxIndex.append(0)
        tempMin=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 self.get(i,j)>tempMax:
                    tempMax=self.get(i,j)
                    maxIndex[0]=i
                    maxIndex[1]=j
                elif self.get(i,j)<tempMin:
                    tempMin=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
