1###################################################################### 2# # 3# Copyright 2009 Lucas Heitzmann Gabrielli. # 4# This file is part of gdspy, distributed under the terms of the # 5# Boost Software License - Version 1.0. See the accompanying # 6# LICENSE file or <http://www.boost.org/LICENSE_1_0.txt> # 7# # 8###################################################################### 9 10import pytest 11import gdspy 12import uuid 13import datetime 14from tutils import hash_file 15 16gdspy.library.use_current_library = False 17 18 19def unique(): 20 return str(uuid.uuid4()) 21 22 23def test_add(): 24 lib = gdspy.GdsLibrary() 25 c1 = gdspy.Cell("gl_add_1") 26 c2 = gdspy.Cell("gl_add_2") 27 c3 = gdspy.Cell("gl_add_3") 28 r1 = gdspy.CellReference(c1) 29 with pytest.warns(UserWarning): 30 r2 = gdspy.CellReference("gl_add_2") 31 c3.add([r1, r2]) 32 lib.add(c1) 33 lib.add((c2, c3)) 34 assert lib.cells == {"gl_add_1": c1, "gl_add_2": c2, "gl_add_3": c3} 35 lib = gdspy.GdsLibrary() 36 lib.add(c3) 37 assert lib.cells == {"gl_add_1": c1, "gl_add_3": c3} 38 39 40def test_duplicate(): 41 name = "gl_duplicate" 42 lib = gdspy.GdsLibrary() 43 lib.add(gdspy.Cell(name)) 44 c = gdspy.Cell(name) 45 with pytest.raises(ValueError) as e: 46 lib.add(c) 47 assert name in str(e.value) 48 49 lib.add(c, overwrite_duplicate=True) 50 assert lib.cells == {name: c} 51 52 cl = [gdspy.Cell(name), gdspy.Cell(name + "1")] 53 with pytest.raises(ValueError) as e: 54 lib.add(cl) 55 assert name in str(e.value) 56 57 lib.add(cl, overwrite_duplicate=True) 58 assert lib.cells == {name: cl[0], name + "1": cl[1]} 59 60 61def test_add_update(): 62 lib = gdspy.GdsLibrary() 63 main = gdspy.Cell("MAIN") 64 c1 = gdspy.Cell("C1") 65 c2 = gdspy.Cell("C2") 66 c3 = gdspy.Cell("C1") 67 r1 = gdspy.CellReference(c1) 68 main.add(r1) 69 with pytest.warns(UserWarning): 70 r2 = gdspy.CellArray("C1", 1, 1, (1, 1)) 71 main.add(r2) 72 r3 = gdspy.CellReference(c2) 73 main.add(r3) 74 r4 = gdspy.CellReference(c3) 75 c2.add(r4) 76 with pytest.warns(UserWarning): 77 r5 = gdspy.CellReference("C3") 78 c1.add(r5) 79 with pytest.warns(UserWarning): 80 r6 = gdspy.CellReference("C2") 81 main.add(r6) 82 lib.add([main, c1, c2], include_dependencies=False) 83 lib.add(c3, include_dependencies=False, overwrite_duplicate=True) 84 assert r1.ref_cell is c3 85 assert r2.ref_cell is c3 86 assert r3.ref_cell is c2 87 assert r4.ref_cell is c3 88 assert r5.ref_cell == "C3" 89 assert r6.ref_cell == "C2" 90 91 92def test_add_update2(): 93 lib = gdspy.GdsLibrary() 94 main = gdspy.Cell("MAIN") 95 c1 = gdspy.Cell("C1") 96 c2 = gdspy.Cell("C2") 97 c3 = gdspy.Cell("C1") 98 r1 = gdspy.CellReference(c1) 99 main.add(r1) 100 with pytest.warns(UserWarning): 101 r2 = gdspy.CellArray("C1", 1, 1, (1, 1)) 102 main.add(r2) 103 r3 = gdspy.CellReference(c2) 104 main.add(r3) 105 r4 = gdspy.CellReference(c3) 106 c2.add(r4) 107 with pytest.warns(UserWarning): 108 r5 = gdspy.CellReference("C3") 109 c1.add(r5) 110 with pytest.warns(UserWarning): 111 r6 = gdspy.CellReference("C2") 112 main.add(r6) 113 lib.add([main, c1, c2], include_dependencies=False) 114 lib.add( 115 c3, 116 include_dependencies=False, 117 overwrite_duplicate=True, 118 update_references=False, 119 ) 120 assert r1.ref_cell is c1 121 assert r2.ref_cell == "C1" 122 assert r3.ref_cell is c2 123 assert r4.ref_cell is c3 124 assert r5.ref_cell == "C3" 125 assert r6.ref_cell == "C2" 126 127 128def test_remove(): 129 lib = gdspy.GdsLibrary() 130 main = gdspy.Cell("MAIN") 131 c1 = gdspy.Cell("C1") 132 c2 = gdspy.Cell("C2") 133 c3 = gdspy.Cell("C1") 134 r1 = gdspy.CellReference(c1) 135 main.add(r1) 136 with pytest.warns(UserWarning): 137 r2 = gdspy.CellArray("C1", 1, 1, (1, 1)) 138 main.add(r2) 139 r3 = gdspy.CellReference(c2) 140 main.add(r3) 141 r4 = gdspy.CellReference(c3) 142 c2.add(r4) 143 with pytest.warns(UserWarning): 144 r5 = gdspy.CellReference("C3") 145 c1.add(r5) 146 with pytest.warns(UserWarning): 147 r6 = gdspy.CellReference("C2") 148 main.add(r6) 149 lib.add([main, c1, c2], include_dependencies=False) 150 assert lib.remove("C3") == 1 151 assert len(c1.references) == 0 152 assert len(c2.references) == 1 153 assert c2.references[0] is r4 154 assert lib.remove(c1) == 3 155 assert "C1" not in lib.cells 156 assert len(main.references) == 2 157 assert main.references[0] is r3 158 assert main.references[1] is r6 159 assert len(c2.references) == 0 160 161 162def test_replace(): 163 lib = gdspy.GdsLibrary() 164 main = gdspy.Cell("MAIN") 165 c1 = gdspy.Cell("C1") 166 c2 = gdspy.Cell("C2") 167 c3 = gdspy.Cell("C1") 168 r1 = gdspy.CellReference(c1) 169 main.add(r1) 170 with pytest.warns(UserWarning): 171 r2 = gdspy.CellArray("C1", 1, 1, (1, 1)) 172 main.add(r2) 173 r3 = gdspy.CellReference(c2) 174 main.add(r3) 175 r4 = gdspy.CellReference(c3) 176 c2.add(r4) 177 with pytest.warns(UserWarning): 178 r5 = gdspy.CellReference("C3") 179 c1.add(r5) 180 with pytest.warns(UserWarning): 181 r6 = gdspy.CellReference("C2") 182 main.add(r6) 183 lib.add([main, c1, c2], include_dependencies=False) 184 assert lib.replace_references(c2, c3) == 2 185 assert r3.ref_cell is c3 186 assert r6.ref_cell is c3 187 assert lib.replace_references("C3", "C1") == 1 188 assert r5.ref_cell is c1 189 assert lib.replace_references("C1", c2) == 6 190 assert r1.ref_cell is c2 191 assert r2.ref_cell is c2 192 assert r3.ref_cell is c2 193 assert r4.ref_cell is c2 194 assert r5.ref_cell is c2 195 assert r6.ref_cell is c2 196 197 198def test_rename(): 199 lib = gdspy.GdsLibrary() 200 main = gdspy.Cell("MAIN") 201 c1 = gdspy.Cell("C1") 202 c2 = gdspy.Cell("C2") 203 c3 = gdspy.Cell("C1") 204 r1 = gdspy.CellReference(c1) 205 main.add(r1) 206 with pytest.warns(UserWarning): 207 r2 = gdspy.CellArray("C1", 1, 1, (1, 1)) 208 main.add(r2) 209 r3 = gdspy.CellReference(c2) 210 main.add(r3) 211 r4 = gdspy.CellReference(c3) 212 c2.add(r4) 213 with pytest.warns(UserWarning): 214 r5 = gdspy.CellReference("C3") 215 c1.add(r5) 216 with pytest.warns(UserWarning): 217 r6 = gdspy.CellReference("C2") 218 main.add(r6) 219 lib.add([main, c1, c2], include_dependencies=False) 220 with pytest.raises(ValueError): 221 lib.rename_cell(c3, "C3") 222 assert c3.name == "C1" 223 with pytest.raises(ValueError): 224 lib.rename_cell(c2, "C1") 225 assert c2.name == "C2" 226 assert lib.rename_cell(c1, "C3") == 2 227 assert c1.name == "C3" 228 assert lib.cells["C3"] is c1 229 assert lib.rename_cell(c2, "X2", False) == 0 230 assert c2.name == "X2" 231 assert lib.cells["X2"] is c2 232 assert r1.ref_cell is c1 233 assert r2.ref_cell is c1 234 assert r3.ref_cell is c2 235 assert r4.ref_cell is c1 236 assert r5.ref_cell == "C3" 237 assert r6.ref_cell == "C2" 238 239 240@pytest.fixture 241def tree(): 242 c = [gdspy.Cell("tree_" + unique()) for _ in range(8)] 243 lib = gdspy.GdsLibrary() 244 lib.add(c) 245 c[0].add(gdspy.CellReference(c[1])) 246 c[0].add(gdspy.CellReference(c[3])) 247 c[1].add(gdspy.CellReference(c[2])) 248 c[1].add(gdspy.CellArray(c[2], 2, 1, (0, 0))) 249 c[1].add(gdspy.CellArray(c[3], 2, 1, (0, 0))) 250 c[4].add(gdspy.CellReference(c[3])) 251 c[6].add(gdspy.CellArray(c[5], 2, 1, (0, 0))) 252 return lib, c 253 254 255def test_top_level_1(tree): 256 lib, c = tree 257 tl = lib.top_level() 258 assert len(tl) == 4 and c[0] in tl and c[4] in tl and c[6] in tl and c[7] in tl 259 260 261def test_top_level_2(tree): 262 lib, c = tree 263 c[7].add(gdspy.CellReference(c[0])) 264 c[7].add(gdspy.CellReference(c[4])) 265 c[7].add(gdspy.CellReference(c[6])) 266 assert lib.top_level() == [c[7]] 267 268 269def test_top_level_3(tree): 270 lib, c = tree 271 c[7].add(gdspy.CellReference(c[0])) 272 c[3].add(gdspy.CellReference(c[4])) 273 c[2].add(gdspy.CellReference(c[6])) 274 c[1].add(gdspy.CellReference(c[7])) 275 assert lib.top_level() == [] 276 277 278def test_rw_gds(tmpdir): 279 lib = gdspy.GdsLibrary("lib", unit=2e-3, precision=1e-5) 280 c1 = gdspy.Cell("gl_rw_gds_1") 281 c1.add(gdspy.Rectangle((0, -1), (1, 2), 2, 4)) 282 c1.add(gdspy.Label("label", (1, -1), "w", 45, 1.5, True, 5, 6)) 283 c2 = gdspy.Cell("gl_rw_gds_2") 284 c2.add(gdspy.Round((0, 0), 1, number_of_points=32, max_points=20)) 285 c3 = gdspy.Cell("gl_rw_gds_3") 286 c3.add(gdspy.CellReference(c1, (0, 1), -90, 2, True)) 287 c4 = gdspy.Cell("gl_rw_gds_4") 288 c4.add(gdspy.CellArray(c2, 2, 3, (1, 4), (-1, -2), 180, 0.5, True)) 289 lib.add((c1, c2, c3, c4)) 290 291 fname1 = str(tmpdir.join("test1.gds")) 292 lib.write_gds(fname1) 293 lib1 = gdspy.GdsLibrary( 294 infile=fname1, 295 unit=1e-3, 296 precision=1e-6, 297 units="convert", 298 rename={"gl_rw_gds_1": "1"}, 299 layers={2: 4}, 300 datatypes={4: 2}, 301 texttypes={6: 7}, 302 ) 303 assert lib1.name == "lib" 304 assert len(lib1.cells) == 4 305 assert set(lib1.cells.keys()) == {"1", "gl_rw_gds_2", "gl_rw_gds_3", "gl_rw_gds_4"} 306 c = lib1.cells["1"] 307 assert len(c.polygons) == len(c.labels) == 1 308 assert c.polygons[0].area() == 12.0 309 assert c.polygons[0].layers == [4] 310 assert c.polygons[0].datatypes == [2] 311 assert c.labels[0].text == "label" 312 assert c.labels[0].position[0] == 2 and c.labels[0].position[1] == -2 313 assert c.labels[0].anchor == 4 314 assert c.labels[0].rotation == 45 315 assert c.labels[0].magnification == 1.5 316 assert c.labels[0].x_reflection == True 317 assert c.labels[0].layer == 5 318 assert c.labels[0].texttype == 7 319 320 c = lib1.cells["gl_rw_gds_2"] 321 assert len(c.polygons) == 2 322 assert isinstance(c.polygons[0], gdspy.Polygon) and isinstance( 323 c.polygons[1], gdspy.Polygon 324 ) 325 326 c = lib1.cells["gl_rw_gds_3"] 327 assert len(c.references) == 1 328 assert isinstance(c.references[0], gdspy.CellReference) 329 assert c.references[0].ref_cell == lib1.cells["1"] 330 assert c.references[0].origin[0] == 0 and c.references[0].origin[1] == 2 331 assert c.references[0].rotation == -90 332 assert c.references[0].magnification == 2 333 assert c.references[0].x_reflection == True 334 335 c = lib1.cells["gl_rw_gds_4"] 336 assert len(c.references) == 1 337 assert isinstance(c.references[0], gdspy.CellArray) 338 assert c.references[0].ref_cell == lib1.cells["gl_rw_gds_2"] 339 assert c.references[0].origin[0] == -2 and c.references[0].origin[1] == -4 340 assert c.references[0].rotation == 180 341 assert c.references[0].magnification == 0.5 342 assert c.references[0].x_reflection == True 343 assert c.references[0].spacing[0] == 2 and c.references[0].spacing[1] == 8 344 assert c.references[0].columns == 2 345 assert c.references[0].rows == 3 346 347 fname2 = str(tmpdir.join("test2.gds")) 348 lib.name = "lib2" 349 with open(fname2, "wb") as fout: 350 lib.write_gds(fout) 351 with open(fname2, "rb") as fin: 352 lib2 = gdspy.GdsLibrary() 353 lib2.read_gds(fin) 354 assert lib2.name == "lib2" 355 assert len(lib2.cells) == 4 356 357 358def test_properties(tmpdir): 359 lib = gdspy.GdsLibrary() 360 c1 = lib.new_cell("POLY") 361 rect = gdspy.Rectangle((0, 0), (2, 1)) 362 rect.properties[1] = "test1" 363 rect.properties[126] = "test_126" 364 lbl = gdspy.Label("LABEL", (20, 20)) 365 lbl.properties[2] = "test2" 366 lbl.properties[22] = "test22" 367 c1.add((rect, lbl)) 368 c2 = lib.new_cell("REF") 369 ref = gdspy.CellReference(c1, (0, 0)) 370 ref.properties[6] = "test6" 371 ref.properties[121] = "test_121" 372 c2.add(ref) 373 c3 = lib.new_cell("AREF") 374 aref = gdspy.CellArray(c1, 1, 2, (30, 40), (0, 0)) 375 aref.properties[4] = "test4" 376 aref.properties[123] = "test_123" 377 c3.add(aref) 378 c4 = lib.new_cell("FP") 379 fp = gdspy.FlexPath([(0, 0), (0, 1), (1, 1)], 0.01, gdsii_path=True) 380 fp.properties[2] = "test2" 381 fp.properties[125] = "test_125" 382 c4.add(fp) 383 c5 = lib.new_cell("RP") 384 rp = gdspy.RobustPath((0, 0), [0.01, 0.01], 0.5, gdsii_path=True).segment((1, 1)) 385 rp.properties[3] = "test3" 386 rp.properties[124] = "test_124" 387 c5.add(rp) 388 fname = str(tmpdir.join("test_properties.gds")) 389 lib.write_gds(fname) 390 lib1 = gdspy.GdsLibrary(infile=fname) 391 assert rect.properties == lib1.cells["POLY"].polygons[0].properties 392 assert lbl.properties == lib1.cells["POLY"].labels[0].properties 393 assert ref.properties == lib1.cells["REF"].references[0].properties 394 assert aref.properties == lib1.cells["AREF"].references[0].properties 395 assert fp.properties == lib1.cells["FP"].paths[0].properties 396 assert rp.properties == lib1.cells["RP"].paths[0].properties 397 assert rp.properties == lib1.cells["RP"].paths[1].properties 398 399 400def test_time_changes_gds_hash(tmpdir): 401 fn1 = str(tmpdir.join('nofreeze1.gds')) 402 fn2 = str(tmpdir.join('nofreeze2.gds')) 403 date1 = datetime.datetime(1988, 8, 28) 404 date2 = datetime.datetime(2020, 12, 25) 405 lib = gdspy.GdsLibrary(name='speedy') 406 lib.new_cell("empty") 407 lib.write_gds(fn1, timestamp=date1) 408 hash1 = hash_file(fn1) 409 lib.write_gds(fn2, timestamp=date2) 410 hash2 = hash_file(fn2) 411 412 assert hash1 != hash2 413 414 415def test_frozen_gds_has_constant_hash(tmpdir): 416 fn1 = str(tmpdir.join('freeze1.gds')) 417 fn2 = str(tmpdir.join('freeze2.gds')) 418 frozen_date = datetime.datetime(1988, 8, 28) 419 lib = gdspy.GdsLibrary(name='Elsa') 420 lib.new_cell("empty") 421 lib.write_gds(fn1, timestamp=frozen_date) 422 hash1 = hash_file(fn1) 423 lib.write_gds(fn2, timestamp=frozen_date) 424 hash2 = hash_file(fn2) 425 426 assert hash1 == hash2 427 428 429def test_frozen_gds_with_cell_has_constant_hash(tmpdir): 430 fn1 = str(tmpdir.join('freezec1.gds')) 431 fn2 = str(tmpdir.join('freezec2.gds')) 432 frozen_date = datetime.datetime(1988, 8, 28) 433 lib = gdspy.GdsLibrary(name='Elsa') 434 cell = gdspy.Cell(name='Anna') 435 cell.add(gdspy.Rectangle((0, 0), (100, 1000))) 436 lib.add(cell) 437 lib.write_gds(fn1, timestamp=frozen_date) 438 hash1 = hash_file(fn1) 439 lib.write_gds(fn2, timestamp=frozen_date) 440 hash2 = hash_file(fn2) 441 442 assert hash1 == hash2 443 444 445def test_frozen_gds_with_cell_array_has_constant_hash(tmpdir): 446 fn1 = str(tmpdir.join('freezea1.gds')) 447 fn2 = str(tmpdir.join('freezea2.gds')) 448 frozen_date = datetime.datetime(1988, 8, 28) 449 lib = gdspy.GdsLibrary(name='Elsa') 450 cell = gdspy.Cell(name='Anna') 451 cell.add(gdspy.Rectangle((0, 0), (100, 1000))) 452 cell2 = gdspy.Cell(name='Olaf') 453 cell2.add(gdspy.Rectangle((0, 0), (50, 100))) 454 455 cell_array = gdspy.CellArray(ref_cell=cell2, columns=5, rows=2, spacing=(60, 120), origin=(1000, 0)) 456 cell.add(cell_array) 457 lib.add(cell) 458 lib.write_gds(fn1, timestamp=frozen_date) 459 hash1 = hash_file(fn1) 460 lib.write_gds(fn2, timestamp=frozen_date) 461 hash2 = hash_file(fn2) 462 463 assert hash1 == hash2 464