def IntegerParameter(restriction=None, preprocess=None, **kwargs): from .variables import INTEGER if 'default' not in kwargs: kwargs['default'] = 0 R = INTEGER & restriction # P = preprocess # return RestrictedParameter(restriction=R, preprocess=P, **kwargs) return RestrictedParameter(restriction=R, **kwargs)
class __OutputBasic__(ParameterInitializer): """ """ file_name = StringParameter() output_filter = RestrictedParameter( default=Filter(), # restriction=RestrictType(Filter), doc="filter class which is applied to all output items") def __init__(self, file_name=None, **kwargs): super().__init__(file_name=file_name, **kwargs) self.__init_collector__() self.__collect_method_dict__ = {} def __init_collector__(self): self.collector = {} def write(self, item): raise NotImplementedError('Must provide implementation in subclass.') def collect(self, item, **kwargs): self.do_collect(item, **kwargs) return self def do_collect(self, item, **kwargs): """ Collects each element using the Visitor Design Pattern. """ import inspect items = self.output_filter(item) if len(items) == 1: item = items[0] else: item = items T = type(item) if inspect.isclass(T): collect_method = self.__collect_method_dict__.get(T, None) if collect_method is None: for cls in inspect.getmro(T): collect_method_name = 'collect_{}'.format(cls.__name__) if hasattr(self, collect_method_name): collect_method = getattr(self, collect_method_name) self.__collect_method_dict__[T] = collect_method break if collect_method is None: LOG.warn("No collect method found for object of type %s" % T) else: collect_method(item, **kwargs) return self
class Edge(Path): """ Edge elements are object that represents the edge of a polygonal shape. """ line_shape = ShapeParameter(default=[]) edge_type = RestrictedParameter(default=constants.EDGE_TYPE_NORMAL, restriction=RestrictValueList( constants.EDGE_TYPES)) internal_pid = StringParameter( default='no_pid', doc='A unique polygon ID to which the edge connects.') external_pid = StringParameter( default='no_pid', doc='A unique polygon ID to which the edge connects.') def __init__(self, shape, layer, transformation=None, **kwargs): super().__init__(shape=shape, layer=layer, transformation=transformation, **kwargs) def __repr__(self): if self is None: return 'Edge is None!' layer = RDD.GDSII.IMPORT_LAYER_MAP[self.layer] class_string = "[SPiRA: Edge] (center {}, width {}, process {}, purpose {})" return class_string.format(self.center, self.width, self.layer.process.symbol, self.layer.purpose.symbol) def __str__(self): return self.__repr__() def __hash__(self): return hash(self.__repr__()) def short_string(self): # return "Edge [{}, {}, {}]".format(self.center, self.layer.process.symbol, self.layer.purpose.symbol) # NOTE: We want to ignore the purpose for CIRCUIT_METAL ot DEVICE_METAL net connections. return "Edge [{}, {}]".format(self.center, self.layer.process.symbol) def flat_copy(self, level=-1): """ Flatten a copy of the polygon. """ S = Edge(shape=self.shape, layer=self.layer, transformation=self.transformation) S.expand_transform() return S
class Path(__ShapeElement__): """ """ width = NumberParameter( default=1, doc='The distance the edge extends from the shape.') path_type = RestrictedParameter(default=constants.PATH_TYPE_NORMAL, restriction=RestrictValueList( constants.PATH_TYPES)) def __init__(self, shape, layer, transformation=None, **kwargs): super().__init__(shape=shape, layer=layer, transformation=transformation, **kwargs) def __repr__(self): if self is None: return 'Path is None!' layer = RDD.GDSII.IMPORT_LAYER_MAP[self.layer] class_string = "[SPiRA: Path \'{}\'] (center {}, width {}, extend {}, process {}, purpose {})" return class_string.format(self.alias, self.center, self.shape.width, self.extend, self.layer.process.symbol, self.layer.purpose.symbol) def __str__(self): return self.__repr__() def __hash__(self): return hash(self.__repr__()) def short_string(self): return "Path [{}, {}, {}]".format(self.center, self.layer.process.symbol, self.layer.purpose.symbol) def flat_copy(self, level=-1): """ Flatten a copy of the polygon. """ S = Path(shape=self.shape, layer=self.layer, transformation=self.transformation) S.expand_transform() return S
def ListParameter(restriction=None, **kwargs): from .variables import LIST if 'default' not in kwargs: kwargs['default'] = [] R = LIST & restriction return RestrictedParameter(restriction=R, **kwargs)
def TupleParameter(restriction=None, **kwargs): from .variables import TUPLE if 'default' not in kwargs: kwargs['default'] = [] return RestrictedParameter(restriction=TUPLE, **kwargs)
def StringParameter(restriction=None, **kwargs): from .variables import STRING if 'default' not in kwargs: kwargs['default'] = '' R = STRING & restriction return RestrictedParameter(restriction=R, **kwargs)
def BoolParameter(restriction=None, **kwargs): from .variables import BOOL if 'default' not in kwargs: kwargs['default'] = False return RestrictedParameter(restriction=BOOL, **kwargs)
def ProcessParameter(local_name=None, restriction=None, **kwargs): R = RestrictType(ProcessLayer) & restriction return RestrictedParameter(local_name, restriction=R, **kwargs)
def FloatParameter(restriction=None, **kwargs): from .variables import FLOAT if 'default' not in kwargs: kwargs['default'] = 0.0 return RestrictedParameter(restriction=FLOAT, **kwargs)
def GraphParameter(restriction=None, **kwargs): from .variables import GRAPH if 'default' not in kwargs: kwargs['default'] = nx.Graph() R = GRAPH & restriction return RestrictedParameter(restriction=R, **kwargs)
def LayerParameter(local_name=None, restriction=None, **kwargs): R = RestrictType(__Layer__) & restriction return RestrictedParameter(local_name, restriction=R, **kwargs)
def DictParameter(local_name=None, restriction=None, **kwargs): from .variables import DICTIONARY if 'default' not in kwargs: kwargs['default'] = {} R = DICTIONARY & restriction return RestrictedParameter(local_name, restriction=R, **kwargs)
def VModelProcessFlowParameter(local_name=None, restriction=None, **kwargs): R = RestrictType(VModelProcessFlow) & restriction return RestrictedParameter(local_name, restriction=R, **kwargs)
def NetParameter(local_name=None, restriction=None, **kwargs): R = RestrictType(Net) & restriction return RestrictedParameter(local_name, restriction=R, **kwargs)
def StippleParameter(local_name=None, restriction=None, preprocess=None,**kwargs): R = RestrictType(StipplePattern) & restriction P = ProcessorStipplePattern() + preprocess return RestrictedParameter(local_name, restriction=R, preprocess=P, **kwargs)
def CoordParameter(local_name=None, restriction=None, preprocess=None, **kwargs): if 'default' not in kwargs: kwargs['default'] = Coord(0,0) R = RESTRICT_COORD & restriction P = ProcessorTypeCast(Coord) + preprocess return RestrictedParameter(local_name, restriction=R, preprocess=P, **kwargs)
def NumpyArrayParameter(restriction=None, **kwargs): from .variables import NUMPY_ARRAY if 'default' not in kwargs: kwargs['default'] = np.array([]) return RestrictedParameter(restriction=NUMPY_ARRAY, **kwargs)
def NumberParameter(restriction=None, **kwargs): if 'default' not in kwargs: kwargs['default'] = 0 R = NUMBER & restriction return RestrictedParameter(restriction=R, **kwargs)
def TimeParameter(local_name=None, restriction=None, **kwargs): import time R = NUMBER & restriction if not 'default' in kwargs: kwargs['default'] = time.time() return RestrictedParameter(local_name, restriction=R, **kwargs)
def ComplexParameter(restriction=None, **kwargs): from .variables import COMPLEX if 'default' not in kwargs: kwargs['default'] = 0 return RestrictedParameter(restriction=COMPLEX, **kwargs)
class OutputBasic(__OutputBasic__): """ """ layer_map = RestrictedParameter(default=RDD.GDSII.EXPORT_LAYER_MAP) def __init__(self, file_name=None, **kwargs): super().__init__(file_name=file_name, **kwargs) self.library = None self._current_cell = None self.__collect_method_dict__ = {} def set_current_cell(self, item): self._current_cell = item def do_collect(self, item, **kwargs): from spira.yevon.gdsii.library import Library if isinstance(item, Library): self.library = item self.grids_per_unit = self.library.grids_per_unit self.unit = self.library.unit if self.library == None: self.library = get_current_library() super().do_collect(item, **kwargs) return self def collect_list(self, item, **kwargs): for i in item: self.collect(i, **kwargs) return self def collect_Library(self, library, usecache=False, **kwargs): referenced_cells = self.library.referenced_cells() for rc in referenced_cells: c = gdspy.Cell(rc.name, exclude_from_current=True) self.collector.update({rc: c}) self.collect(referenced_cells, **kwargs) return self def collect_CellList(self, item, **kwargs): for s in item: self.collect(s, **kwargs) return self def collect_Cell(self, item, **kwargs): self.set_current_cell(item) self.collect(item.elements, **kwargs) return self def collect_ElementList(self, item, additional_transform=None, **kwargs): for s in item: self.collect(s, additional_transform=additional_transform, **kwargs) return self def collect_Group(self, item, additional_transform=None, **kwargs): T = item.transformation + additional_transform self.collect(item.elements, additional_transform=T, **kwargs) return self def collect_SRef(self, item, additional_transform=None): T = item.transformation + Translation(item.midpoint) origin = Coord(0, 0).transform(T).to_numpy_array() rotation = 0 reflection = False magnification = 1.0 if isinstance(T, CompoundTransform): for t in T.__subtransforms__: if isinstance(t, GenericTransform): rotation = t.rotation reflection = t.reflection magnification = t.magnification else: rotation = T.rotation reflection = T.reflection magnification = T.magnification ref_cell = self.collector[item.reference] self.collect_reference(ref_cell, origin, rotation, reflection, magnification) return self def collect_Polygon(self, item, additional_transform=None, **kwargs): # def collect___ShapeElement__(self, item, additional_transform=None, **kwargs): T = item.transformation + additional_transform shape = item.shape.transform_copy(T) shape.snap_to_grid(self.grids_per_unit) coordinates = shape if len(shape) < 3: LOG.warning("Polygon cannot have less than 4 points.") return self if not (coordinates[0] == coordinates[-1]): coordinates.append(coordinates[0]) self.collect_polygon(points=coordinates.points, layer=item.layer) return self def collect_Label(self, item, additional_transform=None): T = item.transformation + additional_transform item.position = T.apply_to_coord(item.position) item.orientation = T.apply_to_angle(item.orientation) position = item.position.to_numpy_array() self.collect_label(text=item.text, position=position, rotation=item.orientation, layer=item.layer) return self def map_layer(self, layer): from spira.yevon.process.gdsii_layer import Layer L = self.layer_map.get(layer, None) if isinstance(L, Layer): return L elif L is None: return L else: return Layer(number=L)
def PurposeLayerParameter(local_name=None, restriction=None, **kwargs): R = RestrictType(PurposeLayer) & restriction return RestrictedParameter(local_name, restrictions=R, **kwargs)