read_parameters.py 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417
  1. # -*- coding: utf-8 -*-
  2. """
  3. Copyright (c) 2010-2014 pyrod
  4. @author: Han Xu
  5. @mail: xuhan@mail.ustc.edu.cn
  6. """
  7. # Codes are free to use. Do whatever you want
  8. from __future__ import absolute_import
  9. """Read orginaized parameters"""
  10. ####################### LIBRARY #############################
  11. # exceptions library
  12. from exceptions import (Illegal_Filename_Exception,
  13. Illegal_Sheetname_Exception,
  14. Excel_Load_Exception,
  15. Data_Base_Exception)
  16. # Python stdlib imports
  17. import datetime
  18. import re
  19. import os
  20. # data processing library
  21. import numpy as np
  22. import pandas as pd
  23. import openpyxl as ox
  24. import xlrd
  25. # pyrod library
  26. ####################### CONSTANT ############################
  27. # constant
  28. #regex of parameters, sheet names
  29. PARAMETERS = re.compile('^parameters_?\w*\.xlsx$')
  30. SHEET_SLAB = re.compile('^slab\d$')
  31. # location of parameters in substrate,slabs
  32. # [header,usecols,index_col,skip_footer]
  33. PARAMETERS_LOCATE = {'properties': [0,1,0,19],
  34. 'ions': [6,5,0,16],
  35. 'lattice': [4,6,0,18],
  36. 'ocu': [8,5,0,14],
  37. 'dw': [10,5,0,10],
  38. 'dis': [14,5,0,6],
  39. 'nel': [18,5,0,4],
  40. 'pos': [20,5,0,0]}
  41. # atomic_form_factor.xlsx
  42. ATOMIC_FORM_FACTOR = os.path.abspath(os.path.dirname('atomic_form_facotr.xlsx')) +\
  43. '/base/atomic_form_factor.xlsx'
  44. try:
  45. IONS_TABLE = pd.read_excel(ATOMIC_FORM_FACTOR,
  46. sheet_name = 'atomic_form_factor',
  47. index_col = 0)
  48. IONS_LIST = IONS_TABLE.index.values.tolist()
  49. except Excel_Load_Exception:
  50. print('load atomic form factor data base load fail')
  51. ####################### FUNCTIONS ###########################
  52. # load the parameters from parameter excel
  53. def _load_parameters(file,parameter,SHEET):
  54. # paramters from PARAMETERS_LOCATE
  55. PARS = PARAMETERS_LOCATE[parameter]
  56. HEADER = PARS[0]
  57. USECOLS = PARS[1]
  58. INDEX_COL = PARS[2]
  59. SKIP_FOOTER = PARS[3]
  60. file_path = os.path.abspath(os.path.dirname(file)) +\
  61. '/data/' + file
  62. try:
  63. variable = pd.read_excel(file_path,
  64. sheet_name = SHEET,
  65. header = HEADER,
  66. usecols = USECOLS,
  67. index_col = INDEX_COL,
  68. skip_footer = SKIP_FOOTER)
  69. except:
  70. error = 'Error while loading parameters using pandas'
  71. raise Excel_Load_Exception(error)
  72. return variable
  73. # check if ions are included in atomic form factor data base
  74. def check_ions(ions):
  75. # input one ion, str
  76. if isinstance(ions, str):
  77. # ion is included
  78. if ions in IONS_LIST:
  79. pass
  80. # not included, raise error
  81. else:
  82. error = 'ion ' + ions + ' is not included'
  83. raise Data_Base_Exception(error)
  84. # input seveal ions, list
  85. elif isinstance(ions, list):
  86. ions_not_included = []
  87. flag = 1
  88. for ion in ions:
  89. #ion is included
  90. if ion in IONS_LIST:
  91. pass
  92. #ion is included, record
  93. else:
  94. ions_not_included.append(ion)
  95. flag = 0
  96. # not included, raise error
  97. if not flag:
  98. error = 'ions: ' + str(ions_not_included) + ' not included'
  99. raise Data_Base_Exception(error)
  100. # append atomic form factor of ions to atomic_form_factor.xlsx
  101. # a--atomic form factor
  102. def append_ions(ion_a):
  103. # openpyxl read atomic_form_facotr
  104. # loaded xlsx
  105. try:
  106. pxlsx = ox.load_workbook(ATOMIC_FORM_FACTOR)
  107. except Excel_Load_Exception:
  108. print('openpyxl load excel error')
  109. # loaded sheet
  110. try:
  111. psheet = pxlsx['atomic_form_factor']
  112. except Illegal_Sheetname_Exception:
  113. print('wrong sheet name')
  114. # new appended ions location
  115. location = 'A' + str(len(IONS_LIST)+1) + ':' + 'J' + str(len(IONS_LIST)+1)
  116. pcell = psheet[location]
  117. # load new atomic form factor
  118. index = 0
  119. for row in pcell:
  120. for element in row:
  121. element.value = ion_a[index]
  122. index += 1
  123. # reload atomic_form_factor.xlsx
  124. try:
  125. ions_table = pd.read_excel(ATOMIC_FORM_FACTOR,
  126. sheet_name = 'atomic_form_factor',
  127. index_col = 0).index.values.tolist()
  128. except Excel_Load_Exception:
  129. print('reload atomic form factor data base load fail')
  130. return ions_table
  131. ######################## CLASSS #############################
  132. # experiment raw data and parameters initialization
  133. class initialization_parameters(object):
  134. def __init__(self,
  135. parameters = 'parameters.xlsx'):
  136. self.parameters = parameters
  137. self.path = os.path.abspath(os.path.dirname(parameters)) + parameters
  138. # check files
  139. self.check_parameters = 1
  140. # check sheets
  141. self.check_sheet_fir = 1
  142. self.check_sheet_las = 1
  143. self.check_sheet_slab = 1
  144. self.check_sheet_rank = 1
  145. self.var_table = {}
  146. self.var_list = {}
  147. # layers_sum-- slab1 layer number, slab1+slab2 layer number, 1+2+3 layer number .....
  148. self.layers_sum = []
  149. # layers_n-- 1 layer number, 2 layer number ,3.....
  150. self.layers_n = []
  151. # atoms_sum-- 1 atoms number, 2 atoms numbers......
  152. self.atoms_sum = []
  153. # atoms_max-- max atoms number of all slabs
  154. self.atoms_max = 0
  155. # layers_max-- max layers number of all slabs
  156. self.layers_max = 0
  157. def _check_parameters(self):
  158. # check parameters, xlsx
  159. self.check_parameters = PARAMETERS.match(self.parameters)
  160. if not self.check_parameters:
  161. error = 'parameters name is illegal.appropriate file name: parameters_xxx--.xlsx'
  162. raise Illegal_Filename_Exception(error)
  163. # check sheet names
  164. def _check_sheetname(self):
  165. """legal names: substrate slab1 slab2 slab3 .... factors"""
  166. # read sheet names
  167. sheet_names = xlrd.open_workbook(self.path,
  168. on_demand=True).sheet_names()
  169. self.check_sheet_fir = sheet_names[ 0] == 'substrate'
  170. self.check_sheet_las = sheet_names[-1] == 'factors'
  171. slab_names = sheet_names[1:-1]
  172. # check slab names
  173. self.check_sheet_slab = 1
  174. self.check_sheet_rank = 1
  175. sheet_rank = []
  176. for slab in slab_names:
  177. self.check_sheet_slab = self.check_sheet_slab and SHEET_SLAB.match(slab)
  178. try:
  179. sheet_rank.append(int(slab.split('b')[1]))
  180. except:
  181. self.check_sheet_slab = 0
  182. self.check_sheet_rank = sheet_rank == np.linspace(1,len(sheet_rank),
  183. len(sheet_rank),
  184. dtype = int).tolist()
  185. if not self.check_sheet_fir:
  186. error = 'The first sheet should be "substrate"'
  187. raise Illegal_Sheetname_Exception(error)
  188. elif not self.check_sheet_slab:
  189. error = 'appropriate slab names'
  190. raise Illegal_Sheetname_Exception(error)
  191. elif not self.check_sheet_rank:
  192. error = 'Slab names are not in right order'
  193. raise Illegal_Sheetname_Exception(error)
  194. elif not self.check_sheet_las:
  195. error = 'The las sheet should be "factors"'
  196. raise Illegal_Sheetname_Exception(error)
  197. # read all the parameters
  198. def _var_list(self):
  199. """ Read model parameters. construct model parameters list and table"""
  200. pars = {}
  201. xls = xlrd.open_workbook(self.path, on_demand=True)
  202. for sheet_n in xls.sheet_names()[0:-1]:
  203. for key in PARAMETERS_LOCATE.keys():
  204. if key == 'properties':
  205. # properties-- atoms number , layers number and absorption
  206. properties = _load_parameters(self.parameters,'properties',sheet_n)
  207. # atoms_num-- atoms number in one crysatl lattice
  208. atoms_num = properties.at['atoms_num','c1']
  209. # absorption of one layers
  210. absorption = properties.at['absorption','c1']
  211. # layers_num-- layers number in one slab
  212. layers_num = properties.at['layers_num','c1']
  213. self.layers_max = self.layers_max + layers_num
  214. self.layers_sum.append(self.layers_max)
  215. self.layers_n.append(layers_num)
  216. self.atoms_sum.append(atoms_num)
  217. if atoms_num > self.atoms_max:
  218. self.atoms_max = atoms_num
  219. pars['atoms_num'] = atoms_num
  220. pars['absorption'] = absorption
  221. pars['layers_num'] = layers_num
  222. else:
  223. pars[key] = _load_parameters(self.parameters,key,sheet_n)
  224. pars['roughness'] = 1
  225. self.var_list[sheet_n] = pars
  226. pars = {}
  227. return self.var_list
  228. #
  229. # construct parameters tables
  230. def _var_table(self):
  231. self.var_table = {}
  232. # slab_index-- which slab
  233. slab_index = 0
  234. # tot_layer-- total layers till the layer under calculation
  235. tot_layer = 0
  236. #
  237. # talbe--matrix total layers x max atoms
  238. x, y = int(self.layers_max), int(self.atoms_max)
  239. posx_table = np.mat(np.zeros([x, y]))
  240. posy_table = np.mat(np.zeros([x, y]))
  241. posz_table = np.mat(np.zeros([x, y]))
  242. ocup_table = np.mat(np.zeros([x, y]))
  243. elec_table = np.mat(np.zeros([x, y]))
  244. ions_table = []
  245. dw_table = []
  246. slab_list = []
  247. # initalize lattice c modulation list
  248. posz_list = np.ones(x)
  249. posx_list = np.ones(x)
  250. posy_list = np.ones(x)
  251. # contral_table is used to multiply the contral variables
  252. contral_table = np.mat(np.zeros([x, y]))
  253. # first, we should locate and remove the zero value from layers_sum
  254. # for zero values equals to the inexistence of this slab
  255. layers_sum_exist = []
  256. layers_index_exist = []
  257. exist_slab = np.nonzero(np.array(self.layers_sum))[0]
  258. for s in exist_slab:
  259. layers_sum_exist.append(self.layers_sum[int(s)])
  260. layers_index_exist.append(int(s))
  261. for layer_index in range(x):
  262. # a-- determine which layer this layer_index close with
  263. # [5,6,10]-8 = [-3,-2,2]
  264. # "numpy.argmin return the first minimux index"
  265. # if result>0 slab index is a
  266. # elif result<0 slab index is a+1
  267. a = np.argmin(abs(np.array(layers_sum_exist) - layer_index -1))
  268. if (np.array(layers_sum_exist)-layer_index)[a] > 0:
  269. slab_index = layers_index_exist[a]
  270. elif (np.array(self.layers_sum)-layer_index)[a] <= 0:
  271. slab_index = layers_index_exist[a + 1]
  272. else:
  273. print('There must be something wrong! layer index should not bigger than total layer number!')
  274. # recognise which slab
  275. # index which slab
  276. xls = xlrd.open_workbook(self.path,
  277. on_demand=True)
  278. slab_list.append(xls.sheet_names()[slab_index])
  279. par = self.var_list[xls.sheet_names()[slab_index]]
  280. # normalize the lattice matrix and cosntant by substrate lattice
  281. # reduce_lattice = slab_lattice/substrate_lattice
  282. substrate_lattice = self.var_list['substrate']['lattice'].as_matrix()[0,0:3]
  283. slab_lattice = par['lattice'].as_matrix()[0,0:3]
  284. reduce_lattice = slab_lattice/substrate_lattice
  285. # postion x,y and z are constructed by reduce_lattice
  286. posx_table[layer_index,] = par['pos'].loc['pos_x'].as_matrix()*reduce_lattice[0]
  287. posy_table[layer_index,] = par['pos'].loc['pos_y'].as_matrix()*reduce_lattice[1]
  288. ocup_table[layer_index,] = par['ocu'].as_matrix()
  289. elec_table[layer_index,] = par['nel'].as_matrix()
  290. ions_table.append(par['ions'].as_matrix().tolist()[0])
  291. dw_table.append(par['dw'])
  292. # tot_layer-- the layer postion in the current slab
  293. tot_layer = tot_layer + reduce_lattice[2]
  294. # the atom postion in the current layer
  295. posz_table[layer_index] = tot_layer + \
  296. par['pos'].loc['pos_z'].as_matrix()*reduce_lattice[2] - \
  297. self.layers_sum[0]*1
  298. self.var_table = {'posx_table': posx_table,
  299. 'posy_table': posy_table,
  300. 'posz_table': posz_table,
  301. 'posz_list': posz_list,
  302. 'posx_list': posx_list,
  303. 'posy_list': posy_list,
  304. 'ocu_table': ocup_table,
  305. 'nel_table': elec_table,
  306. 'ion_table': ions_table,
  307. 'dw_table': dw_table,
  308. 'slab_list': slab_list,
  309. 'contral_table':contral_table}
  310. return self.var_table