Coverage for tbkit/error_handling.py: 100%
398 statements
« prev ^ index » next coverage.py v7.16.0, created at 2026-09-22 13:16 +0100
« prev ^ index » next coverage.py v7.16.0, created at 2026-09-22 13:16 +0100
1import numpy as np
2import inspect
5ATOL = 1e-3 # matches the distance/angle tolerance used throughout tbkit.system
8###############################
9# GENERIC EXCEPTION HANDLING
10###############################
13def boolean(var, var_name):
14 '''
15 Check if *var* is a boolean.
17 :raises TypeError: Parameter *var* must be a bool.
18 '''
19 if not isinstance(var, bool):
20 raise TypeError('\n\nParameter {} must be a bool.\n'.format(var_name))
23def positive_int(var, var_name):
24 '''
25 Check if *var* is a positive integer.
27 :raises TypeError: Parameter *var* must be an integer.
28 :raises ValueError: Parameter *var* must be a positive integer.
29 '''
30 if not isinstance(var, int):
31 raise TypeError('\n\nParameter {} must be an integer.\n'.format(var_name))
32 if var < 1:
33 raise ValueError('\n\nParameter {} must be a positive integer.\n'.format(var_name))
36def positive_int_lim(var, var_name, nmax):
37 '''
38 Check if *var* is a positive integer smaller than nmax.
40 :raises TypeError: Parameter *var* must be an integer.
41 :raises ValueError: Parameter *var* must be a positive integer.
42 :raises ValueError: Parameter *var* must be a positive integer
43 smaller than nmax.
44 '''
45 if not isinstance(var, int):
46 raise TypeError('\n\nParameter {} must be an integer.\n'.format(var_name))
47 if var < 1:
48 raise ValueError('\n\nParameter {} must be a positive integer.\n'.format(var_name))
49 if var > nmax:
50 raise ValueError('\n\nParameter {} must be a positive integer\n'\
51 'smaller than {}.\n'.format(var_name, nmax))
54def real_number(var, var_name):
55 '''
56 Check if parameter *var* is a real number.
58 :raises TypeError: Parameter *var* must be a real number.
59 '''
60 if not isinstance(var, (int, float)):
61 raise TypeError('\n\nParameter {} must be a real number.\n'.format(var_name))
64def positive_real(var, var_name):
65 '''
66 Check if parameter *var* is a positive number.
68 :raises TypeError: Parameter *var* must be a real number.
69 :raises ValueError: Parameter *var* must be a positive number.
70 '''
71 if not isinstance(var, (int, float)):
72 raise TypeError('\n\nParameter {} must be a real number.\n'.format(var_name))
73 if var <= 0:
74 raise ValueError('\n\nParameter {} must be a positive number.\n'.format(var_name))
77def positive_real_zero(var, var_name):
78 '''
79 Check if parameter *var* is a positive number or zero.
81 :raises TypeError: Parameter *var* must be a real number.
82 :raises ValueError: Parameter *var* must be a positive number or zero.
83 '''
84 if not isinstance(var, (int, float)):
85 raise TypeError('\n\nParameter {} must be a real number.\n'.format(var_name))
86 if var < 0:
87 raise ValueError('\n\nParameter {} must be a positive number or zero.\n'.format(var_name))
90def negative_real(var, var_name):
91 '''
92 Check if parameter *var* is a negative number.
94 :raises TypeError: Parameter *var* must be a real number.
95 :raises ValueError: Parameter *var* must be a negative number.
97 '''
98 if not isinstance(var, (int, float)):
99 raise TypeError('\n\nParameter {} must be a real number.\n'.format(var_name))
100 if var >= 0:
101 raise ValueError('\n\nParameter {} must be a negative number.\n'.format(var_name))
104def number(var, var_name):
105 '''
106 Check if parameter *var* is a number.
108 :raises TypeError: Parameter *var* must be a real number.
109 '''
110 if not isinstance(var, (int, float, complex)):
111 raise TypeError('\n\nParameter {} must be a real number.\n'.format(var_name))
114def is_callable(var, var_name):
115 '''
116 Check if parameter *var* is callable.
118 :raises TypeError: Parameter *var* must be callable.
119 '''
120 if not callable(var):
121 raise TypeError('\n\nParameter {} must be callable.\n'.format(var_name))
124def larger(var1, var_name1, var2, var_name2):
125 '''
126 Check if *var1* larger than *val*.
128 :raises ValueError: Parameter *var1* larger than *var2*.
129 '''
130 if var1 >= var2:
131 raise ValueError('\n\n{} must be larger than {}.\n'
132 .format(var_name1, var_name2))
135def smaller(var1, var_name1, var2, var_name2):
136 '''
137 Check if *var1* smaller than *var2*.
139 :raises ValueError: Parameter *var1* must be smaller than *var2*.
140 '''
141 if var1 >= var2:
142 raise ValueError('\n\n{} must be smaller than {}.\n'
143 .format(var_name1, var_name2))
146def string(var, var_name):
147 '''
148 Check if parameter *var* is a string.
150 :raises TypeError: Parameter *var* must be a string.
151 '''
152 if var is None:
153 return
154 if not isinstance(var, str):
155 raise TypeError('\n\nParameter {} must be a string.\n'.format(var_name))
158def ndarray(var, var_name, length):
159 '''
160 Check if parameter *var* is a numpy array.
162 :raises TypeError: Parameter *var* must be a numpy ndarray.
163 :raises ValueError: length array must be equal to length.
164 '''
165 if not isinstance(var, np.ndarray):
166 raise TypeError('\n\nParameter {} must be a numpy ndarray.\n'.format(var_name))
167 if len(var) != length:
168 raise ValueError('\n\nParameter {} must be a numpy ndarray of {}\n'
169 ''.format(var_name, length))
172def ndarray_null(var, var_name):
173 '''
174 Check if parameter *var* is not a null numpy array.
176 :raises ValueError: Parameter *var* must not be a null numpy ndarray.
177 '''
178 array_null = np.zeros(len(var))
179 if np.allclose(var, array_null):
180 raise ValueError('\n\nParameter {} must not be a null numpy ndarray.\n'.format(var_name))
183def ndarray_empty(var, var_name):
184 '''
185 Check if parameter *var* is not an empty numpy array.
187 :raises ValueError: Parameter *var* must not be an emptynumpy ndarray.
188 '''
189 if var.size == 0:
190 raise ValueError('\n\nParameter {} must not be an emptynumpy ndarray.\n'.format(var_name))
193def list_tuple_2elem(var, var_name):
194 '''
195 Check if parameter *var* is a list/tuple with 2 elements.
197 :raises TypeError: Parameter *var* must be a list/tuple.
198 :raises ValueError: Parameter *var* must contain 2 elements.
199 '''
200 if var is None:
201 return
202 if not isinstance(var, (list, tuple)):
203 raise TypeError('\n\nParameter {} must be a list/tuple\n'.format(var_name))
204 if len(var) != 2:
205 raise ValueError('\n\nParameter {} must be a list/tuple of length two.\n'.format(var_name))
208def tuple_2elem(var, var_name):
209 '''
210 Check if parameter *var* is a tuple with 2 elements.
212 :raises TypeError: Parameter *var* must be a tuple.
213 :raises ValueError: Parameter *var* must contain 2 elements.
214 '''
215 if var is None:
216 return
217 if not isinstance(var, tuple):
218 raise TypeError('\n\nParameter {} must be a tuple\n'.format(var_name))
219 if len(var) != 2:
220 raise ValueError('\n\nParameter {} must be a list/tuple of length two.\n'.format(var_name))
223###############################
224# LATTICE EXCEPTION HANDLING
225###############################
228def lat(lat):
229 '''
230 Check if parameter is an instance of the *lattice*.
231 :raises TypeError: Parameter must be an instance of the class lattice.
232 '''
233 names = inspect.getmro(lat.__class__)
234 if str(names).find('lattice') == -1:
235 raise TypeError('\n\nParameter must be an instance of the class lattice.\n')
238def unit_cell(unit_cell):
239 '''
240 Check parameter *unit_cell*.
242 :raises TypeError: Parameter unit_cell must be a list.
243 :raises KeyError: Dictionaries must contain the key "tag".
244 :raises KeyError: Dictionaries must contain the key "r0".
245 :raises TypeError: Key "tags" must contain a one-character string.
246 :raises ValueError: Key "tags" must contain a one-character string.
247 :raises ValueError: Key "r0" must contain be a list.
248 :raises TypeError: Key "r0" must contain be a tuple.
249 :raises ValueError: Key "r0" must contain a tuple of length two.
250 :raises ValueError: Key "r0" must contain a tuple of two real numbers.
251 '''
252 if not isinstance(unit_cell, list):
253 raise TypeError('\n\nParameter unit_cell must be a list.\n')
254 for dic in unit_cell:
255 if 'tag' not in dic:
256 raise KeyError('\n\nDictionaries must contain the key "tag".\n')
257 if 'r0' not in dic:
258 raise KeyError('\n\nDictionaries must contain the key "r0".\n')
259 if not isinstance(dic['tag'], str):
260 raise TypeError('\n\nKey "tag" must contain a one-character string.\n')
261 if not len(dic['tag']) == 1:
262 raise ValueError('\n\nKey "tag" must be a one-character string.\n')
263 if not isinstance(dic['r0'], tuple):
264 raise TypeError('\n\nKey "r0" must be a tuple.\n')
265 if not len(dic['r0']) == 2:
266 raise ValueError('\n\nKey "r0" must contain a tuple of length two.\n')
267 if not isinstance(dic['r0'][0], (int, float)) or not isinstance(dic['r0'][1], (int, float)):
268 raise ValueError('\n\nKey "r0" must contain a tuple of two real numbers.\n')
271def prim_vec(prim_vec):
272 '''
273 Check parameter *prim_vec*.
275 :raises TypeError: Parameter prim_vec must be a list.
276 :raises ValueError: Parameter prim_vec must be a list
277 of length 1 for 1D lattices or length 2 fro 2D lattices.
278 :raises TypeError: List elements must be tuples.
279 :raises ValueError: List elements must be 1 or 2 tuples.
280 :raises ValueError: Tuples must be of length 2.
281 :raises ValueError: Tuples must containt real numbers.
282 :raises ValueError: Norm of coor should be larger than 0.1.
283 '''
284 if not isinstance(prim_vec, list):
285 raise TypeError('\n\nParameter prim_vec must be a list.\n')
286 if not len(prim_vec) == 1 and not len(prim_vec) == 2:
287 raise ValueError('\n\nParameter prim_vec must be a list.\n'
288 'of length 1 for 1D lattices or length 2 fro 2D lattices.\n')
289 for coor in prim_vec:
290 if not isinstance(coor, tuple):
291 raise TypeError('\n\nParameter prim_vec contain tuples\n')
292 if len(coor) != 2:
293 raise ValueError('\n\nParameter prim_vec contain tuples of length 2.\n')
294 if (not isinstance(coor[0], (int, float))) or \
295 (not isinstance(coor[1], (int, float))):
296 raise ValueError('\n\ncoor must contain real numbers.\n')
297 if coor[0] ** 2 + coor[1] ** 2 < 0.1:
298 raise ValueError('\n\nNorm of coor should be larger than 0.1.\n')
301def get_lattice(prim_vec, n1, n2):
302 '''
303 Check method *get_lattice*.
305 :raises TypeError: Parameter n1 must be an integer.
306 :raises TypeError: Parameter n2 must be an integer.
307 :raises ValueError: Parameter n1 must be a positive integer.
308 :raises ValueError: Parameter n2 must be a positive integer.
309 '''
310 positive_int(n1, 'n1')
311 positive_int(n2, 'n2')
312 if len(prim_vec) == 1 and n2 > 1:
313 raise ValueError('\n\nParameter n2 should be equal to 1\n'
314 'if one primitive vector is given\n')
317def coor(coor):
318 '''
319 Check if *coor* is a structured array with
320 dtype=[('x', 'f8'), ('y', 'f8'), ('tag', 'U1')].
321 '''
322 if coor.dtype != np.dtype([('x', 'f8'), ('y', 'f8'), ('tag', 'U1')]):
323 raise TypeError('\n\nParameter coor dtype must be\n'
324 'dtype=[("x", "f8"), ("y", "f8"), ("tag", "U1")].\n')
327def coor_1d(coor):
328 '''
329 Check if *coor* is 1d (coor['y'] = cst).
330 :raises ValueError: *coor* must be 1d( coor['y'] = cst)..
331 '''
332 if not np.allclose(coor['y'][0], coor['y']):
333 raise ValueError('\n\ncoor["y"] must be constant.\n')
336def remove_sites(index, sites):
337 '''
338 Check method *remove_sites*.
340 :raises TypeError: Parameter index must be a list.
341 :raises ValueError: Parameter index must be a list of integers.
342 :raises ValueError: Indices must be between 0 and sites -1.
343 of integers between 0 and sites
344 '''
345 if not isinstance(index, list):
346 raise TypeError('\n\nParameter index must be a list.\n')
347 if not all(isinstance(i, int) for i in index):
348 raise ValueError('\n\nParameter index must be a list of integers.\n')
349 if not all(-1 < i < sites for i in index):
350 raise ValueError('\n\nElements of index must be between 0 and sites - 1.\n')
353def shift(shift):
354 '''
355 Check *shift_x* and *shift_y*.
356 :raises TypeError: Parameter delta must be a real number.
357 '''
358 if not isinstance(shift, (int, float)):
359 raise TypeError('\n\nParameter shift must be a real number.\n')
362def boundary_line(cx, cy, co):
363 '''
364 Check *boundary_line*.
365 :raises TypeError: Parameter cx must be a real number.
366 :raises TypeError: Parameter cy must be a real number.
367 :raises TypeError: Parameter co must be a real number.
368 '''
369 if not isinstance(cx, (int, float)):
370 raise TypeError('\n\nParameter cx must be a real number.\n')
371 if not isinstance(cy, (int, float)):
372 raise TypeError('\n\nParameter cy must be a real number.\n')
373 if not isinstance(co, (int, float)):
374 raise TypeError('\n\nParameter co must be a real number.\n')
377def ellipse(a, b):
378 '''
379 Check *ellipse_in* and *ellipse_out*.
380 :raises TypeError: Parameter a must be a positive number.
381 :raises TypeError: Parameter b must be a positive number.
382 '''
383 if not isinstance(a, (int, float)):
384 raise TypeError('\n\nParameter a must be a positive number.\n')
385 if not isinstance(b, (int, float)):
386 raise TypeError('\n\nParameter b must be a positive number.\n')
387 if a <= 0:
388 raise ValueError('\n\nParameter a must be a positive number.\n')
389 if b <= 0:
390 raise ValueError('\n\nParameter b must be a positive number.\n')
393def sites(sites):
394 '''
395 Check if *get_lattice* has been called (*coor* not empty).
396 :raises RuntimeError: Run method lat.get_lattice first.
397 '''
398 if sites == 0:
399 raise RuntimeError('\n\nRun method lat.get_lattice first.\n')
402####################################
403# CLASS SYSTEM EXCEPTION HANDLING
404####################################
407def sys(sys):
408 '''
409 Check if parameter is an instance of the *system*.
410 :raises TypeError: Parameter must be an instance of the class system.
411 '''
412 names = inspect.getmro(sys.__class__)
413 if str(names).find('system') == -1:
414 raise TypeError('\n\nParameter must be an instance of the class system.\n')
417def print_hopping(n, nmax):
418 '''
419 Check method *print_vec_hopping*.
421 :raises TypeError: Parameter *nmax* must be an integer.
422 :raises ValueError: Parameter *nmax* must be a positive integer.
423 between 1 and n_max-1.
424 '''
425 if not isinstance(n, int):
426 raise TypeError('\n\nParameter n_max must be an integer.\n')
427 if n < 1 or n > nmax-1:
428 raise ValueError('\n\nParameter n_max must be a positive integer'
429 'between 1 and n_max-1.\n')
432def set_onsite(onsite, tags):
433 '''
434 Check method *set_onsite*.
436 :raises TypeError: Parameter onsite must be a dictionary.
437 :raises ValueError: Parameter onsite keys must be a tag.
438 :raises ValueError: Parameter onsite values must be
439 real and/or complex numbers.
440 '''
441 if not isinstance(onsite, dict):
442 raise TypeError('\n\nParameter onsite must be a dictionary.\n')
443 for tag, val in onsite.items():
444 if tag not in tags:
445 raise ValueError('\n\nParameter onsite keys must be a tag.\n')
446 if not isinstance(val, (int, float, complex)):
447 raise ValueError('\n\nParameter onsite values must be\n'\
448 'real and/or complex numbers.\n')
451def set_hopping(list_hop, n_max):
452 '''
453 Check method *set_hopping*.
455 :raises TypeError: Parameter *list_hop* must be a list.
456 :raises TypeError: Parameter *list_hop* must be a list of dictionary.
457 :raises KeyError: "n" and "t" must be dictionary keys.
458 :raises KeyError: "tag" or "ang" must be a key.
459 :raises KeyError: "tag" and "ang" must be a key.
460 :raises ValueError: Dictionaries must be of length 2, 4, or 4.
461 :raises ValueError: "n" must be between 1 and nmax"
463 '''
464 if not isinstance(list_hop, list):
465 raise TypeError('\n\nParameter *list_hop* must be a list.\n')
466 for dic in list_hop:
467 if not isinstance(dic, dict):
468 raise TypeError('\n\nParameter *list_hop* must be a list of dictionary.\n')
469 if 'n' not in dic or 't' not in dic:
470 raise KeyError('\n\n"n" and "t" must be dictionary keys.\n')
471 if not isinstance(dic['n'], int):
472 raise TypeError('\n\n"n" value must be an integer.\n')
473 if not 0 < dic['n'] <= n_max:
474 raise ValueError('\n\n"n" value must be between 1 and nmax".\n')
475 if not isinstance(dic['t'], (int, float, complex)):
476 raise TypeError('\n\n"t" value must be a real or complex number.\n')
477 if len(dic) == 3:
478 if 'tag' not in dic and 'ang' not in dic:
479 raise KeyError('\n\n"tag" or "ang" must be a key.\n')
480 elif len(dic) == 4:
481 if 'tag' not in dic and 'ang' not in dic:
482 raise KeyError('\n\n"tag" or "ang" must be a key.\n')
483 elif len(dic) > 4:
484 raise ValueError('\n\nDictionaries must be of length 2, 3, or 4.\n')
485 if 'tag' in dic:
486 if not isinstance(dic['tag'], str):
487 raise TypeError('\n\n"tag" value must be a string.\n')
488 if len(dic['tag']) != 2:
489 raise ValueError('\n\n"tag" value must be a string of length 2.\n')
490 if 'ang' in dic:
491 if not isinstance(dic['ang'], (int, float)):
492 raise TypeError('\n\n"ang" value must be a real number.\n')
495def index(ind, dic):
496 '''
497 check if *ind* not empy.
498 '''
499 if np.sum(ind) == 0:
500 raise ValueError('\n\nNo hoppings with parameters {}.\n'.format(dic))
503def set_hopping_def(hop, hopping_def, sites):
504 '''
505 Check method *set_hop_def*.
507 :raises TypeError: Parameter *hopping_def* must be a dictionary
508 :raises TypeError: *hopping_def* keys must be lists.
509 :raises ValueError: *hopping_def* keys must be lists of length 2.
510 :raises ValueError: *hopping_def* keys must be lists of integers.
511 :raises TypeError: *hopping_def* keys must be lists.
512 :raises ValueError: *hopping_def* keys must be integers between 0 and sites-1.
513 :raises ValueError: *hopping_def* keys must be different integers between 0 and sites-1.
514 :raises TypeError: *hopping_def* values must be numbers.
515 '''
516 if not isinstance(hopping_def, dict):
517 raise TypeError('\n\nParameter hopping_def must be a dictionary.\n')
518 for key, val in hopping_def.items():
519 if not isinstance(key, tuple):
520 raise TypeError('\n\nhopping_def keys must be lists.\n')
521 if len(key) != 2:
522 raise TypeError('\n\nhopping_def keys must be lists of length 2.\n')
523 if not isinstance(key[0], int) or not isinstance(key[1], int):
524 raise ValueError('\n\nhopping_def keys must be lists of integers.\n')
525 if key[0] < 0 or key[1] < 0 or key[0] > sites-1 or key[1] > sites-1:
526 raise ValueError('\n\nhopping_def keys must be integers between 0 and sites-1.\n')
527 if key[0] == key[1]:
528 raise ValueError('\n\nhopping_def keys must be different integers between 0 and sites-1.\n')
529 if not isinstance(val, (int, float, complex)):
530 raise TypeError('\n\nhopping_def values must be numbers.\n')
533def set_onsite_def(onsite_def, sites):
534 '''
535 Check method *set_ons_def*.
537 :raises TypeError: Parameter *onsite_def* must be a dictionary.
538 :raises TypeError: *onsite_def* keys must be integers.
539 :raises TypeError: *onsite_def* values must be numbers.
540 :raises ValueError: *onsite_def* keys must be integers between :math:`[0, sites)`.
541 '''
542 if not isinstance(onsite_def, dict):
543 raise TypeError('\n\nParameter onsite_def must be a dictionary.\n')
544 for key, val in onsite_def.items():
545 if not isinstance(key, int):
546 raise TypeError('\n\nonsite_def keys must be integers.\n')
547 if not isinstance(val, (int, float, complex)):
548 raise TypeError('\n\nonsite_def values must be numbers.\n')
549 if key < 0 or key > sites-1:
550 raise ValueError('\n\nonsite_def keys must be integers between 0 and sites-1.\n')
553def hop_n1(hop):
554 '''
555 Check method if self.hop contains nearest neighbours hoppings.
557 :raises ValueError: self.hop must contain nearest neighbours hoppings.
558 '''
559 if len(hop['n'] == 1) == 0:
560 raise ValueError('\n\nParameter hop must contain nearest neighbours hoppings.\n')
563def empty_onsite(onsite):
564 '''
565 Check if *onsite* not empty.
567 :raises RuntimeError: Run method set_onsite first.
568 '''
569 if onsite.size == 0:
570 raise RuntimeError('\n\nRun method set_onsite first\n')
573def empty_hop(hop):
574 '''
575 Check if *hop* not empty.
577 :raises RuntimeError: Run method set_hopping first.
578 '''
579 if hop.size == 0:
580 raise RuntimeError('\n\nRun method set_hopping first\n')
583def hop_sites(hop, sites):
584 '''
585 Check if *hop* indices are smaller than *sites*.
587 :raises ValueError: Run method sys.clean_hopping.
588 '''
589 row_max = np.max(hop['i'])
590 col_max = np.max(hop['i'])
591 ind_max = max(row_max, col_max)
592 if sites < ind_max:
593 raise ValueError('\n\nRun method system.clean_hopping.\n'
594 'and redefine the hoppings.\n')
597def empty_coor(coor):
598 '''
599 Check if *coor* not empty.
601 :raises RuntimeError: Run method lattice.get_lattice first.
602 '''
603 if coor.size == 0:
604 raise RuntimeError('\n\nRun method lattice.get_lattice first.\n')
607def empty_coor_hop(coor_hop):
608 '''
609 Check if *coor_hop* not empty.
611 :raises RuntimeError: Run method system.get_coor_hop first.
612 '''
613 if coor_hop.size == 0:
614 raise RuntimeError('\n\nRun method system.get_coor_hop first.\n')
617def empty_ham(ham):
618 '''
619 Check if Hamiltonian not empty.
621 :raises RuntimeError: Run method system.get_ham first.
622 '''
623 if not ham.nnz:
624 raise RuntimeError('\n\nRun method system.get_ham first.\n')
627def empty_en(en):
628 '''
629 Check if *en* not empty.
631 :raises RuntimeError: Run method get_ham first.
632 '''
633 if en.size == 0:
634 raise RuntimeError('\n\nRun method get_eig first\n')
637def empty_pola(pola):
638 '''
639 Check if *pola* not empty.
641 :raises RuntimeError: Run method get_eig(eigenvec=True) first.
642 '''
643 if pola.size == 0:
644 raise RuntimeError('\n\nRun method get_eig(eigenvec=True) first\n')
647def empty_vn(vn):
648 '''
649 Check if *vn* not empty.
651 :raises RuntimeError: Run method get_eig(eigenvec=True) first.
652 '''
653 if vn.size == 0:
654 raise RuntimeError('\n\nRun method get_eig(eigenvec=True) first\n')
657def empty_ipr(ipr):
658 '''
659 Check if *ipr* not empty.
660 '''
661 if ipr.size == 0:
662 raise RuntimeError('\n\nRun method get_ipr first\n')
665def empty_ndarray(arr, method):
666 '''
667 Check if *arr* is a not empty np.ndarray.
668 '''
669 if arr.size == 0:
670 raise RuntimeError('\n\nRun method {} first\n'. format(method))
673def tag(tag, tags):
674 '''
675 Check tag.
677 :raises TypeError: Parameter *tag* must be a string.
678 :raises ValueError: Parameter *tag* is not in tags.
679 '''
680 if not isinstance(tag, str):
681 raise TypeError('\n\nParameter tag must be a one-character string.\n')
682 if tag not in tags:
683 raise ValueError('\n\nParameter tag is not in tags.\n')
686def angle(angle, angles, upper_part):
687 '''
688 Check angle.
690 :raises TypeError: Parameter *angle* must be
692 * a positive number if *upper_part* is True
693 * a negative real if *upper_part* is False.
694 :raises ValueError: Parameter *angle* is not in hop['ang'].
695 '''
696 if upper_part:
697 positive_real_zero(angle, 'angle, if upper_part=True,')
698 else:
699 negative_real(angle, 'angle, if upper_part=False,')
700 if not np.sum(np.isclose(angle, angles, atol=ATOL)) and \
701 not np.sum(np.isclose(angle, angles - 180, atol=ATOL)):
702 raise ValueError('\n\nParameter angle is not in hop["ang"].\n')
705def lims(lims):
706 '''
707 Check parameter *lims*.
709 :raises TypeError: Parameter lims must be a list.
710 :raises TypeError: Parameter *lims[0]* must be a real number.
711 :raises TypeError: Parameter *lims[1]* must be a real number.
712 :raises ValueError: *lims* must be a list of length 2.
713 :raises ValueError: *lims[0]* must be smaller than *lims[1]*.
714 '''
715 if lims is not None:
716 list_tuple_2elem(lims, 'lims')
717 real_number(lims[0], 'lims[0]')
718 real_number(lims[1], 'lims[1]')
719 smaller(lims[0], 'lims[0]', lims[1], 'lims[1]')
722def lims_positive(lims):
723 '''
724 Check parameter *lims*.
726 :raises TypeError: Parameter lims must be a list.
727 :raises TypeError: Parameter *lims[0]* must be a positive real number.
728 :raises TypeError: Parameter *lims[1]* must be a positive real number.
729 :raises ValueError: *lims* must be a list of length 2.
730 :raises ValueError: *lims[0]* must be smaller than *lims[1]*.
731 '''
732 if lims is not None:
733 list_tuple_2elem(lims, 'lims')
734 positive_real(lims[0], 'lims[0]')
735 positive_real(lims[1], 'lims[1]')
736 smaller(lims[0], 'lims[0]', lims[1], 'lims[1]')
739#################################
740# CLASS PLOT EXCEPTION HANDLING
741#################################
744def fig(fig):
745 '''
746 Check if fig is an instance of *Figure*.
748 :raises TypeError: fig must be an instance of *Figure*.
749 '''
750 if not fig.__class__.__name__ == 'Figure':
751 raise TypeError('\n\nfig must be an instance of *Figure*.\n')
754def ani(ani):
755 '''
756 Check if ani is an instance of *FuncAnimation*.
758 :raises TypeError: ani must be an instance of *FuncAnimation*.
759 '''
760 if not ani.__class__.__name__ == 'FuncAnimation':
761 raise TypeError('\n\nani must be an instance of *FuncAnimation*.\n')
764def file_format(file_format):
765 '''
766 Check if file_format is a string 'png', 'pdf', 'ps', 'eps', or 'svg'.
768 :raises TypeError: file_format must be a string.
769 :raises ValueError: file_format must be a string given by 'png', 'pdf', 'ps', 'eps', or 'svg'.
771 '''
772 if not isinstance(file_format, str):
773 raise TypeError('\n\nfile_format must be a string.\n')
774 if file_format not in ['png', 'pdf', 'ps', 'eps', 'svg']:
775 raise ValueError('\n\nfile_format must be a string given by,\n'\
776 ' "png", "pdf", "ps", "eps", or "svg".\n')
779####################################
780# PROPAGATION
781####################################
784def get_pump(hams):
785 if not isinstance(hams, list):
786 raise TypeError('\n\nhams must be a list.\n')
787 for ham in hams:
788 empty_ham(ham)
790def prop_type(prop_type):
791 string(prop_type, 'prop_type')
792 if prop_type not in ['real', 'imag', 'norm']:
793 raise ValueError('\n\nParameter prop_type must be a string:\n'
794 '"real", "imag", "norm".\n')
797####################################
798# CLASS KSPACE EXCEPTION HANDLING
799####################################
802def k_vector(vec, var_name, ndim):
803 '''
804 Check that *vec* is a tuple/list of *ndim* real numbers.
806 :raises TypeError: Parameter *var_name* must be a tuple/list.
807 :raises ValueError: Parameter *var_name* must be of length *ndim*.
808 :raises TypeError: Parameter *var_name* must contain real numbers.
809 '''
810 if not isinstance(vec, (tuple, list, np.ndarray)):
811 raise TypeError('\n\nParameter {} must be a tuple, list, or ndarray.\n'.format(var_name))
812 if len(vec) != ndim:
813 raise ValueError('\n\nParameter {} must be of length {}.\n'.format(var_name, ndim))
814 for val in vec:
815 if not isinstance(val, (int, float, np.integer, np.floating)):
816 raise TypeError('\n\nParameter {} must contain real numbers.\n'.format(var_name))
819def spin_matrix(t, var_name):
820 '''
821 Check a spinful "t" or onsite value: either a plain number, or a 2x2
822 complex matrix.
824 :raises TypeError: Parameter *var_name* must be a number or a 2x2 matrix.
825 '''
826 if isinstance(t, (int, float, complex)):
827 return
828 t = np.asarray(t)
829 if t.shape != (2, 2):
830 raise TypeError('\n\nParameter {} must be a number or a 2x2 matrix.\n'.format(var_name))
833def set_hopping_kspace(list_hop, n_sites, ndim, spin=False):
834 '''
835 Check method *kspace.set_hopping*.
837 :raises TypeError: Parameter *list_hop* must be a list of dictionaries.
838 :raises KeyError: "i", "j", "R", and "t" must be dictionary keys.
839 :raises ValueError: "i" and "j" must be site indices between 0 and n_sites-1.
840 :raises ValueError: "R" must be a tuple of *ndim* integers.
841 :raises TypeError: "t" must be a real or complex number (or, if *spin*,
842 a 2x2 matrix).
843 '''
844 if not isinstance(list_hop, list):
845 raise TypeError('\n\nParameter list_hop must be a list.\n')
846 for dic in list_hop:
847 if not isinstance(dic, dict):
848 raise TypeError('\n\nParameter list_hop must be a list of dictionaries.\n')
849 if not {'i', 'j', 'R', 't'} <= set(dic):
850 raise KeyError('\n\n"i", "j", "R", and "t" must be dictionary keys.\n')
851 if not isinstance(dic['i'], int) or not isinstance(dic['j'], int):
852 raise TypeError('\n\n"i" and "j" must be integers.\n')
853 if not (0 <= dic['i'] < n_sites) or not (0 <= dic['j'] < n_sites):
854 raise ValueError('\n\n"i" and "j" must be site indices between 0 and {}.\n'.format(n_sites-1))
855 if not isinstance(dic['R'], tuple) or len(dic['R']) != ndim:
856 raise ValueError('\n\n"R" must be a tuple of {} integers.\n'.format(ndim))
857 if not all(isinstance(n, int) for n in dic['R']):
858 raise TypeError('\n\n"R" must be a tuple of integers.\n')
859 if dic['i'] == dic['j'] and dic['R'] == (0,) * ndim:
860 raise ValueError('\n\nUse kspace.set_onsite for i == j and R == 0.\n')
861 if spin:
862 spin_matrix(dic['t'], '"t"')
863 elif not isinstance(dic['t'], (int, float, complex)):
864 raise TypeError('\n\n"t" value must be a real or complex number.\n')
867def set_onsite_kspace(dict_onsite, tags, spin=False):
868 '''
869 Check method *kspace.set_onsite*.
871 :raises TypeError: Parameter *dict_onsite* must be a dictionary.
872 :raises ValueError: keys must be tags.
873 :raises TypeError: values must be real or complex numbers (or, if
874 *spin*, a pair of real/complex numbers).
875 '''
876 if not isinstance(dict_onsite, dict):
877 raise TypeError('\n\nParameter dict_onsite must be a dictionary.\n')
878 for tag, val in dict_onsite.items():
879 if tag not in tags:
880 raise ValueError('\n\nParameter dict_onsite keys must be a tag.\n')
881 if spin and not isinstance(val, (int, float, complex)):
882 if not (isinstance(val, (tuple, list)) and len(val) == 2
883 and all(isinstance(v, (int, float, complex)) for v in val)):
884 raise TypeError('\n\nParameter dict_onsite values must be a number, or, '
885 'if spin, a pair of numbers (E_up, E_down).\n')
886 elif not spin and not isinstance(val, (int, float, complex)):
887 raise TypeError('\n\nParameter dict_onsite values must be real and/or complex numbers.\n')
890def k_path_points(points, ndim):
891 '''
892 Check parameter *points* used by *kspace.k_path*.
894 :raises TypeError: Parameter points must be a list.
895 :raises ValueError: Parameter points must contain at least two k-points.
896 '''
897 if not isinstance(points, list):
898 raise TypeError('\n\nParameter points must be a list of k-points.\n')
899 if len(points) < 2:
900 raise ValueError('\n\nParameter points must contain at least two k-points.\n')
901 for i, pt in enumerate(points):
902 k_vector(pt, 'points[{}]'.format(i), ndim)
905####################################
906# DENSITY OF STATES
907####################################
910def dos_kernel(kernel):
911 '''
912 Check parameter *kernel* used by *dos.density_of_states*.
914 :raises TypeError: Parameter kernel must be a string.
915 :raises ValueError: Parameter kernel must be "gaussian" or "lorentzian".
916 '''
917 string(kernel, 'kernel')
918 if kernel not in ['gaussian', 'lorentzian']:
919 raise ValueError('\n\nParameter kernel must be a string:\n'
920 '"gaussian", "lorentzian".\n')
923def nk(nk, ndim):
924 '''
925 Check parameter *nk* used by *kspace.mesh_bands* / *kspace.berry_curvature*.
927 :raises TypeError: Parameter nk must be an integer or a tuple of integers.
928 :raises ValueError: Parameter nk (or each of its elements) must be a
929 positive integer.
930 :raises ValueError: Parameter nk must be a tuple of length *ndim*.
931 '''
932 if isinstance(nk, int):
933 positive_int(nk, 'nk')
934 return
935 if not isinstance(nk, tuple):
936 raise TypeError('\n\nParameter nk must be an integer or a tuple of integers.\n')
937 if len(nk) != ndim:
938 raise ValueError('\n\nParameter nk must be of length {}.\n'.format(ndim))
939 for n in nk:
940 positive_int(n, 'nk')
943####################################
944# TOPOLOGY
945####################################
948def dim_2(dim):
949 '''
950 Check that the model is 2D. Berry curvature / Chern number are only
951 defined for a 2D Brillouin zone.
953 :raises ValueError: This calculation requires a 2D lattice.
954 '''
955 if dim != 2:
956 raise ValueError('\n\nThis calculation requires a 2D lattice '
957 '(two primitive vectors).\n')
960def direction(direction):
961 '''
962 Check parameter *direction* used by *kspace.ribbon*.
964 :raises TypeError: Parameter direction must be an integer.
965 :raises ValueError: Parameter direction must be 0 or 1.
966 '''
967 if not isinstance(direction, int):
968 raise TypeError('\n\nParameter direction must be an integer.\n')
969 if direction not in (0, 1):
970 raise ValueError('\n\nParameter direction must be 0 or 1.\n')
973def band_indices(bands, norb):
974 '''
975 Check parameter *bands* used by *kspace.berry_curvature*.
977 :raises TypeError: Parameter bands must be a non-empty list of integers.
978 :raises ValueError: Parameter bands must be a list of distinct band
979 indices between 0 and norb-1.
980 '''
981 if not isinstance(bands, list) or not bands:
982 raise TypeError('\n\nParameter bands must be a non-empty list of integers.\n')
983 if not all(isinstance(b, int) for b in bands):
984 raise TypeError('\n\nParameter bands must be a non-empty list of integers.\n')
985 if len(set(bands)) != len(bands):
986 raise ValueError('\n\nParameter bands must be a list of distinct band indices.\n')
987 if not all(0 <= b < norb for b in bands):
988 raise ValueError('\n\nParameter bands must be integers between 0 and {}.\n'.format(norb-1))