class Funnel(i3.PCell): """A generic Funnel to connect elements. It is defined by a boundary which are defined by points """ # 1. First we define our 2 Channel Templates with different Width's. channel_1_template = microfluidics.ShortChannelTemplate() channel_2_template = microfluidics.ShortChannelTemplate() # 2. Then we use the LinearWindowChannelTransition class to create a transition between Channels. #####################3 ################### channel_template = microfluidics.ChannelTemplateProperty( default=microfluidics.ShortChannelTemplate(), doc="Channel template of the tee") _name_prefix = "Funnel" # a prefix added to the unique funnel_length = i3.NumberProperty(default=100.0, doc="length of funnel") initial_width = i3.NumberProperty(default=200.0, doc="initial with of funnel") final_width = i3.NumberProperty(default=100.0, doc="final width of funnel") class Layout(i3.LayoutView): def _generate_instances(self, insts): channel_1_template = self.cell.channel_1_template.Layout( channel_width=self.cell.initial_width) channel_2_template = self.cell.channel_2_template.Layout( channel_width=self.cell.final_width) funnel = microfluidics.LinearWindowChannelTransition( start_trace_template=self.cell.channel_1_template, end_trace_template=self.cell.channel_2_template) funnel_layout = funnel.Layout( start_position=(0.0, 0.0), end_position=(self.cell.funnel_length, 0.0)) insts += i3.SRef(reference=funnel_layout, name='funnel', position=(0, 0)) return insts def _generate_ports(self, ports): #port1 ports += microfluidics.FluidicPort( name='in', position=(0, 0), direction=i3.PORT_DIRECTION.IN, angle_deg=180, trace_template=self.cell.channel_template) #port2 ports += microfluidics.FluidicPort( name='out', position=(self.funnel_length, 0), direction=i3.PORT_DIRECTION.OUT, angle_deg=0, trace_template=self.cell.channel_template) return ports
class TeeBoolean(i3.PCell): """A generic Tee to connect elements. It is defined by a boundary which are defined by points """ channel_template = microfluidics.ChannelTemplateProperty( default=microfluidics.ShortChannelTemplate(), doc="Channel template of the tee") _name_prefix = "Tee" # a prefix added to the unique identifier class Layout(i3.LayoutView): tee_length = i3.NumberProperty(default=10.0, doc="length of each tee branch") def _generate_instances(self, elems): # insts): rectangle = i3.RoundedRectangle(layer=i3.TECH.PPLAYER.CH2.TRENCH, center=(0.0, 0.0), box_size=(self.tee_length, 2 * self.tee_length), radius=1.0) rectangle2 = i3.RoundedRectangle(layer=i3.TECH.PPLAYER.CH2.TRENCH, center=(0.5 * self.tee_length, 0.0), box_size=(self.tee_length, self.tee_length), radius=1.0) #boolean operation add main trap and 1st rectangle b_add = rectangle | rectangle2 s = i3.Structure(elements=b_add) elems += i3.SRef(s) return elems #insts def _generate_ports(self, ports): #port1 ports += microfluidics.FluidicPort( name='in1', position=(0, -self.tee_length), direction=i3.PORT_DIRECTION.IN, angle_deg=270, trace_template=self.cell.channel_template) #port2 ports += microfluidics.FluidicPort( name='in2', position=(0, self.tee_length), direction=i3.PORT_DIRECTION.IN, angle_deg=90, trace_template=self.cell.channel_template) #port3 ports += microfluidics.FluidicPort( name='out1', position=(self.tee_length, 0.0), direction=i3.PORT_DIRECTION.IN, angle_deg=0, trace_template=self.cell.channel_template) return ports
class TeeSimple(i3.PCell): """ Provide a description of this PCell """ channel_template = microfluidics.ChannelTemplateProperty( default=microfluidics.ShortChannelTemplate(), doc="Channel template of the tee") _name_prefix = "Tee" # a prefix added to the unique identifier class Layout(i3.LayoutView): tee_length = i3.NumberProperty(default=300.0, doc="length of each tee branch") def _generate_instances(self, insts): channel1 = microfluidics.Channel( trace_template=self.cell.channel_template) channel1_lo = channel1.Layout( shape=[(0, -self.tee_length), (0, self.tee_length)]) insts += i3.SRef(channel1_lo, position=(0, 0)) channel2 = microfluidics.Channel( trace_template=self.cell.channel_template) channel2_lo = channel2.Layout(shape=[(0, 0), (-self.tee_length, 0)]) insts += i3.SRef(channel2_lo, position=(self.tee_length, 0)) return insts def _generate_ports(self, ports): #port1 ports += microfluidics.FluidicPort( name='in1', position=(0, -self.tee_length), direction=i3.PORT_DIRECTION.IN, angle_deg=270, trace_template=self.cell.channel_template) #port2 ports += microfluidics.FluidicPort( name='in2', position=(0, self.tee_length), direction=i3.PORT_DIRECTION.IN, angle_deg=90, trace_template=self.cell.channel_template) #port3 ports += microfluidics.FluidicPort( name='out1', position=(self.tee_length, 0.0), direction=i3.PORT_DIRECTION.OUT, angle_deg=0, trace_template=self.cell.channel_template) return ports
class JoinedObstacles(i3.PCell): #(Structure): channel_template = microfluidics.ChannelTemplateProperty( default=microfluidics.ShortChannelTemplate(), doc="Channel template for ports") mysingleObstacle = i3.ChildCellProperty( doc='the single Obstacle child cell, which will be clonned many times', default=Obstacle_BooleanBoundary()) wholeTrapX = i3.PositiveNumberProperty( default=500.0, doc="total X distance length of traps") wholeTrapY = i3.PositiveNumberProperty( default=500.0, doc="total Y distance length of traps") cInp = i3.Coord2Property(default=0.0, doc="") class Layout(i3.LayoutView): def _generate_instances(self, insts): x_inc = (self.mysingleObstacle.gap_btw_barriers + self.mysingleObstacle.obstacle_trap_length) * 2 y_inc = self.mysingleObstacle.channel_trap_width * 1.5 cycles_x = int(self.wholeTrapX / ((self.mysingleObstacle.gap_btw_barriers + self.mysingleObstacle.obstacle_trap_length) * 2)) cycles_y = int(self.wholeTrapY / (y_inc)) insts += i3.ARef(reference=self.mysingleObstacle, origin=(0, 0.0 * self.cell.wholeTrapY), period=(x_inc, y_inc), n_o_periods=(cycles_x, cycles_y)) print 'insts', insts return insts def _generate_ports(self, ports): #port1 ports += microfluidics.FluidicPort( name='in', position=(0, self.wholeTrapY * 0.5), #position = (0, 'insts_0'.size_info().north*0.5), direction=i3.PORT_DIRECTION.IN, angle_deg=180, trace_template=self.cell.channel_template) #port2 ports += microfluidics.FluidicPort( name='out', position=(self.wholeTrapX, self.wholeTrapY * 0.5), direction=i3.PORT_DIRECTION.OUT, angle_deg=0, trace_template=self.cell.channel_template) return ports
class TeeSimple(i3.PCell): """A generic Tee to connect elements. It is defined by a boundary which are defined by points """ channel_template = microfluidics.ChannelTemplateProperty( default=microfluidics.ShortChannelTemplate(), doc="Channel template of the tee") _name_prefix = "Tee" # a prefix added to the unique identifier TECH = i3.get_technology() class Layout(i3.LayoutView): tee_length = i3.NumberProperty(default=10.0, doc="length of each tee branch") def _generate_instances(self, elems): # insts): channel1 = microfluidics.Channel( trace_template=self.cell.channel_template) channel1_lo = channel1.Layout( shape=i3.Shape([(0, -self.tee_length), (0, self.tee_length)])) elems += i3.SRef(channel1, position=(0, 0)) channel2 = microfluidics.Channel( trace_template=self.cell.channel_template) channel2_lo = channel2.Layout(shape=[(0, 0), (-self.tee_length, 0)]) elems += i3.SRef(channel2, position=(self.tee_length, 0)) return elems #insts def _generate_ports(self, ports): #port1 ports += microfluidics.FluidicPort( name='in1', position=(0, -self.tee_length), direction=i3.PORT_DIRECTION.IN, angle_deg=270, trace_template=self.cell.channel_template) #port2 ports += microfluidics.FluidicPort( name='in2', position=(0, self.tee_length), direction=i3.PORT_DIRECTION.IN, angle_deg=90, trace_template=self.cell.channel_template) #port3 ports += microfluidics.FluidicPort( name='out1', position=(self.tee_length, 0.0), direction=i3.PORT_DIRECTION.IN, angle_deg=0, trace_template=self.cell.channel_template) return ports
class Block(i3.PCell): """A generic cell trap class. It is defined by a boundary which are defined by points """ _name_prefix = "BLOCK" # a prefix added to the unique identifier channel_template = microfluidics.ChannelTemplateProperty( default=microfluidics.ShortChannelTemplate(), doc="Channel template") TECH = i3.get_technology() class Layout(i3.LayoutView): # definition of the default values of the block PCELL block_length = i3.PositiveNumberProperty(default=300.0) def _generate_elements(self, insts): block_width = self.channel_template.channel_width point_list = [] point_list.append((-self.block_length * 0.5, -block_width * 0.5)) point_list.insert(0, (-self.block_length * 0.5, block_width * 0.5)) point_list.append((self.block_length * 0.5, -block_width * 0.5)) point_list.insert(0, (self.block_length * 0.5, block_width * 0.5)) t = i3.Shape(point_list, closed=True) bo = i3.Boundary(i3.TECH.PPLAYER.CH2.TRENCH, t) insts += bo #comm/uncomm for debugging round stl return insts def _generate_ports(self, ports): #port1 ports += microfluidics.FluidicPort( name='in1', position=(-self.block_length * 0.5, 0.0), direction=i3.PORT_DIRECTION.IN, angle_deg=180, trace_template=self.channel_template) ports += microfluidics.FluidicPort( name='out1', position=(self.block_length * 0.5, 0.0), direction=i3.PORT_DIRECTION.IN, angle_deg=0, trace_template=self.channel_template) return ports
class CircuitOfBlocks(microfluidics.PlaceAndAutoRoute): """Parametric cell with several traps, which are stacked vertically (Parallel) or horizontally (Series) """ #_name_prefix = "circuitOfTraps" type = i3.NumberProperty(default=0) # 0 Paralell 1 Series block_distance = i3.NumberProperty(default=400.) #distance betwn traps block_with_tee = i3.ChildCellListProperty( ) # Generating traps with Tee from Child Cell List Property trace_template = microfluidics.ChannelTemplateProperty( default=microfluidics.ShortChannelTemplate()) n_blocks_x = i3.PositiveIntProperty(default=30) n_blocks_y = i3.PositiveIntProperty(default=30) x_footprint = i3.PositiveIntProperty(default=1000) y_footprint = i3.PositiveIntProperty(default=1000) def _default_child_cells(self): return { "blk_w_tee{}".format(cnt): self.block_with_tee[cnt] for cnt in range(self.n_blocks_x * self.n_blocks_y) } def _default_links(self): links = [] bx = self.n_blocks_x ######################## ############# PARALLEL if self.type == 0: for cntx in range(0, self.n_blocks_x): # self connection at the top -bypass top = self.n_blocks_y * self.n_blocks_x - self.n_blocks_x + cntx links.append(("blk_w_tee{}:in2".format(top), "blk_w_tee{}:out2".format(top))) # connecting bottom to top for cnty in range(0, self.n_blocks_y - 1): links.append( ("blk_w_tee{}:in2".format(cnty * bx + cntx), "blk_w_tee{}:in1".format((cnty + 1) * bx + cntx))) links.append( ("blk_w_tee{}:out2".format(cnty * bx + cntx), "blk_w_tee{}:out1".format((cnty + 1) * bx + cntx))) #interconnecting horizontally if self.n_blocks_x > 1: for cntd in range(0, self.n_blocks_x - 1): links.append(("blk_w_tee{}:out1".format(cntd), "blk_w_tee{}:in1".format(cntd + 1))) ######## END PARALLEL ################# ######################## ############# SERIES if self.type == 1: # series #all by-pass, each object for cnt in range(0, self.n_blocks_y * self.n_blocks_x): #all bypass links.append(("blk_w_tee{}:in2".format(cnt), "blk_w_tee{}:out2".format(cnt))) #all interconnecting horizontally if self.n_blocks_x > 1: for cnty in range(0, self.n_blocks_y): for cntd in range(0, (self.n_blocks_x - 1)): links.append( ("blk_w_tee{}:out1".format(cnty * bx + cntd), "blk_w_tee{}:in1".format(cnty * bx + cntd + 1))) #left connections for cntd in range(1, (self.n_blocks_y - 1), 2): #links.append(("blk_w_tee{}:in1".format(cntd * bx), "blk_w_tee{}:in1".format((cntd+1) * bx))) links.append(("blk_w_tee{}:in1".format( (cntd + 1) * bx), "blk_w_tee{}:in1".format(cntd * bx))) #right connections for cntd in range(1, (self.n_blocks_y), 2): links.append(("blk_w_tee{}:out1".format(cntd * bx - 1), "blk_w_tee{}:out1".format((cntd + 1) * bx - 1))) ######## END SERIES ################# return links def _default_block_with_tee( self): # Generating traps from Child Cell List Property tee1 = TeeSimple() tee1.Layout(tee_length=(200.0)) my_block = CellTrapSimple() my_block.Layout(cell_trap_length=300.0) return [ TrapWithTees( name="blk_w_tee_{}".format(cnt), trap=my_block, tee=tee1, ) for cnt in range(self.n_blocks_x * self.n_blocks_y) ] class Layout(microfluidics.PlaceAndAutoRoute.Layout): def _default_child_transformations(self): # generate grid x = np.linspace(0, self.cell.x_footprint, self.cell.n_blocks_x) y = np.linspace(0, self.cell.y_footprint, self.cell.n_blocks_y) # generate positions from functions.position_coordinates import generate_positions coords = generate_positions(x, y, self.type) return { "blk_w_tee{}".format(cnt): i3.Translation(coords[cnt]) for cnt in range(self.n_blocks_x * self.n_blocks_y) } def _generate_ports(self, ports): # Add ports if self.type == 0: ports += i3.expose_ports( self.instances, { 'blk_w_tee0:in1': 'in1', 'blk_w_tee{}:out1'.format(self.n_blocks_x - 1): 'out1' }) if self.type == 1: if self.n_blocks_y % 2 == 0: ports += i3.expose_ports( self.instances, { 'blk_w_tee0:in1': 'in1', 'blk_w_tee{}:in1'.format(self.n_blocks_x * self.n_blocks_y - self.n_blocks_x): 'out1' # last left }) else: ports += i3.expose_ports( self.instances, { 'blk_w_tee0:in1': 'in1', 'blk_w_tee{}:out1'.format(self.n_blocks_x * self.n_blocks_y - 1): 'out1' # last right }) return ports
class CellTrapSimple(i3.PCell): """ Provide a description of this PCell """ _name_prefix = "CELLTRAP" # a prefix added to the unique identifier channel_template = microfluidics.ChannelTemplateProperty( default=microfluidics.ShortChannelTemplate(), doc="Channel template") class Layout(i3.LayoutView): cell_trap_length = i3.PositiveNumberProperty(default=300.0, doc="total length") cell_trap_gap = i3.NumberProperty(default=10.0, doc="trap gap") cell_trap_gap_length = i3.NumberProperty(default=60.0, doc="length of trap section") in_angle = i3.NumberProperty(default=85, doc="internal entry angle of the trap ") out_angle = i3.NumberProperty(default=85, doc="internal exit angle of the trap ") radius_fillet = i3.NumberProperty( default=3, doc="radius for rounding internal edges/corners") ''' ----------------------------\ /-------------- in angle \ / outangle \ / |_____| _____ | | / \ in angle / \outangle ____________________________/ \------------------ ''' def _generate_elements(self, elems): cell_trap_width = self.channel_template.channel_width alpha = math.radians(self.in_angle) beta = math.radians(self.out_angle) point_list = [] point_list.append( (-self.cell_trap_length * 0.25, -cell_trap_width * 0.5)) point_list.insert( 0, (-self.cell_trap_length * 0.25, cell_trap_width * 0.5)) point_list.append( (-(cell_trap_width - self.cell_trap_gap) / math.tan(alpha) - self.cell_trap_gap_length * 0.5, -(cell_trap_width * 0.5))) point_list.insert( 0, (-(cell_trap_width - self.cell_trap_gap) / math.tan(alpha) - self.cell_trap_gap_length * 0.5, (cell_trap_width * 0.5))) point_list.append((-self.cell_trap_gap_length * 0.25, -self.cell_trap_gap * 0.5)) # end of array point_list.insert( 0, (-self.cell_trap_gap_length * 0.25, self.cell_trap_gap * 0.5)) # begging of array, position 0 point_list.append( (self.cell_trap_gap_length * 0.25, -self.cell_trap_gap * 0.5)) point_list.insert( 0, (self.cell_trap_gap_length * 0.25, self.cell_trap_gap * 0.5)) point_list.append( ((cell_trap_width - self.cell_trap_gap) / math.tan(beta) + self.cell_trap_gap_length * 0.25, -(cell_trap_width * 0.5))) point_list.insert( 0, ((cell_trap_width - self.cell_trap_gap) / math.tan(beta) + self.cell_trap_gap_length * 0.25, (cell_trap_width * 0.5))) point_list.append( (-self.cell_trap_length * 0.25 + self.cell_trap_length * 0.5, -cell_trap_width * 0.5)) point_list.insert( 0, (-self.cell_trap_length * 0.25 + self.cell_trap_length * 0.5, cell_trap_width * 0.5)) t = i3.Shape(point_list, closed=True) rectang = i3.ShapeRound(original_shape=t, start_face_angle=0, end_face_angle=0, radius=self.radius_fillet) bo = i3.Boundary(self.channel_template.layer, rectang) #insts += bo #comm/uncomm for debugging round stl #creating an inlet rectangle boundary to avoid round corners point_list = [] #w = 3 point_list.append( (-self.cell_trap_length * 0.5, -cell_trap_width * 0.5)) point_list.insert( 0, (-self.cell_trap_length * 0.5, cell_trap_width * 0.5)) point_list.append( (-self.cell_trap_length * 0.25 + self.radius_fillet, -cell_trap_width * 0.5)) point_list.insert(0, (-self.cell_trap_length * 0.25 + self.radius_fillet, cell_trap_width * 0.5)) t = i3.Shape(point_list, closed=True) bo1 = i3.Boundary(self.channel_template.layer, t) #creating an outlet rectangle boundary to avoid round corners point_list = [] point_list.append( (self.cell_trap_length * 0.25 - self.radius_fillet, -cell_trap_width * 0.5)) point_list.insert(0, (self.cell_trap_length * 0.25 - self.radius_fillet, cell_trap_width * 0.5)) point_list.append( (self.cell_trap_length * 0.5, -cell_trap_width * 0.5)) point_list.insert(0, (-self.cell_trap_length * 0.5 + self.cell_trap_length, cell_trap_width * 0.5)) t = i3.Shape(point_list, closed=True) bo2 = i3.Boundary(self.channel_template.layer, t) #boolean operation adding main geometry and inlet rectangle b_add = bo1 | bo #boolean operation adding main geometry and outlet rectangle b_add2 = bo2 | b_add[0] elems += b_add2 return elems def _generate_ports(self, ports): #port1 ports += microfluidics.FluidicPort( name='in1', position=(-self.cell_trap_length * 0.5, 0.0), direction=i3.PORT_DIRECTION.IN, angle_deg=180, trace_template=self.channel_template) ports += microfluidics.FluidicPort( name='out1', position=(self.cell_trap_length * 0.5, 0.0), direction=i3.PORT_DIRECTION.IN, angle_deg=0, trace_template=self.channel_template) return ports
class Obstacle_BooleanBoundary(i3.PCell): # Properties of trap channel_template = microfluidics.ChannelTemplateProperty( default=microfluidics.ShortChannelTemplate(), doc="Channel template of the tee") _name_prefix = "VacTrapV" # a prefix added to the unique identifier radius = i3.PositiveNumberProperty( default=400., doc="radius of the circular vacuum section collecting air") vacuum_channel_circular = i3.PositiveNumberProperty( default=100., doc="width of circular channel collecting air") inlet_channel_length = i3.PositiveNumberProperty( default=300., doc="length of inlet channel vac") layer = i3.LayerProperty(default=i3.TECH.PPLAYER.CH2.TRENCH, doc='Layer to drawn on') cInp = i3.Coord2Property(default=(0.0, 0.0), required=True) class Layout(i3.LayoutView): def _generate_instances(self, insts): sr1 = i3.ShapeCircle(center=(0.0, 0.0), radius=self.radius) #, line_width = 200) sr2 = i3.ShapeCircle( center=(0.0, 0.0), radius=self.radius - self.vacuum_channel_circular) #, line_width = 200) #Rectangles sc1 = i3.ShapeRectangle( center=(self.cInp.x - self.radius, -self.radius), box_size=(self.radius * 2, self.radius * 2 + 100)) #100 has to be linked to channel input width)) #Define the boundaries for shapes br1 = i3.Boundary(layer=self.layer, shape=sr1) br2 = i3.Boundary(layer=self.layer, shape=sr2) bc1 = i3.Boundary(layer=self.layer, shape=sc1) #Substruct boundaries and add to the element list b_sub = br1 - br2 s = i3.Structure(elements=b_sub) b_sub = b_sub[0] - bc1 s = i3.Structure(elements=b_sub) insts += i3.SRef(s) #Input channel - segment channel1 = microfluidics.Channel( trace_template=self.cell.channel_template) channel1_lo = channel1.Layout( shape=[(0, 0), (0, self.inlet_channel_length + self.vacuum_channel_circular * 0.5)]) insts += i3.SRef(channel1_lo, position=(0, self.radius - self.vacuum_channel_circular * 0.5), transformation=i3.Rotation((0.0, 0.0), 0.0)) return insts #Thach added to define one inlet and one outlet def _generate_ports( self, ports): # Use _generate_ports method to define ports #ports += i3.InFluidicPort(name = "in", position = (0., 10.), angle = 180.0) ports += i3.OpticalPort(name="in", position=(0., self.radius + self.inlet_channel_length), angle=180.0) #ports += i3.OutFluidicPort(name ="out", position = (30., 10.), angle = 0.0) #ports += i3.OpticalPort(name ="out", position = ((self.obstacle_trap_length+self.gap_btw_barriers)*2, self.channel_trap_width*0.5), angle = 0.0) return ports
class Obstacle_BooleanBoundary(i3.PCell): # Properties of trap width = 200 #i3.PositiveNumberProperty(default=200.,doc="width main channel") channel_template = microfluidics.ChannelTemplateProperty( default=microfluidics.ShortChannelTemplate().Layout(width=width), doc="Channel template of the tee") _name_prefix = "VacTrapV" # a prefix added to the unique identifier radius = i3.PositiveNumberProperty( default=400., doc="radius of the circular vacuum section collecting air") vacuum_channel_circular = i3.PositiveNumberProperty( default=100., doc="width of circular channel collecting air") inlet_channel_length = i3.PositiveNumberProperty( default=300., doc="length of inlet channel vac") offset_matching = i3.PositiveNumberProperty( default=50., doc="length of inlet channel vac") obstacles = i3.ChildCellProperty( doc='the single Obstacle child cell, which will be clonned many times', default=JoinedObstacles(wholeTrapX=width)) layer = i3.LayerProperty(default=i3.TECH.PPLAYER.CH2.TRENCH, doc='Layer to drawn on') cInp = i3.Coord2Property(default=(0.0, 0.0), required=True) class Layout(i3.LayoutView): def _generate_instances(self, insts): width = 200.0 p1 = (-self.radius, -self.radius) #near cylinders p2 = (-self.radius, -2 * self.radius) #bottom p3 = (2 * self.radius, -2 * self.radius) #right p4 = (2 * self.radius, 0) #top p5 = (2 * self.radius + 500, 0) #out pax = (-width * 0.5 * math.cos(45), width * 0.5 * math.sin(45)) #generate a circle sr1 = i3.ShapeCircle(center=(0.0, 0.0), radius=self.radius) #, line_width = 200) br1 = i3.Boundary(layer=self.layer, shape=sr1) #s= i3.Structure(elements = br1) #rectangle sc1 = i3.ShapeRectangle(center=p1, box_size=(self.radius * 4, self.radius * 0.25)) bc1 = i3.Boundary(layer=self.layer, shape=sc1, transformation=i3.Rotation((0, 0), -45.0)) # was -35 #Substruct boundaries and add to the element list b_sub = br1 - bc1 s = i3.Structure(elements=b_sub) insts += i3.SRef(s) #Input channel - segment channel1 = microfluidics.Channel( trace_template=self.cell.channel_template) #channel_template = microfluidics.ShortChannelTemplate().Layout(width=200.0) channel1_lo = channel1.Layout(shape=[(self.inlet_channel_length + self.offset_matching * 0.5, 0), (0, 0)]) insts += i3.SRef( channel1_lo, position=(-(self.inlet_channel_length + self.radius), 0), transformation=i3.Rotation((0.0, 0.0), 0.0)) #############################routing from ipkiss.plugins.photonics.routing.manhattan import RouteManhattan channel_4 = microfluidics.RoundedChannel( trace_template=self.cell.channel_template) # used for routing channel_4_layout = channel_4.Layout() import operator p1Array = tuple(map(operator.add, p1, pax)) print 'p1: ', p1 print 'pax: ', pax print 'p1Array: ', p1Array #obstacles insts += i3.SRef(reference=self.obstacles, position=p1Array, transformation=i3.Rotation((0, 0), -45.0)) in_port_1 = microfluidics.FluidicPort( position=p1, trace_template=self.cell.channel_template) out_port_1 = microfluidics.FluidicPort( trace_template=self.cell.channel_template) in_port_1.angle_deg = 225 out_port_1.angle_deg = 45 in_port_2 = microfluidics.FluidicPort( position=p2, trace_template=self.cell.channel_template) in_port_2.angle_deg = 225 channel_4_layout.set(bend_radius=150.0, shape=RouteManhattan(input_port=in_port_2, points=[p2, p3, p4, p5], output_port=out_port_1, bend_radius=300.0)) insts += i3.SRef(name="Route_1", reference=channel_4) ##############################routing from ipkiss3.pcell.routing import RouteToAngle # create the route object channel_1 = microfluidics.RoundedChannel( trace_template=self.cell.channel_template) # used for routing channel_1_layout = channel_1.Layout() channel_1_layout.set(bend_radius=50.0, shape=RouteToAngle(input_port=in_port_1, start_straight=300, end_straight=300, angle_out=45)) #insts += i3.SRef(name = "Route_2", reference = channel_1) from ipkiss3.pcell.routing import RouteToEastAtMaxY, RouteToEastAtMinY, RouteToEastAtY # create the route object input_portx = i3.OpticalPort(name="in", position=(-self.radius, -self.radius), angle_deg=225.0) channel_x = microfluidics.RoundedChannel( trace_template=self.cell.channel_template) # used for routing channel_x_layout = channel_x.Layout() channel_x_layout.set(bend_radius=150.0, shape=RouteToEastAtY(input_port=input_portx, start_straight=200, end_straight=200, y_position=-2 * self.radius)) insts += i3.SRef(name="Route_x", reference=channel_x) return insts #Thach added to define one inlet and one outlet def _generate_ports( self, ports): # Use _generate_ports method to define ports #ports += i3.InFluidicPort(name = "in", position = (0., 10.), angle = 180.0) ports += i3.OpticalPort(name="in", position=(0., self.radius + self.inlet_channel_length), angle=180.0) #ports += i3.OutFluidicPort(name ="out", position = (30., 10.), angle = 0.0) #ports += i3.OpticalPort(name ="out", position = ((self.obstacle_trap_length+self.gap_btw_barriers)*2, self.channel_trap_width*0.5), angle = 0.0) return ports