Automatically disambiguate repeated pattern names.

Also check for >32 char names
This commit is contained in:
Jan Petykiewicz 2019-04-13 21:10:08 -07:00
parent 3815069136
commit 3094aa4043

View File

@ -9,6 +9,9 @@ import gdsii.elements
from typing import List, Any, Dict, Tuple from typing import List, Any, Dict, Tuple
import re import re
import numpy import numpy
import base64
import struct
import logging
from .utils import mangle_name, make_dose_table from .utils import mangle_name, make_dose_table
from .. import Pattern, SubPattern, GridRepetition, PatternError, Label, Shape from .. import Pattern, SubPattern, GridRepetition, PatternError, Label, Shape
@ -19,6 +22,9 @@ from ..utils import rotation_matrix_2d, get_bit, set_bit, vector2, is_scalar
__author__ = 'Jan Petykiewicz' __author__ = 'Jan Petykiewicz'
logger = logging.getLogger(__name__)
def write(patterns: Pattern or List[Pattern], def write(patterns: Pattern or List[Pattern],
filename: str, filename: str,
meters_per_unit: float, meters_per_unit: float,
@ -65,13 +71,11 @@ def write(patterns: Pattern or List[Pattern],
for pattern in patterns: for pattern in patterns:
patterns_by_id.update(pattern.referenced_patterns_by_id()) patterns_by_id.update(pattern.referenced_patterns_by_id())
_disambiguate_pattern_names(patterns_by_id.values())
# Now create a structure for each pattern, and add in any Boundary and SREF elements # Now create a structure for each pattern, and add in any Boundary and SREF elements
for pat in patterns_by_id.values(): for pat in patterns_by_id.values():
sanitized_name = re.compile('[^A-Za-z0-9_\?\$]').sub('_', pat.name) structure = gdsii.structure.Structure(name=pat.name)
encoded_name = sanitized_name.encode('ASCII')
if len(encoded_name) == 0:
raise PatternError('Zero-length name after sanitize+encode, originally "{}"'.format(pat.name))
structure = gdsii.structure.Structure(name=encoded_name)
lib.append(structure) lib.append(structure)
# Add a Boundary element for each shape # Add a Boundary element for each shape
@ -384,10 +388,7 @@ def _subpatterns_to_refs(subpatterns: List[SubPattern or GridRepetition]
# strans must be set for angle and mag to take effect # strans must be set for angle and mag to take effect
refs = [] refs = []
for subpat in subpatterns: for subpat in subpatterns:
sanitized_name = re.compile('[^A-Za-z0-9_\?\$]').sub('_', subpat.pattern.name) encoded_name = subpat.pattern.name
encoded_name = sanitized_name.encode('ASCII')
if len(encoded_name) == 0:
raise PatternError('Zero-length name after sanitize+encode, originally "{}"'.format(subpat.pattern.name))
if isinstance(subpat, GridRepetition): if isinstance(subpat, GridRepetition):
mirror_signs = (-1) ** numpy.array(subpat.mirrored) mirror_signs = (-1) ** numpy.array(subpat.mirrored)
@ -446,3 +447,29 @@ def _labels_to_texts(labels: List[Label]) -> List[gdsii.elements.Text]:
xy=xy, xy=xy,
string=label.string.encode('ASCII'))) string=label.string.encode('ASCII')))
return texts return texts
def _disambiguate_pattern_names(patterns):
used_names = []
for pat in patterns:
sanitized_name = re.compile('[^A-Za-z0-9_\?\$]').sub('_', pat.name)
i = 0
suffixed_name = sanitized_name
while suffixed_name in used_names:
suffix = base64.b64encode(struct.pack('>Q', i), b'$?').decode('ASCII')
suffixed_name = sanitized_name + '$' + suffix[:-1].lstrip('A')
i += 1
if suffixed_name != sanitized_name:
logger.warning('Pattern name "{}" appears multiple times; renaming to "{}"'.format(pat.name, suffixed_name))
encoded_name = sanitized_name.encode('ASCII')
if len(encoded_name) == 0:
raise PatternError('Zero-length name after sanitize+encode, originally "{}"'.format(pat.name))
if len(encoded_name) > 32:
raise PatternError('Pattern name "{}" length > 32 after encode, originally "{}"'.format(encoded_name, pat.name))
pat.name = encoded_name
used_names.append(suffixed_name)