@ -8,11 +8,14 @@ import gdsii.elements
from typing import List , Any , Dict , Tuple
from typing import List , Any , Dict , Tuple
import re
import re
import io
import copy
import copy
import numpy
import numpy
import base64
import base64
import struct
import struct
import logging
import logging
import pathlib
import gzip
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
@ -35,7 +38,7 @@ path_cap_map = {0: Path.Cap.Flush,
def write ( patterns : Pattern or List [ Pattern ] ,
def write ( patterns : Pattern or List [ Pattern ] ,
filename: str ,
stream: io . BufferedIOBase ,
meters_per_unit : float ,
meters_per_unit : float ,
logical_units_per_unit : float = 1 ,
logical_units_per_unit : float = 1 ,
library_name : str = ' masque-gdsii-write ' ,
library_name : str = ' masque-gdsii-write ' ,
@ -58,8 +61,8 @@ def write(patterns: Pattern or List[Pattern],
If you want pattern polygonized with non - default arguments , just call pattern . polygonize ( )
If you want pattern polygonized with non - default arguments , just call pattern . polygonize ( )
prior to calling this function .
prior to calling this function .
: param patterns : A Pattern or list of patterns to write to file . Modified by this function .
: param patterns : A Pattern or list of patterns to write to file .
: param file name : Filename to write to .
: param file : Filename or stream object to write to .
: param meters_per_unit : Written into the GDSII file , meters per ( database ) length unit .
: param meters_per_unit : Written into the GDSII file , meters per ( database ) length unit .
All distances are assumed to be an integer multiple of this unit , and are stored as such .
All distances are assumed to be an integer multiple of this unit , and are stored as such .
: param logical_units_per_unit : Written into the GDSII file . Allows the GDSII to specify a
: param logical_units_per_unit : Written into the GDSII file . Allows the GDSII to specify a
@ -99,50 +102,29 @@ def write(patterns: Pattern or List[Pattern],
structure + = _labels_to_texts ( pat . labels )
structure + = _labels_to_texts ( pat . labels )
structure + = _subpatterns_to_refs ( pat . subpatterns )
structure + = _subpatterns_to_refs ( pat . subpatterns )
with open ( filename , mode = ' wb ' ) as stream :
lib . save ( stream )
lib . save ( stream )
return
def write_dose2dtype ( patterns : Pattern or List [ Pattern ] ,
def writefile ( patterns : List [ Pattern ] or Pattern ,
filename : str ,
filename : str or pathlib . Path ,
meters_per_unit : float ,
* args ,
* args ,
* * kwargs ,
* * kwargs ,
) :
) - > List [ float ] :
"""
"""
Write a Pattern or list of patterns to a GDSII file , by first calling
Wrapper for gdsii . write ( ) that takes a filename or path instead of a stream .
. polygonize ( ) to change the shapes into polygons , and then writing patterns
as GDSII structures , polygons as boundary elements , and subpatterns as structure
references ( sref ) .
For each shape ,
Will automatically compress the file if it has a . gz suffix .
layer is chosen to be equal to shape . layer if it is an int ,
or shape . layer [ 0 ] if it is a tuple
datatype is chosen arbitrarily , based on calcualted dose for each shape .
Shapes with equal calcualted dose will have the same datatype .
A list of doses is retured , providing a mapping between datatype
( list index ) and dose ( list entry ) .
Note that this function modifies the Pattern ( s ) .
It is often a good idea to run pattern . subpatternize ( ) prior to calling this function ,
especially if calling . polygonize ( ) will result in very many vertices .
If you want pattern polygonized with non - default arguments , just call pattern . polygonize ( )
prior to calling this function .
: param patterns : A Pattern or list of patterns to write to file . Modified by this function .
: param filename : Filename to write to .
: param meters_per_unit : Written into the GDSII file , meters per ( database ) length unit .
All distances are assumed to be an integer multiple of this unit , and are stored as such .
: param args : passed to masque . file . gdsii . write ( ) .
: param kwargs : passed to masque . file . gdsii . write ( ) .
: returns : A list of doses , providing a mapping between datatype ( int , list index )
and dose ( float , list entry ) .
"""
"""
patterns , dose_vals = dose2dtype ( patterns )
path = pathlib . Path ( filename )
write ( patterns , filename , meters_per_unit , * args , * * kwargs )
if path . suffix == ' gz ' :
return dose_vals
open_func = gzip . open
else :
open_func = open
with open_func ( path , mode = ' wb ' ) as stream :
results = write ( patterns , stream , * args , * * kwargs )
return results
def dose2dtype ( patterns : Pattern or List [ Pattern ] ,
def dose2dtype ( patterns : Pattern or List [ Pattern ] ,
@ -219,14 +201,27 @@ def dose2dtype(patterns: Pattern or List[Pattern],
return patterns , list ( dose_vals )
return patterns , list ( dose_vals )
def read_dtype2dose ( filename : str ) - > ( List [ Pattern ] , Dict [ str , Any ] ) :
def readfile ( filename : str or pathlib . Path ,
* args ,
* * kwargs ,
) - > ( Dict [ str , Pattern ] , Dict [ str , Any ] ) :
"""
"""
Alias for read ( filename , use_dtype_as_dose = True )
Wrapper for gdsii . read ( ) that takes a filename or path instead of a stream .
Tries to autodetermine file type based on suffixes
"""
"""
return read ( filename , use_dtype_as_dose = True )
path = pathlib . Path ( filename )
if path . suffix == ' gz ' :
open_func = gzip . open
else :
open_func = open
with open_func ( path , mode = ' rb ' ) as stream :
results = read ( stream , * args , * * kwargs )
return results
def read ( filename : str ,
def read ( stream: io . BufferedIOBase ,
use_dtype_as_dose : bool = False ,
use_dtype_as_dose : bool = False ,
clean_vertices : bool = True ,
clean_vertices : bool = True ,
) - > ( Dict [ str , Pattern ] , Dict [ str , Any ] ) :
) - > ( Dict [ str , Pattern ] , Dict [ str , Any ] ) :
@ -251,8 +246,7 @@ def read(filename: str,
: return : Tuple : ( Dict of pattern_name : Patterns generated from GDSII structures , Dict of GDSII library info )
: return : Tuple : ( Dict of pattern_name : Patterns generated from GDSII structures , Dict of GDSII library info )
"""
"""
with open ( filename , mode = ' rb ' ) as stream :
lib = gdsii . library . Library . load ( stream )
lib = gdsii . library . Library . load ( stream )
library_info = { ' name ' : lib . name . decode ( ' ASCII ' ) ,
library_info = { ' name ' : lib . name . decode ( ' ASCII ' ) ,
' meters_per_unit ' : lib . physical_unit ,
' meters_per_unit ' : lib . physical_unit ,
@ -532,3 +526,4 @@ def _disambiguate_pattern_names(patterns):
pat . name = encoded_name
pat . name = encoded_name
used_names . append ( suffixed_name )
used_names . append ( suffixed_name )