123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417 |
- # -*- coding: utf-8 -*-
- """
- Copyright (c) 2010-2014 pyrod
- @author: Han Xu
- @mail: xuhan@mail.ustc.edu.cn
- """
- # Codes are free to use. Do whatever you want
- from __future__ import absolute_import
- """Read orginaized parameters"""
- ####################### LIBRARY #############################
- # exceptions library
- from exceptions import (Illegal_Filename_Exception,
- Illegal_Sheetname_Exception,
- Excel_Load_Exception,
- Data_Base_Exception)
- # Python stdlib imports
- import datetime
- import re
- import os
- # data processing library
- import numpy as np
- import pandas as pd
- import openpyxl as ox
- import xlrd
- # pyrod library
- ####################### CONSTANT ############################
- # constant
- #regex of parameters, sheet names
- PARAMETERS = re.compile('^parameters_?\w*\.xlsx$')
- SHEET_SLAB = re.compile('^slab\d$')
- # location of parameters in substrate,slabs
- # [header,usecols,index_col,skip_footer]
- PARAMETERS_LOCATE = {'properties': [0,1,0,19],
- 'ions': [6,5,0,16],
- 'lattice': [4,6,0,18],
- 'ocu': [8,5,0,14],
- 'dw': [10,5,0,10],
- 'dis': [14,5,0,6],
- 'nel': [18,5,0,4],
- 'pos': [20,5,0,0]}
- # atomic_form_factor.xlsx
- ATOMIC_FORM_FACTOR = os.path.abspath(os.path.dirname('atomic_form_facotr.xlsx')) +\
- '/base/atomic_form_factor.xlsx'
- try:
- IONS_TABLE = pd.read_excel(ATOMIC_FORM_FACTOR,
- sheet_name = 'atomic_form_factor',
- index_col = 0)
- IONS_LIST = IONS_TABLE.index.values.tolist()
-
- except Excel_Load_Exception:
- print('load atomic form factor data base load fail')
- ####################### FUNCTIONS ###########################
- # load the parameters from parameter excel
- def _load_parameters(file,parameter,SHEET):
-
- # paramters from PARAMETERS_LOCATE
-
- PARS = PARAMETERS_LOCATE[parameter]
-
- HEADER = PARS[0]
- USECOLS = PARS[1]
- INDEX_COL = PARS[2]
- SKIP_FOOTER = PARS[3]
-
- file_path = os.path.abspath(os.path.dirname(file)) +\
- '/data/' + file
- try:
- variable = pd.read_excel(file_path,
- sheet_name = SHEET,
- header = HEADER,
- usecols = USECOLS,
- index_col = INDEX_COL,
- skip_footer = SKIP_FOOTER)
- except:
-
- error = 'Error while loading parameters using pandas'
- raise Excel_Load_Exception(error)
-
- return variable
- # check if ions are included in atomic form factor data base
- def check_ions(ions):
-
- # input one ion, str
- if isinstance(ions, str):
-
- # ion is included
- if ions in IONS_LIST:
- pass
- # not included, raise error
- else:
- error = 'ion ' + ions + ' is not included'
- raise Data_Base_Exception(error)
-
- # input seveal ions, list
- elif isinstance(ions, list):
-
- ions_not_included = []
- flag = 1
-
- for ion in ions:
-
- #ion is included
- if ion in IONS_LIST:
- pass
- #ion is included, record
- else:
- ions_not_included.append(ion)
- flag = 0
- # not included, raise error
- if not flag:
- error = 'ions: ' + str(ions_not_included) + ' not included'
- raise Data_Base_Exception(error)
- # append atomic form factor of ions to atomic_form_factor.xlsx
- # a--atomic form factor
-
- def append_ions(ion_a):
-
- # openpyxl read atomic_form_facotr
- # loaded xlsx
- try:
- pxlsx = ox.load_workbook(ATOMIC_FORM_FACTOR)
- except Excel_Load_Exception:
- print('openpyxl load excel error')
- # loaded sheet
- try:
- psheet = pxlsx['atomic_form_factor']
- except Illegal_Sheetname_Exception:
- print('wrong sheet name')
-
- # new appended ions location
- location = 'A' + str(len(IONS_LIST)+1) + ':' + 'J' + str(len(IONS_LIST)+1)
- pcell = psheet[location]
-
- # load new atomic form factor
-
- index = 0
-
- for row in pcell:
- for element in row:
-
- element.value = ion_a[index]
- index += 1
-
- # reload atomic_form_factor.xlsx
- try:
- ions_table = pd.read_excel(ATOMIC_FORM_FACTOR,
- sheet_name = 'atomic_form_factor',
- index_col = 0).index.values.tolist()
- except Excel_Load_Exception:
- print('reload atomic form factor data base load fail')
-
- return ions_table
- ######################## CLASSS #############################
- # experiment raw data and parameters initialization
- class initialization_parameters(object):
-
- def __init__(self,
- parameters = 'parameters.xlsx'):
- self.parameters = parameters
- self.path = os.path.abspath(os.path.dirname(parameters)) + parameters
-
- # check files
-
- self.check_parameters = 1
-
- # check sheets
-
- self.check_sheet_fir = 1
- self.check_sheet_las = 1
- self.check_sheet_slab = 1
- self.check_sheet_rank = 1
-
- self.var_table = {}
- self.var_list = {}
-
- # layers_sum-- slab1 layer number, slab1+slab2 layer number, 1+2+3 layer number .....
- self.layers_sum = []
- # layers_n-- 1 layer number, 2 layer number ,3.....
- self.layers_n = []
- # atoms_sum-- 1 atoms number, 2 atoms numbers......
- self.atoms_sum = []
- # atoms_max-- max atoms number of all slabs
- self.atoms_max = 0
- # layers_max-- max layers number of all slabs
- self.layers_max = 0
- def _check_parameters(self):
-
- # check parameters, xlsx
- self.check_parameters = PARAMETERS.match(self.parameters)
-
- if not self.check_parameters:
- error = 'parameters name is illegal.appropriate file name: parameters_xxx--.xlsx'
- raise Illegal_Filename_Exception(error)
- # check sheet names
- def _check_sheetname(self):
-
- """legal names: substrate slab1 slab2 slab3 .... factors"""
-
- # read sheet names
- sheet_names = xlrd.open_workbook(self.path,
- on_demand=True).sheet_names()
-
- self.check_sheet_fir = sheet_names[ 0] == 'substrate'
- self.check_sheet_las = sheet_names[-1] == 'factors'
- slab_names = sheet_names[1:-1]
-
- # check slab names
- self.check_sheet_slab = 1
- self.check_sheet_rank = 1
- sheet_rank = []
-
- for slab in slab_names:
- self.check_sheet_slab = self.check_sheet_slab and SHEET_SLAB.match(slab)
- try:
- sheet_rank.append(int(slab.split('b')[1]))
- except:
- self.check_sheet_slab = 0
-
- self.check_sheet_rank = sheet_rank == np.linspace(1,len(sheet_rank),
- len(sheet_rank),
- dtype = int).tolist()
- if not self.check_sheet_fir:
- error = 'The first sheet should be "substrate"'
- raise Illegal_Sheetname_Exception(error)
-
- elif not self.check_sheet_slab:
- error = 'appropriate slab names'
- raise Illegal_Sheetname_Exception(error)
-
- elif not self.check_sheet_rank:
- error = 'Slab names are not in right order'
- raise Illegal_Sheetname_Exception(error)
-
- elif not self.check_sheet_las:
- error = 'The las sheet should be "factors"'
- raise Illegal_Sheetname_Exception(error)
- # read all the parameters
- def _var_list(self):
- """ Read model parameters. construct model parameters list and table"""
-
- pars = {}
-
- xls = xlrd.open_workbook(self.path, on_demand=True)
- for sheet_n in xls.sheet_names()[0:-1]:
-
- for key in PARAMETERS_LOCATE.keys():
-
- if key == 'properties':
-
- # properties-- atoms number , layers number and absorption
- properties = _load_parameters(self.parameters,'properties',sheet_n)
-
- # atoms_num-- atoms number in one crysatl lattice
- atoms_num = properties.at['atoms_num','c1']
- # absorption of one layers
- absorption = properties.at['absorption','c1']
- # layers_num-- layers number in one slab
- layers_num = properties.at['layers_num','c1']
-
- self.layers_max = self.layers_max + layers_num
- self.layers_sum.append(self.layers_max)
- self.layers_n.append(layers_num)
- self.atoms_sum.append(atoms_num)
-
- if atoms_num > self.atoms_max:
- self.atoms_max = atoms_num
-
- pars['atoms_num'] = atoms_num
- pars['absorption'] = absorption
- pars['layers_num'] = layers_num
-
- else:
-
- pars[key] = _load_parameters(self.parameters,key,sheet_n)
-
- pars['roughness'] = 1
-
- self.var_list[sheet_n] = pars
-
- pars = {}
-
- return self.var_list
- #
- # construct parameters tables
- def _var_table(self):
-
-
- self.var_table = {}
- # slab_index-- which slab
- slab_index = 0
- # tot_layer-- total layers till the layer under calculation
- tot_layer = 0
- #
- # talbe--matrix total layers x max atoms
- x, y = int(self.layers_max), int(self.atoms_max)
-
- posx_table = np.mat(np.zeros([x, y]))
- posy_table = np.mat(np.zeros([x, y]))
- posz_table = np.mat(np.zeros([x, y]))
- ocup_table = np.mat(np.zeros([x, y]))
- elec_table = np.mat(np.zeros([x, y]))
- ions_table = []
- dw_table = []
- slab_list = []
-
- # initalize lattice c modulation list
- posz_list = np.ones(x)
- posx_list = np.ones(x)
- posy_list = np.ones(x)
-
- # contral_table is used to multiply the contral variables
- contral_table = np.mat(np.zeros([x, y]))
-
- # first, we should locate and remove the zero value from layers_sum
- # for zero values equals to the inexistence of this slab
- layers_sum_exist = []
- layers_index_exist = []
- exist_slab = np.nonzero(np.array(self.layers_sum))[0]
-
- for s in exist_slab:
- layers_sum_exist.append(self.layers_sum[int(s)])
- layers_index_exist.append(int(s))
-
- for layer_index in range(x):
-
- # a-- determine which layer this layer_index close with
- # [5,6,10]-8 = [-3,-2,2]
- # "numpy.argmin return the first minimux index"
- # if result>0 slab index is a
- # elif result<0 slab index is a+1
- a = np.argmin(abs(np.array(layers_sum_exist) - layer_index -1))
-
- if (np.array(layers_sum_exist)-layer_index)[a] > 0:
- slab_index = layers_index_exist[a]
- elif (np.array(self.layers_sum)-layer_index)[a] <= 0:
- slab_index = layers_index_exist[a + 1]
- else:
- print('There must be something wrong! layer index should not bigger than total layer number!')
-
- # recognise which slab
- # index which slab
- xls = xlrd.open_workbook(self.path,
- on_demand=True)
- slab_list.append(xls.sheet_names()[slab_index])
- par = self.var_list[xls.sheet_names()[slab_index]]
-
- # normalize the lattice matrix and cosntant by substrate lattice
- # reduce_lattice = slab_lattice/substrate_lattice
- substrate_lattice = self.var_list['substrate']['lattice'].as_matrix()[0,0:3]
- slab_lattice = par['lattice'].as_matrix()[0,0:3]
- reduce_lattice = slab_lattice/substrate_lattice
-
- # postion x,y and z are constructed by reduce_lattice
- posx_table[layer_index,] = par['pos'].loc['pos_x'].as_matrix()*reduce_lattice[0]
- posy_table[layer_index,] = par['pos'].loc['pos_y'].as_matrix()*reduce_lattice[1]
-
- ocup_table[layer_index,] = par['ocu'].as_matrix()
- elec_table[layer_index,] = par['nel'].as_matrix()
- ions_table.append(par['ions'].as_matrix().tolist()[0])
- dw_table.append(par['dw'])
-
- # tot_layer-- the layer postion in the current slab
- tot_layer = tot_layer + reduce_lattice[2]
- # the atom postion in the current layer
- posz_table[layer_index] = tot_layer + \
- par['pos'].loc['pos_z'].as_matrix()*reduce_lattice[2] - \
- self.layers_sum[0]*1
- self.var_table = {'posx_table': posx_table,
- 'posy_table': posy_table,
- 'posz_table': posz_table,
- 'posz_list': posz_list,
- 'posx_list': posx_list,
- 'posy_list': posy_list,
- 'ocu_table': ocup_table,
- 'nel_table': elec_table,
- 'ion_table': ions_table,
- 'dw_table': dw_table,
- 'slab_list': slab_list,
- 'contral_table':contral_table}
-
- return self.var_table
-
-
|