Example notebook for import-export operations with pyMOE

In the following is exemplified how to:

  • Transform a (multi-layer) .gds file into a grayscale image file (allowed extensions as accepted by opencv, e.g. .tiff, .png, .jpg …)

  • Transform a grayscale image file into a dithered image file

  • Transform a grayscale image file (.tiff, .png, …) into a gds file (with squared pixels)

  • Extra: Merge all pixels (or shapes) in a layer inside a .gds file

[1]:
# Notebook display options, change as your preference/system
%matplotlib inline
%config InlineBackend.print_figure_kwargs={'facecolor' : "w",'bbox_inches':None}

import matplotlib as mpl
mpl.rcParams['figure.dpi'] = 120
[2]:
import sys
sys.path.insert(0,'..')
sys.path.insert(0,'../..')

from matplotlib import pyplot as plt
import numpy as np

from scipy.constants import micro, nano, milli

import pyMOE as moe

Export a created mask using gdsconverter

[3]:
###Here we create a gds/dxf file using the generate and the gdsconverter modules

####generate a fresnel phase mask and save it into gds
N_pixels = 101 # nr of pixels
focal_distance = 5000*micro # focal distance in um

refractive_index_633 = 1.630115
wavelength = 633*nano

mask_width = 500*micro #x-size in um
mask_height = 500*micro #y-size in um
radius = 250*micro
n = 10  # number of gray levels


##############
###Fresnel mask with a truncated circular aperture

# Create empty mask
aperture = moe.generate.create_empty_aperture(0,mask_width, N_pixels, 0, mask_height, N_pixels)

center = (250*micro, 250*micro)

# and truncate around radius
mask = moe.generate.fresnel_phase(aperture, focal_distance, wavelength, radius=radius, center = center)
moe.plotting.plot_aperture(mask )

../_images/notebooks_Import_export_5_0.png

Convert phase mask to height map

[4]:

# Unwraps the phase and plots the aperture mask.phase_unwrap() # Converts the phase to height mask.phase2height(wavelength, refractive_index_633) # define the maximum height of the mask height_2pi = moe.sag.phase2height(2*np.pi, wavelength, refractive_index_633) print(f"Maximum height of the mask: {height_2pi/micro} um") mask.modulos(height_2pi, normalize_to_max=True) print("Discretizing mask to number of gray levels: ", n) mask.discretize(n) moe.plotting.plot_aperture(mask)
Maximum height of the mask: 1.0045785293160772 um
Discretizing mask to number of gray levels:  10
../_images/notebooks_Import_export_7_1.png

Export mask to gds and dxf files

.dxf files are recorded with layer names with the naming convention LevelXXX_0.000 where XXX is the layer number and 0.000 is the respetive expected depth for that layer in microns.

[5]:
gdsname = 'examplemask.gds' # name of dxf file+
dxfname = 'examplemask.dxf' # name of dxf file+


#initialize the GDS converter class
gdsmask = moe.GDSMask(mask)

# Create layout and merge polygons together if merge=True
gdsmask.create_layout(mode="raster", merge=True)

gdsmask.write_gds(gdsname)
gdsmask.write_gds(dxfname)
<class 'pyMOE.aperture.Aperture'>
Mask has 10201 number of points distributed in 10 layers
Creating individual pixel polygons
Progress: [####################] 100.0%
[Create Polygons]
Elapsed: 0:00:00.146855
Merging polygons inside layers
Progress: [####################] 100.0%
[Merging polygons]
Elapsed: 0:00:00.044804
[Total time converting to GDS]
Elapsed: 0:00:00.192157
Saving file to examplemask.gds
Saved examplemask.gds
[Saving GDS file]
Elapsed: 0:00:00.012943
Saving file to examplemask.dxf
Saved examplemask.dxf
[Saving GDS file]
Elapsed: 0:00:00.202611

Convert height map dxf file to grayvalue from calibration lookup table

[6]:
gscalibration = moe.GrayscaleCalibration()

# load calibration file
gscalibration.load_calibration("calibration.csv")


# Load mask file
gscalibration.load_gdsfile(dxfname)

# Extracts the height levels from the layer names
gscalibration.get_levels_from_layer_names()
gscalibration.plot_calibration()



# Adjust the height offset gray values
height_offset = -0.2
gscalibration.adjust_grayvalues(height_offset)
gscalibration.plot_calibration()

outfile = dxfname.replace(".dxf", "_grayscale.dxf")

gscalibration.calibrate_layer_names()


# Add fiducials and alignment marks to the mask

corner_length = 500#*micro
corner_width = 100#*micro

field_width = 10000 #*micro
field_height = 10000 #*micro

# Layer number of the fiducials and label names
layer = "layer127"
gscalibration.add_corners(field_width, field_height, corner_length, corner_width, layer)

# Text to use as label
label = "label 01"
gscalibration.add_label(label, position=(-4000, -4000), mag=1000, layer=layer)

gscalibration.save_calibrated_gdsfile(outfile)



Grayscale calibration range is 1.789 um
Loaded mask with 10 levels
Mask range is 0.904 um
[Saving calibrated GDS file]
Elapsed: 0:00:00.177721
Saved examplemask_grayscale.dxf
../_images/notebooks_Import_export_11_1.png
../_images/notebooks_Import_export_11_2.png

Transform layered .gds file into a grayscale image

[7]:
##Start with an existing file
#Might take a while
infile = gdsname
outfile = gdsname.replace(".gds", ".bmp")

n=10

moe.importing.gds2img(infile, outfile, int(n),  rescaled=0, verbose=True)

Layers: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
Datatypes: [0]
xmax is 502.5
ymax is 502.5
xmin is -2.5
ymin is -2.5
Imported file examplemask.gds and exported into examplemask.bmp with size 502 x 502 pixels.
../_images/notebooks_Import_export_13_1.png

Transform grayscale image into (binary) dithered image

[8]:
##Make a dithered mask from the tiff obtained from the gds
import pyMOE.dither as dith

inputimg = outfile
ditherimg = inputimg.replace(".bmp", "_dither.tiff")


#make dithering using the floyd steinberg algorithm now
moe.dither.dither_img(inputimg, ditherimg, plotting=True)
../_images/notebooks_Import_export_15_0.png

Transform binary image file into single layered .gds file

Transform a dithered image into a gds file, using a fractioning of the image

[9]:
infilxe = ditherimg
outfilxe = infilxe.replace(".tiff", ".gds")


pixelx = 1 #um
pixely = 1 #um
cellname = "TOP" #name of the gds cell
graycolor = 0 #black pixels
frac = 250 #size of frac pixels in the image

moe.export.grayim2gds_writer_frac(infilxe, outfilxe, pixelx, pixely, cellname, graycolor, frac, verbose=False)
Sucessfully imported img!
505
505
Exported the image file examplemask_dither.tiff into examplemask_dither.gds

Transform a dithered image into a .gds file, using the whole image

[10]:
infilxe = ditherimg
outfilxe = infilxe.replace(".tiff", "_2.gds")
cellname = "TOP" #name of the gds cell
graycolor = 0 #black pixels
pixelx = 1 #um
pixely = 1 #um

moe.export.grayim2gds_writer(infilxe, outfilxe, pixelx, pixely,cellname, graycolor, verbose=False)
Sucessfully imported img!
505
505
Exported the image file examplemask_dither.tiff into examplemask_dither_2.gds
[11]:
###Using instances to create the dithered gds file (faster and less heavy files)

#(Takes less than 1 min)
infilxe = ditherimg
outfilxe = infilxe.replace(".tiff", "_instances.gds")

cellname = "tops" #name of the gds cell
graycolor = 0 #black pixels
pixelx = 1 #um
pixely = 1 #um

moe.export.grayim2gds_writer_klops(infilxe, outfilxe, pixelx, pixely,cellname, graycolor, verbose=False)
Sucessfully imported img!
505
505
Exported the image file examplemask_dither.tiff into image.gds
Starting making instances
Done

Extra: Merging shapes in the single layer .gds file

The “pixelated” gds files (without instances) are typically large. The file size can be reduced by merging the pixels - the merge operation can be done using the gds_klops module

[12]:
import pyMOE.gds_klops as gdsops

inputfile = outfilxe
outputfile = inputfile.replace(".gds", "_merged.gds")
cellname = "TOP" #name of the gds cell
layer = int(0)
datatype = int(0)

moe.gdsops.merge_layer(inputfile,cellname, layer, datatype ,outputfile )
Merged layers in examplemask_dither_instances_merged.gds
[13]:
#uses the instatiated gds
infile = ditherimg
outfilxe = infile.replace(".tiff", "_instances.gds")
outputfile = outfilxe.replace("_instances.gds", "_instances_merged.gds")
cellname = "TOP" #name of the gds cell
layer = int(0)
datatype = int(0)

moe.gdsops.merge_layer(outfilxe,cellname, layer, datatype ,outputfile )
Merged layers in examplemask_dither_instances_merged.gds