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

1import numpy as np 

2import inspect 

3 

4 

5ATOL = 1e-3 # matches the distance/angle tolerance used throughout tbkit.system 

6 

7 

8############################### 

9# GENERIC EXCEPTION HANDLING 

10############################### 

11 

12 

13def boolean(var, var_name): 

14 ''' 

15 Check if *var* is a boolean. 

16 

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)) 

21 

22 

23def positive_int(var, var_name): 

24 ''' 

25 Check if *var* is a positive integer. 

26 

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)) 

34 

35 

36def positive_int_lim(var, var_name, nmax): 

37 ''' 

38 Check if *var* is a positive integer smaller than nmax. 

39 

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)) 

52 

53 

54def real_number(var, var_name): 

55 ''' 

56 Check if parameter *var* is a real number. 

57 

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)) 

62 

63 

64def positive_real(var, var_name): 

65 ''' 

66 Check if parameter *var* is a positive number. 

67 

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)) 

75 

76 

77def positive_real_zero(var, var_name): 

78 ''' 

79 Check if parameter *var* is a positive number or zero. 

80 

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)) 

88 

89 

90def negative_real(var, var_name): 

91 ''' 

92 Check if parameter *var* is a negative number. 

93 

94 :raises TypeError: Parameter *var* must be a real number. 

95 :raises ValueError: Parameter *var* must be a negative number. 

96 

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)) 

102 

103 

104def number(var, var_name): 

105 ''' 

106 Check if parameter *var* is a number. 

107 

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)) 

112 

113 

114def is_callable(var, var_name): 

115 ''' 

116 Check if parameter *var* is callable. 

117 

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)) 

122 

123 

124def larger(var1, var_name1, var2, var_name2): 

125 ''' 

126 Check if *var1* larger than *val*. 

127 

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)) 

133 

134 

135def smaller(var1, var_name1, var2, var_name2): 

136 ''' 

137 Check if *var1* smaller than *var2*. 

138 

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)) 

144 

145 

146def string(var, var_name): 

147 ''' 

148 Check if parameter *var* is a string. 

149 

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)) 

156 

157 

158def ndarray(var, var_name, length): 

159 ''' 

160 Check if parameter *var* is a numpy array. 

161 

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)) 

170 

171 

172def ndarray_null(var, var_name): 

173 ''' 

174 Check if parameter *var* is not a null numpy array. 

175 

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)) 

181 

182 

183def ndarray_empty(var, var_name): 

184 ''' 

185 Check if parameter *var* is not an empty numpy array. 

186 

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)) 

191 

192 

193def list_tuple_2elem(var, var_name): 

194 ''' 

195 Check if parameter *var* is a list/tuple with 2 elements. 

196 

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)) 

206 

207 

208def tuple_2elem(var, var_name): 

209 ''' 

210 Check if parameter *var* is a tuple with 2 elements. 

211 

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)) 

221 

222 

223############################### 

224# LATTICE EXCEPTION HANDLING 

225############################### 

226 

227 

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') 

236 

237 

238def unit_cell(unit_cell): 

239 ''' 

240 Check parameter *unit_cell*. 

241 

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') 

269 

270 

271def prim_vec(prim_vec): 

272 ''' 

273 Check parameter *prim_vec*. 

274 

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') 

299 

300 

301def get_lattice(prim_vec, n1, n2): 

302 ''' 

303 Check method *get_lattice*. 

304 

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') 

315 

316 

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') 

325 

326 

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') 

334 

335 

336def remove_sites(index, sites): 

337 ''' 

338 Check method *remove_sites*. 

339 

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') 

351 

352 

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') 

360 

361 

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') 

375 

376 

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') 

391 

392 

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') 

400 

401 

402#################################### 

403# CLASS SYSTEM EXCEPTION HANDLING 

404#################################### 

405 

406 

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') 

415 

416 

417def print_hopping(n, nmax): 

418 ''' 

419 Check method *print_vec_hopping*. 

420 

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') 

430 

431 

432def set_onsite(onsite, tags): 

433 ''' 

434 Check method *set_onsite*. 

435 

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') 

449 

450 

451def set_hopping(list_hop, n_max): 

452 ''' 

453 Check method *set_hopping*. 

454 

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" 

462 

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') 

493 

494 

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)) 

501 

502 

503def set_hopping_def(hop, hopping_def, sites): 

504 ''' 

505 Check method *set_hop_def*. 

506 

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') 

531 

532 

533def set_onsite_def(onsite_def, sites): 

534 ''' 

535 Check method *set_ons_def*. 

536 

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') 

551 

552 

553def hop_n1(hop): 

554 ''' 

555 Check method if self.hop contains nearest neighbours hoppings. 

556 

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') 

561 

562 

563def empty_onsite(onsite): 

564 ''' 

565 Check if *onsite* not empty. 

566 

567 :raises RuntimeError: Run method set_onsite first. 

568 ''' 

569 if onsite.size == 0: 

570 raise RuntimeError('\n\nRun method set_onsite first\n') 

571 

572 

573def empty_hop(hop): 

574 ''' 

575 Check if *hop* not empty. 

576 

577 :raises RuntimeError: Run method set_hopping first. 

578 ''' 

579 if hop.size == 0: 

580 raise RuntimeError('\n\nRun method set_hopping first\n') 

581 

582 

583def hop_sites(hop, sites): 

584 ''' 

585 Check if *hop* indices are smaller than *sites*. 

586 

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') 

595 

596 

597def empty_coor(coor): 

598 ''' 

599 Check if *coor* not empty. 

600 

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') 

605 

606 

607def empty_coor_hop(coor_hop): 

608 ''' 

609 Check if *coor_hop* not empty. 

610 

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') 

615 

616 

617def empty_ham(ham): 

618 ''' 

619 Check if Hamiltonian not empty. 

620 

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') 

625 

626 

627def empty_en(en): 

628 ''' 

629 Check if *en* not empty. 

630 

631 :raises RuntimeError: Run method get_ham first. 

632 ''' 

633 if en.size == 0: 

634 raise RuntimeError('\n\nRun method get_eig first\n') 

635 

636 

637def empty_pola(pola): 

638 ''' 

639 Check if *pola* not empty. 

640 

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') 

645 

646 

647def empty_vn(vn): 

648 ''' 

649 Check if *vn* not empty. 

650 

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') 

655 

656 

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') 

663 

664 

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)) 

671 

672 

673def tag(tag, tags): 

674 ''' 

675 Check tag. 

676 

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') 

684 

685 

686def angle(angle, angles, upper_part): 

687 ''' 

688 Check angle. 

689 

690 :raises TypeError: Parameter *angle* must be 

691 

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') 

703 

704 

705def lims(lims): 

706 ''' 

707 Check parameter *lims*. 

708 

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]') 

720 

721 

722def lims_positive(lims): 

723 ''' 

724 Check parameter *lims*. 

725 

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]') 

737 

738 

739################################# 

740# CLASS PLOT EXCEPTION HANDLING 

741################################# 

742 

743 

744def fig(fig): 

745 ''' 

746 Check if fig is an instance of *Figure*. 

747 

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') 

752 

753 

754def ani(ani): 

755 ''' 

756 Check if ani is an instance of *FuncAnimation*. 

757 

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') 

762 

763 

764def file_format(file_format): 

765 ''' 

766 Check if file_format is a string 'png', 'pdf', 'ps', 'eps', or 'svg'. 

767 

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'. 

770 

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') 

777 

778 

779#################################### 

780# PROPAGATION 

781#################################### 

782 

783 

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) 

789 

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') 

795 

796 

797#################################### 

798# CLASS KSPACE EXCEPTION HANDLING 

799#################################### 

800 

801 

802def k_vector(vec, var_name, ndim): 

803 ''' 

804 Check that *vec* is a tuple/list of *ndim* real numbers. 

805 

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)) 

817 

818 

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. 

823 

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)) 

831 

832 

833def set_hopping_kspace(list_hop, n_sites, ndim, spin=False): 

834 ''' 

835 Check method *kspace.set_hopping*. 

836 

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') 

865 

866 

867def set_onsite_kspace(dict_onsite, tags, spin=False): 

868 ''' 

869 Check method *kspace.set_onsite*. 

870 

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') 

888 

889 

890def k_path_points(points, ndim): 

891 ''' 

892 Check parameter *points* used by *kspace.k_path*. 

893 

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) 

903 

904 

905#################################### 

906# DENSITY OF STATES 

907#################################### 

908 

909 

910def dos_kernel(kernel): 

911 ''' 

912 Check parameter *kernel* used by *dos.density_of_states*. 

913 

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') 

921 

922 

923def nk(nk, ndim): 

924 ''' 

925 Check parameter *nk* used by *kspace.mesh_bands* / *kspace.berry_curvature*. 

926 

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') 

941 

942 

943#################################### 

944# TOPOLOGY 

945#################################### 

946 

947 

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. 

952 

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') 

958 

959 

960def direction(direction): 

961 ''' 

962 Check parameter *direction* used by *kspace.ribbon*. 

963 

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') 

971 

972 

973def band_indices(bands, norb): 

974 ''' 

975 Check parameter *bands* used by *kspace.berry_curvature*. 

976 

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))