#*********************************************************************************
#* Copyright (C) 2020 Brendan Smith, Alexey V. Akimov
#* Copyright (C) 2019 Alexey V. Akimov
#*
#* This file is distributed under the terms of the GNU General Public License
#* as published by the Free Software Foundation, either version 3 of
#* the License, or (at your option) any later version.
#* See the file LICENSE in the root directory of this distribution
#* or <http://www.gnu.org/licenses/>.
#***********************************************************************************
"""
.. module:: data_conv
:platform: Unix, Windows
:synopsis:
This module implements various functions for data conversions and data transformations
.. moduleauthor:: Alexey V. Akimov, Brendan Smith
"""
import os
import sys
import math
import copy
import numpy as np
if sys.platform=="cygwin":
from cyglibra_core import *
elif sys.platform=="linux" or sys.platform=="linux2":
from liblibra_core import *
#import common_utils as comn
import util.libutil as comn
[docs]def unit_conversion(X, scaling_factor):
"""
Rescales the data X uniformly:
X(original) -> ( X ) (x) (scaling_factor),
Here, (x) indicates the element-wise multiplicaiton, and shift1, shift2, and scale are matrices
Args:
X ( list of lists of CMATRIX(nstates, nstates) ): the original data stored as
X[idata][step] - a CMATRIX(nstates, nstates) for the dataset `idata` and time
step `step`
scaling_factor ( double or complex ): the rescaling factor
Returns:
None: but transforms X input directly, so changes the original input
"""
nst = X[0][0].num_of_cols
scl = CMATRIX(nst, nst);
shi = CMATRIX(nst, nst);
# Default ones
for i in range(0,nst):
for j in range(0,nst):
scl.set(i,j, scaling_factor*(1.0+0.0j))
shi.set(i,j, (0.0+0.0j))
transform_data(X, {"shift2":shi, "scale":scl })
[docs]def scale_NAC(X, a, b, scaling_factor):
"""
Rescales only the matrix elements X_ab by a uniform scaling factor:
X_ab(original) -> ( X_ab ) x (scaling_factor),
Args:
X ( list of lists of CMATRIX(nstates, nstates) ): the original data stored as
X[idata][step] - a CMATRIX(nstates, nstates) for the dataset `idata` and time
step `step`
scaling_factor ( double or complex ): the rescaling factor
Returns:
None: but transforms X input directly, so changes the original input
"""
nst = X[0][0].num_of_cols
scl = CMATRIX(nst, nst);
shi = CMATRIX(nst, nst);
# Default ones
for i in range(0,nst):
for j in range(0,nst):
scl.set(i,j, 1.0+0.0j)
shi.set(i,j, 0.0+0.0j)
scl.set(a,b, scaling_factor)
transform_data(X, {"shift2":shi, "scale":scl })
[docs]def scale_NACs(X, scaling_factor):
"""
Rescales all the off-diagonal matrix elements X_ab by a uniform scaling factor:
X_ab(original) -> ( X_ab ) x (scaling_factor), for all a!=b
Args:
X ( list of lists of CMATRIX(nstates, nstates) ): the original data stored as
X[idata][step] - a CMATRIX(nstates, nstates) for the dataset `idata` and time
step `step`
scaling_factor ( double or complex ): the rescaling factor
Returns:
None: but transforms X input directly, so changes the original input
"""
nst = X[0][0].num_of_cols
scl = CMATRIX(nst, nst);
shi = CMATRIX(nst, nst);
# Default ones
for i in range(0,nst):
for j in range(0,nst):
if i!=j:
scl.set(i,j, scaling_factor*(1.0+0.0j))
else:
scl.set(i,j, (1.0+0.0j))
shi.set(i,j, (0.0+0.0j))
transform_data(X, {"shift2":shi, "scale":scl })
[docs]def scissor(X, a, dE):
"""
Shift the diagonal elements of X : X_ii for all i = a, a+1, ... by a constant value dE
X_ii(original) -> ( X_ii ) + dE, for all i >= a
Args:
X ( list of lists of CMATRIX(nstates, nstates) ): the original data stored as
X[idata][step] - a CMATRIX(nstates, nstates) for the dataset `idata` and time
step `step`
dE ( double or complex ): the shift magnitude
Returns:
None: but transforms X input directly, so changes the original input
"""
nst = X[0][0].num_of_cols
scl = CMATRIX(nst, nst);
shi = CMATRIX(nst, nst);
# Default ones
for i in range(0,nst):
for j in range(0,nst):
scl.set(i,j, 1.0+0.0j)
shi.set(i,j, 0.0+0.0j)
for i in range(a, nst):
shi.add(i,i, dE)
transform_data(X, {"shift2":shi, "scale":scl })
[docs]def unpack1(H, i, j, component=2):
"""
Converts a list of CMATRIX or MATRIX objects into a list of doubles.
These numbers are the time-series of a specifiend component (real of imaginary)
of a specified matrix element (i,j) of each matrix: res[k] = H[k].get(i,j).component
Args:
H ( list of CMATRIX(n, m) or MATRIX(n, m)): time-series of the matrices
i ( int ): row index of the matrix element of interest
j ( int ): column index of the matrix element of interest
component ( int ): index selecting real or imaginary component
- 0: real
- 1: imaginary
- 2: the whole thing - use for real matrices [ default ]
Returns:
list of doubles: time-series of a given matrix element's component
"""
sz = len(H)
res = []
for k in range(0,sz):
if component==0:
res.append( H[k].get(i,j).real )
elif component==1:
res.append( H[k].get(i,j).imag )
elif component==2:
res.append( H[k].get(i,j) )
return res
[docs]def unpack2(H, i, component=2):
"""
Converts a CMATRIX or MATRIX object into a list of doubles.
These numbers are the time-series of a specifiend component (real of imaginary)
of a specified matrix column ```i``` res[k] = H.get(k,i).component
Args:
H ( CMATRIX(n, m) or MATRIX(n, m) ): time-series in a form of a matrix
i ( int ): column index of interest
component ( int ): index selecting real or imaginary component
- 0: real
- 1: imaginary
- 2: the whole thing - use for real matrices
Returns:
list of doubles: time-series of a given matrix column's components
"""
sz = H.num_of_rows
res = []
for k in range(0,sz):
if component==0:
res.append( H.get(k,i).real )
elif component==1:
res.append( H.get(k,i).imag )
elif component==2:
res.append( H.get(k,i) )
return res
[docs]def list2MATRIX(data):
"""Converts a list of N doubles into a MATRIX(N,1) object
Args:
data ( list of doubles ): data to be converted
Returns:
MATRIX(N,1): a matrix representation of the data
"""
N = len(data)
res = MATRIX(N,1)
for n in range(0,N):
res.set(n, 0, data[n])
return res
[docs]def nparray2MATRIX(data):
"""
Converts 2D np.array of shape( N, M ) doubles into a MATRIX( N, M ) object
The numpy array can contain either complex or real values
Args:
data ( 2D np.array of dimension N x M ): data to be converted
Returns:
MATRIX( N, M ): a matrix representation of the data
"""
N = data.shape[0]
M = data.shape[1]
res = MATRIX(N,M)
for n in range(0,N):
for m in range(0,M):
res.set(n, m, data[n][m].real)
return res
[docs]def nparray2CMATRIX(data):
"""
Converts 2D np.array of shape( N, M ) doubles into a CMATRIX( N, M ) object
The numpy array should be complex
Args:
data ( 2D np.array of dimension N x M ): data to be converted
Returns:
MATRIX( N, M ): a matrix representation of the data
"""
N = data.shape[0]
M = data.shape[1]
res = CMATRIX(N,M)
for n in range(0,N):
for m in range(0,M):
res.set(n, m, data[n][m])
return res
[docs]def MATRIX2nparray( data ):
"""
Converts both Libra MATRIX ( N, M ) object and CMATRIX ( N, M ) object
into a 2D np.array of shape( N, M )
Args:
data ( Libra MATRIX object of dimension N x M ): data to be converted
Returns:
2d np.array: 2D np.array of shape( N, M )
"""
N = data.num_of_rows
M = data.num_of_cols
res = []
for n in range(0,N):
res.append( [] )
for m in range(0,M):
res[n].append(data.get(n,m))
return np.array(res)
[docs]def matrix2list(q):
"""
Converts the MATRIX(ndof, 1) or CMATRIX(ndof, 1) to a list of `ndof` float/complex numbers
Args:
=======
q ( MATRIX(ndof, 1) or CMATRIX(ndof, 1) ): input matrix
Returns:
list : list representation of the matrix
"""
list_q = []
ndof = q.num_of_rows
for idof in range(ndof):
list_q.append( q.get(idof, 0) )
return list_q
[docs]def make_list(nitems, value):
"""
Creates a list of `nitems` items, each of which is `value`
Args:
nitems ( int ): the size of the resulting list to create
value ( any type ): the value of each initialized element of the list
Returns:
list : the list of the added values
"""
res_list = []
for iitem in range(nitems):
res_list.append( value )
return res_list