From f39fe2c259b1900226ec164cf9148d9d71cf69c9 Mon Sep 17 00:00:00 2001 From: demis Date: Fri, 8 May 2020 22:27:56 -0700 Subject: [PATCH] plot_wafer(): shows alignment marks --- ASML_JobCreator/Plot.py | 126 +++++++++++++++++++++++++++------------- 1 file changed, 87 insertions(+), 39 deletions(-) diff --git a/ASML_JobCreator/Plot.py b/ASML_JobCreator/Plot.py index 59846b8..657468e 100644 --- a/ASML_JobCreator/Plot.py +++ b/ASML_JobCreator/Plot.py @@ -33,11 +33,16 @@ def __init__(self, parent=None): - def plot_wafer(self): + def plot_wafer(self, showwafer=True, showmarks=True): """ Plot the Wafer layout and distributed Images. Note that some plotting options, such as font size and axis positioning, are set in __globals.py + Parameters + ---------- + showwafer, showmarks : True | False, optional + Show the wafer outline marks + edge clearance (showware) and alignment marks (showmarks). Defaults to True. + Returns ------- fig, ax : Matplotlib Figure and Axis objects containing the schematic. Use these handles to manipulate the plot after generation. Matplotlib Patches are used to draw the shapes. @@ -47,7 +52,7 @@ def plot_wafer(self): import numpy as np fig, ax = plt.subplots(nrows=1, ncols=1) - + LegendEntries = [] ## Plot the wafer outline: # Arc angles: @@ -57,9 +62,11 @@ def plot_wafer(self): A = np.rad2deg( np.arcsin( (F/2) / (D/2) ) ) # arc angle corresponding to 1/2 of wafer flat else: A = 2 - # matplotlib.patches.Arc(xy, width, height, angle=0.0, theta1=0.0, theta2=360.0) : - wf = mplp.Arc( (0,0) , D, D, angle=-90, theta1=A, theta2=-A , color=Defaults.Plotting_WaferEdgeColor, hatch=Defaults.Plotting_BGHatch) - ax.add_patch( wf ) + + if showwafer: + # matplotlib.patches.Arc(xy, width, height, angle=0.0, theta1=0.0, theta2=360.0) : + wf = mplp.Arc( (0,0) , D, D, angle=-90, theta1=A, theta2=-A , color=Defaults.Plotting_WaferEdgeColor, hatch=Defaults.Plotting_BGHatch) + ax.add_patch( wf ) ## Plot the edge clearance @@ -70,8 +77,10 @@ def plot_wafer(self): Ac = np.rad2deg( np.arcsin( (Fc/2) / (Dc/2) ) ) # arc angle corresponding to 1/2 of wafer flat else: Ac = 2 - clearance = mplp.Arc( (0,0) , Dc, Dc, angle=-90, theta1=Ac, theta2=(-Ac) , color=Defaults.Plotting_WaferColor, hatch=Defaults.Plotting_BGHatch) - ax.add_patch( clearance ) + + if showwafer: + clearance = mplp.Arc( (0,0) , Dc, Dc, angle=-90, theta1=Ac, theta2=(-Ac) , color=Defaults.Plotting_WaferColor, hatch=Defaults.Plotting_BGHatch) + ax.add_patch( clearance ) ## Plot the Cell grid: @@ -127,13 +136,50 @@ def gen_grid(inc, maxval, shift=0): tick.label1.set_horizontalalignment('center') #end for(ytick) - ax.grid(True, which='minor', color=Defaults.Plotting_GridColor, linestyle=Defaults.Plotting_GridStyle) - ax.grid(False, which='major') + if showwafer: + ax.grid(True, which='minor', color=Defaults.Plotting_GridColor, linestyle=Defaults.Plotting_GridStyle) + ax.grid(False, which='major') + #end if(showwafer) + + + # Plot alignment marks + if self.parent.Alignment: + cmap = plt.get_cmap(Defaults.Plotting_MarkColorMap) # cycling colors + c=-1 # colormap index + AlImgs = [] + for i, Mrk in enumerate(self.parent.Alignment.MarkList): + if DEBUG(): print("plot_wafer:marks(): MrkImg #%i:\n"%i, Mrk.Image.ImageID, "c=%i"%c ) + Iwidth = Mrk.Image.sizeXY[0] + Iheight = Mrk.Image.sizeXY[1] + X = Mrk.waferXY[0] - Iwidth/2 + Y = Mrk.waferXY[1] - Iheight/2 + + Imgi = np.where( np.isin(AlImgs, Mrk.Image) )[0] + if len(Imgi)==0: + # Unlisted Mark Image + c = c+1 # cycle colormap + #end if(Mark added to legend) + + R = mplp.Rectangle( (X,Y), Iwidth, Iheight, + facecolor=Defaults.Plotting_MarkFace, + edgecolor=cmap(c), + label=Mrk.Image.ImageID, + alpha=Defaults.Plotting_MarkAlpha, + linewidth=Defaults.Plotting_MarkLineWidth ) + ax.add_patch( R ) + + if len(Imgi)==0: + # Unlisted Mark Image + AlImgs.append( Mrk.Image ) + LegendEntries.append( R ) # add once only + if DEBUG(): print("plot_wafer:marks(): ", "\nAdding Legend entry %i\n"%len(LegendEntries), "MrkImg: ", Mrk.Image.ImageID, "c=%i"%c ) + #end if(Mark added to legend) + #end for(Imagelist) + #end if(Alignment) # Plot the distributed images: - cmap = plt.get_cmap("tab20") # cycling colors - LegendEntries = [] + cmap = plt.get_cmap(Defaults.Plotting_ImageColorMap) # cycling colors for i, Img in enumerate(self.parent.ImageList): Iwidth = Img.sizeXY[0] Iheight = Img.sizeXY[1] @@ -151,6 +197,7 @@ def gen_grid(inc, maxval, shift=0): #end for(ImgDistr) #end for(Imagelist) + # Shrink current axis by 20% for legend to fit box = ax.get_position() if DEBUG(): print("ax:box=", box.x0, box.y0) @@ -166,7 +213,7 @@ def gen_grid(inc, maxval, shift=0): - def plot_reticles(self, scale=False): + def plot_reticles(self, scale=False, showwindow=True, showlens=True): """ Plot the Reticle layout(s). If multiple Reticle ID's are detected, multiple reticles will be plotted. Note that some plotting options, such as font size and axis positioning, are set in __globals.py @@ -175,6 +222,9 @@ def plot_reticles(self, scale=False): ---------- scale : True | False, optional If True, plot at Reticle scale (eg. 4x or 5x, as set in `Defaults.py :: LENS_REDUCTION`). Defaults to False, which plots at 1x wafer-scale. + + showwindow, showlens : True | False, optional + If True, show the rectangular reticle table window (showwindow) and circular lens (showlens) outlines. These dimensions are defined in Defaults.py. Both defualt to True. Returns ------- @@ -188,14 +238,9 @@ def plot_reticles(self, scale=False): else: Mag = 1.0 - # RETICLE_TABLE_SIZE, LENS_DIAMETER import matplotlib.pyplot as plt import matplotlib.patches as mplp # for plotting shapes - import numpy as np - - # TODO: - # - figure out number of ReticleID's, one axis per - # - loop thru images on each reticle + import numpy as np Rets,Imgs = self._get_ReticlesPerImage() figs, axs = [],[] @@ -205,25 +250,28 @@ def plot_reticles(self, scale=False): figs.append(fig) axs.append(ax) - ## Plot the Lens outline: - Lens = mplp.Circle( (0,0), Defaults.LENS_DIAMETER/2.0 * Mag, label="Lens Diameter", - facecolor=Defaults.Plotting_LensColor, - linewidth=Defaults.Plotting_BGOutlineWidth, - edgecolor=Defaults.Plotting_BGOutlineColor, - linestyle=Defaults.Plotting_BGOutlineStyle, - alpha = Defaults.Plotting_Alpha ) - ax.add_patch( Lens ) - - - ## Plot the Reticle Table outline: - RT = mplp.Rectangle( (-Defaults.RETICLE_TABLE_WINDOW[0]/2.0 * Mag, -Defaults.RETICLE_TABLE_WINDOW[1]/2.0 * Mag), Defaults.RETICLE_TABLE_WINDOW[0] * Mag, Defaults.RETICLE_TABLE_WINDOW[1] * Mag, - label="Reticle Table Window", - facecolor=Defaults.Plotting_ReticleTableColor, - linewidth=Defaults.Plotting_BGOutlineWidth, - edgecolor=Defaults.Plotting_BGOutlineColor, - linestyle=Defaults.Plotting_BGOutlineStyle, - alpha = Defaults.Plotting_Alpha ) - ax.add_patch( RT ) + if showlens: + ## Plot the Lens outline: + Lens = mplp.Circle( (0,0), Defaults.LENS_DIAMETER/2.0 * Mag, label="Lens Diameter", + facecolor=Defaults.Plotting_LensColor, + linewidth=Defaults.Plotting_BGOutlineWidth, + edgecolor=Defaults.Plotting_BGOutlineColor, + linestyle=Defaults.Plotting_BGOutlineStyle, + alpha = Defaults.Plotting_Alpha ) + ax.add_patch( Lens ) + #end if(showlens) + + if showwindow: + ## Plot the Reticle Table outline: + RT = mplp.Rectangle( (-Defaults.RETICLE_TABLE_WINDOW[0]/2.0 * Mag, -Defaults.RETICLE_TABLE_WINDOW[1]/2.0 * Mag), Defaults.RETICLE_TABLE_WINDOW[0] * Mag, Defaults.RETICLE_TABLE_WINDOW[1] * Mag, + label="Reticle Table Window", + facecolor=Defaults.Plotting_ReticleTableColor, + linewidth=Defaults.Plotting_BGOutlineWidth, + edgecolor=Defaults.Plotting_BGOutlineColor, + linestyle=Defaults.Plotting_BGOutlineStyle, + alpha = Defaults.Plotting_Alpha ) + ax.add_patch( RT ) + #end if(showwindow) ax.set_xlabel("%ix Scale, mm" % (Mag), fontsize=PlotLabelFontSize) ax.set_ylabel("mm", fontsize=PlotLabelFontSize) @@ -232,7 +280,7 @@ def plot_reticles(self, scale=False): # Plot the defined images: - cmap = plt.get_cmap("tab20") # cycling colors + cmap = plt.get_cmap(Defaults.Plotting_ImageColorMap) # cycling colors LegendEntries = [] for i, Img in enumerate(Imgs[r]): #if DEBUG(): print("_get_ReticlesPerImage(): Imgs:\n", Imgs, "\nImg #%i\n"%i, Img) @@ -241,7 +289,7 @@ def plot_reticles(self, scale=False): X = Img.shiftXY[0] * Mag - Iwidth/2 Y = Img.shiftXY[1] * Mag - Iheight/2 - R = mplp.Rectangle( (X,Y), Iwidth, Iheight, color=cmap(i), label=Img.ImageID, alpha=1.0, linewidth=Defaults.Plotting_LineWidth ) + R = mplp.Rectangle( (X,Y), Iwidth, Iheight, color=cmap(i), label=Img.ImageID, alpha=Defaults.Plotting_Alpha, linewidth=Defaults.Plotting_LineWidth ) ax.add_patch( R ) LegendEntries.append( R ) # add once only #end for(Imagelist)