Best Python code snippet using localstack_python
prime_tower.py
Source:prime_tower.py
1from tool_change_plan import LayerInfo, ToolChangeInfo, ToolChangeException2from gcode_analyzer import Token3import tool_change_plan4import gcode_analyzer5import doublelinkedlist6import conf7import copy, math, time, logging8from collections import deque9import logging10logger = logging.getLogger(__name__)11# Function to generate vertices for a circle 12def circle_generate_vertices(cx, cy, radius, num_faces):13 vertices = []14 for indx in range(0, num_faces):15 alpha = 2 * math.pi * float(indx) / num_faces16 x = round(radius * math.cos(alpha) + cx, 3)17 y = round(radius * math.sin(alpha) + cy, 3)18 vertices.append([x, y])19 return vertices 20# Function to Generate a Zig-Zag between two circles21def zigzag_generate_vertices(cx, cy, r1, r2, num_faces):22 v1 = circle_generate_vertices(cx, cy, r1, num_faces)23 v2 = circle_generate_vertices(cx, cy, r2, num_faces)24 v = []25 for indx in range(0, num_faces):26 v.append(v1[indx])27 v.append(v2[indx])28 return v29# Tool change exception30class PrimeTowerException(Exception):31 def __init__(self, message):32 self.message = message 33###########################################################################################################34# Prime Tower Layer Info35class PrimeTowerLayerInfo(LayerInfo):36 def __init__(self, layer_num = 0, layer_z = 0.0, layer_height = 0.0, tool_change_seq = None, prime_tower = None):37 LayerInfo.__init__(self, 38 layer_num = layer_num, 39 layer_z = layer_z, 40 layer_height = layer_height, 41 tool_change_seq = tool_change_seq)42 self.prime_tower = prime_tower43 # Create tokens for printing a shape44 # Moves to the first point 45 def gcode_print_shape(self, vertices, tool_id, retract_on_move = True, closed = True):46 tokens = doublelinkedlist.DLList()47 if tool_id not in self.tools_active:48 raise gcode_analyzer.GCodeSerializeException("Tool {tool_id} not in active set of prime tower layer #{layer_num}".format(49 tool_id = tool_id,50 layer_num = self.layer_num))51 52 tokens.append_node(gcode_analyzer.GCode('G1', {'X' : vertices[0][0], 'Y' : vertices[0][1]}))53 tokens.append_node(gcode_analyzer.GCode('G1', {'F' : conf.prime_tower_print_speed}))54 for v in range(1, len(vertices)):55 distance = math.sqrt((vertices[v][0] - vertices[v-1][0])**2 + (vertices[v][1] - vertices[v-1][1])**2)56 E = conf.calculate_E(tool_id, self.layer_height, distance)57 tokens.append_node(gcode_analyzer.GCode('G1', {'X' : vertices[v][0], 'Y' : vertices[v][1], 'E' : E}))58 if closed:59 distance = math.sqrt((vertices[-1][0] - vertices[0][0])**2 + (vertices[-1][1] - vertices[0][1])**2)60 E = conf.calculate_E(tool_id, self.layer_height, distance)61 tokens.append_node(gcode_analyzer.GCode('G1', {'X' : vertices[0][0], 'Y' : vertices[0][1], 'E' : E}))62 return tokens63 # Create gcode for band for specific tool64 def gcode_pillar_band(self, tool_id):65 band_gcode = doublelinkedlist.DLList()66 for radius in self.prime_tower.get_pillar_bands(self.layer_num, tool_id):67 # Start each circle at a different point to avoid weakening the tower68 circle_vertices = deque(circle_generate_vertices(conf.prime_tower_x, conf.prime_tower_y, radius, conf.prime_tower_band_num_faces))69 circle_vertices.rotate(self.layer_num)70 band_gcode.append_nodes(self.gcode_print_shape(circle_vertices, tool_id))71 if conf.GCODE_VERBOSE:72 band_gcode.head.comment = "TC-PSPP - T{tool} - Pillar - Start".format(tool = tool_id)73 band_gcode.tail.comment = "TC-PSPP - T{tool} - Pillar - End".format(tool = tool_id)74 75 return band_gcode76 # Generate gcode for pillar bands for IDLE tools77 def gcode_pillar_idle_tool_bands(self, tool_id): 78 # Generate vertices79 tokens = doublelinkedlist.DLList()80 for idle_tool_id in self.tools_idle:81 gcode_band = doublelinkedlist.DLList()82 for radius in self.prime_tower.get_pillar_bands(self.layer_num, idle_tool_id):83 vertices = circle_generate_vertices(conf.prime_tower_x, conf.prime_tower_y, radius, conf.prime_tower_band_num_faces)84 gcode_band.append_nodes(self.gcode_print_shape(vertices, tool_id))85 86 gcode_band.head.append_node(gcode_analyzer.GCode('G11'))87 gcode_band.head.append_node_left(gcode_analyzer.GCode('G10'))88 tokens.append_nodes(gcode_band)89 if conf.GCODE_VERBOSE:90 tokens.head.comment = "TC-PSPP - Prime tower idle tool infill for layer #{layer} - start".format(layer = self.layer_num)91 tokens.tail.comment = "TC-PSPP - Prime tower idle tool infill for layer #{layer} - end".format(layer = self.layer_num)92 return tokens93 # Find wipe end point94 def gcode_wipe_path(self, start_point, length, retract_length):95 path = []96 x0, y0, z0 = start_point.state_post.x, start_point.state_post.y, start_point.state_post.z97 previous_move = start_point98 accumulated_dist = 0.099 while accumulated_dist < length:100 if previous_move.state_pre == None:101 break102 x1, y1, z1 = previous_move.state_pre.x, previous_move.state_pre.y, previous_move.state_pre.z103 if z1 != z0:104 break105 dist = math.sqrt((x1-x0)**2 + (y1-y0)**2)106 # If end107 if dist + accumulated_dist > length:108 # Check cutoff109 dist_corrected = length - accumulated_dist110 x1 = x0 + (x1 - x0) * (dist_corrected / dist)111 y1 = y0 + (y1 - y0) * (dist_corrected / dist)112 dist = dist_corrected113 if dist != 0.0:114 accumulated_dist += dist115 x0, y0 = x1, y1116 path.append((x1, y1, dist))117 if previous_move.prev is not None:118 previous_move = previous_move.prev119 if accumulated_dist < length:120 logger.warn("Calculated wipe path {wipe_length:0.2f}[mm] less then configured {length:0.2f}[mm]".format(wipe_length = accumulated_dist, length = length))121 # Generate GCodes122 gcode = doublelinkedlist.DLList()123 if len(path) > 2:124 for vertex in path:125 to_retract = -retract_length * (vertex[2]) / accumulated_dist126 gcode.append_node(gcode_analyzer.GCode('G1', {'X' : vertex[0], 'Y' : vertex[1], 'E' : to_retract}))127 logger.info("Calculated wipe path: {length}".format(length = accumulated_dist))128 else:129 # Just add retraction130 gcode.append_node(gcode_analyzer.GCode('G1', {'E', -retract_length}))131 gcode.head.comment = "wipe start"132 return gcode133 # Inject move to prime tower134 # Assumes first gcode in gcode is G1 - move135 def inject_prime_tower_move_in(self, inject_point, gcode):136 inject_state = inject_point.state_post137 gcode_pre = doublelinkedlist.DLList()138 gcode_post = doublelinkedlist.DLList()139 # If firmware retracts - it is quite simple140 if conf.retraction_firmware:141 # - if prime tower Z is higher then current Z - inject Z move before moving to brim XY142 # - if prime tower Z is lower then current Z - inject Z move after brim XY143 if inject_state.z == None or inject_state.z < self.layer_z:144 gcode.head.append_node_left(gcode_analyzer.GCode('G1', { 'Z' : self.layer_z} ))145 elif inject_state.z > self.layer_z:146 gcode.head.append_node(gcode_analyzer.GCode('G1', { 'Z' : self.layer_z} ))147 # - if was unretracted - add retraction/unretraction around the first move from gcode148 if not inject_state.is_retracted:149 gcode.head.append_node(gcode_analyzer.GCode('G11', comment = 'move-in detract'))150 gcode.head.append_node_left(gcode_analyzer.GCode('G10', comment = 'move-in retract' ))151 152 # - if was retracted, just add unretraction after first move from gcode153 if inject_state.is_retracted:154 gcode.head.append_node(gcode_analyzer.GCode('G11', comment = 'move-in detract'))155 gcode.head.append_node_left(gcode_analyzer.GCode('G1', { 'F' : conf.prime_tower_move_speed }))156 # If not firmware retract - do a move manually157 # If not retracted also do a wipe move (not longer then 1mm)158 if not conf.retraction_firmware:159 # If not retracted do a wipe move160 to_detract = 0.0161 if inject_state.is_retracted:162 to_detract = abs(inject_state.retraction)163 else:164 # We will need to detract same what retract in next step165 to_detract = conf.retraction_length[inject_state.tool_selected]166 # If retracted but we need to ajust the Z167 gcode_pre = doublelinkedlist.DLList()168 if inject_state.is_retracted:169 move_z = self.layer_z + conf.retraction_zhop[inject_state.tool_selected]170 if move_z > inject_state.z:171 gcode_pre.append_node(gcode_analyzer.GCode('G1', {'F', conf.prime_tower_move_speed}))172 gcode_pre.append_node(gcode_analyzer.GCode('G1', {'Z', move_z }))173 else:174 # Need to retract and Z-hop175 move_z = max(inject_state.z, self.layer_z) + conf.retraction_zhop[inject_state.tool_selected]176 177 gcode_pre.append_node(gcode_analyzer.GCode('G1', {'F' : conf.retraction_speed[inject_state.tool_selected]}))178 # Add the wipe179 if conf.wipe_distance > 0.0:180 wipe_gcode = self.gcode_wipe_path(inject_point, conf.wipe_distance, conf.retraction_length[inject_state.tool_selected] / 2.0)181 gcode_pre.append_nodes(wipe_gcode)182 gcode_pre.append_node(gcode_analyzer.GCode('G1', {'E' : -conf.retraction_length[inject_state.tool_selected] / 2.0}))183 else:184 gcode_pre.append_node(gcode_analyzer.GCode('G1', {'E' : -conf.retraction_length[inject_state.tool_selected]}))185 gcode_pre.append_node(gcode_analyzer.GCode('G1', {'F', conf.prime_tower_move_speed}))186 gcode_pre.append_node(gcode_analyzer.GCode('G1', {'Z', move_z }))187 # Add the speed188 gcode_pre.append_node(gcode_analyzer.GCode('G1', {'F', conf.prime_tower_move_speed}))189 gcode_post = doublelinkedlist.DLList()190 gcode_post.append_node(gcode_analyzer.GCode('G1', {'Z' : self.layer_z, 'E' : conf.retraction_length[inject_state.tool_selected]}))191 # Add to gcode 192 gcode.head.append_nodes_right(gcode_post)193 gcode.head.append_nodes_left(gcode_pre)194 return gcode195 # Inject move out of prime tower196 def inject_prime_tower_move_out(self, inject_point, gcode):197 inject_state = inject_point.state_post198 # - if prime tower is higher then inject point Z, move XY first and then Z199 # - if prime tower is lower then inject point Z, move Z first and then XY200 if inject_state.z is None:201 raise PrimeTowerException("Malformed GCode - injecting prime tower move-out code where Z is not set")202 # If firmware retracts - it is quite simple203 if conf.retraction_firmware:204 # No need to move out in 205 # -To handle the situation where state is not set initially206 # - Inject point is BEFORE_LAYER_END207 # 208 if inject_point.type != Token.PARAMS or inject_point.label != 'BEFORE_LAYER_CHANGE':209 gcode.append_node(gcode_analyzer.GCode('G10', comment = 'move-out retract'))210 if inject_state.x != None and inject_state.y != None:211 gcode.append_node(gcode_analyzer.GCode('G1', { 'F' : conf.prime_tower_move_speed }))212 if inject_state.z < self.layer_z:213 gcode.append_node(gcode_analyzer.GCode('G1', { 'X' : inject_state.x, 'Y' : inject_state.y }))214 gcode.append_node(gcode_analyzer.GCode('G1', { 'Z' : inject_state.z }))215 elif inject_state.z > self.layer_z:216 gcode.append_node(gcode_analyzer.GCode('G1', { 'Z' : inject_state.z }))217 gcode.append_node(gcode_analyzer.GCode('G1', { 'X' : inject_state.x, 'Y' : inject_state.y }))218 else:219 gcode.append_node(gcode_analyzer.GCode('G1', { 'X' : inject_state.x, 'Y' : inject_state.y }))220 gcode.append_node(gcode_analyzer.GCode('G1', { 'F' : inject_state.feed_rate}))221 else:222 logger.warn("X/Y position state not present, if this error apears more then once the GCode is malformed")223 # Retract before 224 # - if tool was unretracted before entry point - unretract after the move225 if not inject_state.is_retracted:226 gcode.append_node(gcode_analyzer.GCode('G11', comment = 'move-out detract'))227 else:228 if inject_state.is_retracted:229 gcode.append_node(gcode_analyzer.GCode('G10', comment = 'move-out retract'))230 # If slicer retracts - more work231 if not conf.retraction_firmware:232 # No need to move out in:233 # - to handle the situation where state is not set initially234 # - Inject point is BEFORE_LAYER_END235 if inject_point.type != Token.PARAMS or inject_point.label != 'BEFORE_LAYER_CHANGE':236 move_z = max(inject_state.z, self.layer_z) + conf.retraction_zhop[inject_state.tool_selected]237 gcode.append_node(gcode_analyzer.GCode('G1', {'F' : conf.retraction_speed[inject_state.tool_selected]}, comment = 'move-out retract'))238 gcode.append_node(gcode_analyzer.GCode('G1', {'E' : -conf.retraction_length[inject_state.tool_selected]}))239 gcode.append_node(gcode_analyzer.GCode('G1', {'F' : conf.prime_tower_move_speed}))240 gcode.append_node(gcode_analyzer.GCode('G1', {'Z' : move_z }))241 gcode.append_node(gcode_analyzer.GCode('G1', {'X' : inject_state.x, 'Y' : inject_state.y}))242 gcode.append_node(gcode_analyzer.GCode('G1', {'Z' : inject_state.z}))243 if not inject_state.is_retracted:244 gcode.append_node(gcode_analyzer.GCode('G1', {'F' : conf.retraction_speed[inject_state.tool_selected]}))245 gcode.append_node(gcode_analyzer.GCode('G1', {'E' : conf.retraction_length[inject_state.tool_selected]}))246 else:247 if inject_state.is_retracted:248 gcode.append_node(gcode_analyzer.GCode('G1', {'F' : conf.retraction_speed[inject_state.tool_selected]}))249 gcode.append_node(gcode_analyzer.GCode('G1', {'E' : -conf.retraction_length[inject_state.tool_selected]}))250 251 return gcode252 # Inject prime tower layer gcode253 def inject_gcode(self):254 255 filled_idle_gaps = False256 # Check if we need to continue constructing the tower257 if len(self.tools_active) == 1 and len(self.tools_idle) == 0:258 logger.debug("One tool ACTIVE and no more IDLE tools - can stop generating prime tower")259 return 260 tool_indx = 0261 for tool_change in self.tools_sequence:262 inject_point = None263 if tool_indx == 0 and self.layer_num == 0:264 inject_point = self.layer_start265 elif tool_indx == 0 and len(self.tool_change_seq) == 0:266 inject_point = self.layer_end267 elif tool_indx == 0 and len(self.tools_sequence) > 0:268 # de-prime (fill the gap) - prefered because we use same filament269 inject_point = tool_change.block_end270 else:271 inject_point = tool_change.block_start272 # Not gonna happen - because we will cut off earlier but273 if inject_point is None:274 raise PrimeTowerException("Inject-Point is None...")275 # Generate BAND276 gcode_band = self.gcode_pillar_band(tool_id = tool_change.tool_id)277 logger.debug("Generated prime tower band for layer #{layer_num} for T{tool}".format(layer_num = self.layer_num, tool = tool_change.tool_id))278 gcode_idle = None279 if not filled_idle_gaps and len(self.tools_idle) != 0:280 gcode_idle = self.gcode_pillar_idle_tool_bands(tool_change.tool_id)281 filled_idle_gaps = True282 logger.debug("Generated prime tower idle tools infill for layer #{layer_num} with T{tool}".format(layer_num = self.layer_num, tool = tool_change.tool_id))283 # Finally inject 284 gcode = gcode_band285 # 1) Move to Z of Prime Tower layer 286 # 2) Check if the tool has been already retracted, if not don't retract again287 gcode = self.inject_prime_tower_move_in(inject_point, gcode) 288 289 # 3) Add the idle tools290 if gcode_idle is not None:291 gcode.append_nodes(gcode_idle)292 # 4) If was retracted - retract293 # 5) Go back to the previous position - but not if block end 294 if inject_point.type == Token.PARAMS and inject_point.label != 'TOOL_BLOCK_END':295 gcode = self.inject_prime_tower_move_out(inject_point, gcode)296 # Info297 gcode.head.append_node_left(gcode_analyzer.Comment("prime-tower layer #{layer_num}".format(layer_num = self.layer_num)))298 inject_point.append_nodes_right(gcode)299 logger.debug("(DEBUG) Generated prime tower band for layer #{layer} for T{tool}".format(layer = self.layer_num, tool = tool_change.tool_id))300 tool_indx += 1301###########################################################################################################302# Prime Tower 303# Contains all the information related to prime tower generation304class PrimeTower:305 def __init__(self, layers = None):306 pass307 #if layers is not None:308 # self.generate_layers(layers)309 310 # Generate bands for a layer/tool311 def generate_pillar_bands(self):312 self.band_radiuses = {} 313 self.brim_radiuses = {}314 # Enabled tools - in sequence315 layer0_tools = [tool.tool_id for tool in self.layers[0].tools_sequence] + sorted(self.layers[0].tools_idle)316 # - BRIM317 current_r = conf.prime_tower_r318 for tool in layer0_tools:319 self.brim_radiuses[tool] = []320 for indx in range(0, conf.brim_width):321 current_r += conf.tool_nozzle_diameter[tool] / 2.0322 self.brim_radiuses[tool].append(current_r)323 current_r += conf.tool_nozzle_diameter[tool] / 2.0324 current_r = conf.prime_tower_r325 while current_r > 1.5 * conf.tool_nozzle_diameter[0]:326 current_r -= conf.tool_nozzle_diameter[0] / 2.0327 self.brim_radiuses[tool].insert(0, current_r)328 current_r -= conf.tool_nozzle_diameter[0] / 2.0329 # - BAND330 current_r = conf.prime_tower_r331 for tool in layer0_tools:332 self.band_radiuses[tool] = []333 for indx in range(0, conf.prime_tower_band_width):334 current_r += conf.tool_nozzle_diameter[tool] / 2.0335 self.band_radiuses[tool].append(current_r)336 current_r += conf.tool_nozzle_diameter[tool] / 2.0337 # Get the bands for specific layer338 def get_pillar_bands(self, layer_num, tool_id):339 if layer_num < conf.brim_height:340 return self.brim_radiuses[tool_id]341 else:342 return self.band_radiuses[tool_id]343 # Analyze the tool status344 def analyze_tool_status(self):345 current_tool = None346 enabled_tools = set()347 # Analyse which tools are active per layer (active = printing)348 for layer_info in self.layers:349 # Reset the statuses350 layer_info.reset_status()351 if current_tool is not None:352 layer_info.tools_active.add(current_tool.tool_id)353 for tool_change in layer_info.tool_change_seq:354 current_tool = tool_change355 layer_info.tools_active.add(tool_change.tool_id)356 # add the tools to enabled tools set 357 enabled_tools |= layer_info.tools_active358 # Analyse which tools are disabled (temp = 0) or idle (on standby) per layer359 for layer_info in reversed(self.layers):360 next_layer = layer_info.layer_num + 1361 362 if next_layer == len(self.layers):363 # If it's the last layer 364 # - everything that is not active is disabled365 layer_info.tools_idle = set()366 layer_info.tools_disabled = enabled_tools - layer_info.tools_active367 else:368 # If it's not the last layer369 # - suspended in this layer = (suspended in next layer & active in next layer) & !active in this layer)370 # - disabled in this layer = disabled in next layer & !active in this layer371 layer_info.tools_idle = (self.layers[next_layer].tools_idle | self.layers[next_layer].tools_active) - layer_info.tools_active372 layer_info.tools_disabled = self.layers[next_layer].tools_disabled - layer_info.tools_active373 # Generate the layers for prime tower printing374 def analyze_gcode(self, gcode_analyzer):375 self.layers = [PrimeTowerLayerInfo(prime_tower = self)]376 t_start = time.time()377 # Active tool378 current_tool = None # Tool Change Info379 layer_info = self.layers[-1] # Layer Info380 for token in gcode_analyzer.analyze_state():381 # Check if AFTER_LAYER_CHANGE label382 if token.type == Token.PARAMS and token.label == 'AFTER_LAYER_CHANGE':383 current_layer, current_layer_z = token.param[0], token.param[1]384 previous_layer_z = 0.0385 # This is because will put first tool before the AFTER_LAYER_CHANGE-BEFORE_LAYER_CHANGE block386 if current_layer != 0:387 previous_layer_z = layer_info.layer_z388 layer_info = PrimeTowerLayerInfo(prime_tower = self)389 self.layers.append(layer_info)390 391 # Update the value392 layer_info.layer_num = current_layer393 layer_info.layer_z = current_layer_z394 layer_info.layer_height = current_layer_z - previous_layer_z395 396 # Update the values397 layer_info.layer_start = token398 # If current tool is not none 399 if current_tool is not None:400 self.layers[-1].tools_sequence = [current_tool]401 else:402 self.layers[-1].tools_sequence = []403 continue404 # Check if BEFORE_LAYER_CHANGE label405 if token.type == Token.PARAMS and token.label == 'BEFORE_LAYER_CHANGE':406 # Mark the last layer end as the token before BEFORE_LAYER_CHANGE407 layer_info.layer_end = token408 # Validate the height409 toolset = [tool_change_info.tool_id for tool_change_info in layer_info.tools_sequence]410 toolset_max_layer_height = conf.max_layer_height(toolset)411 # Layer height higher then max for the toolset (shouldn't happen!)412 if round(layer_info.layer_height, 5) > toolset_max_layer_height:413 raise PrimeTowerException("Input layer #{layer_num} height {layer_height:0.4f} higher then max allowed for the toolset {tools}".format(414 layer_num = layer_info.layer_num,415 layer_height = layer_info.layer_height, 416 tools = ','.join(['T' + str(tool_id) for tool_id in toolset])))417 continue418 # Check if Tool change419 if token.type == Token.TOOLCHANGE:420 if token.next_tool != -1:421 current_tool = ToolChangeInfo(tool_change = token)422 logger.debug("PrimeTower - Added tool T{tool_id} to layer #{layer_num}".format(tool_id = token.next_tool, layer_num = self.layers[-1].layer_num))423 layer_info.tool_change_seq.append(current_tool)424 layer_info.tools_sequence.append(current_tool)425 continue426 # Beginning to Tool block427 if token.type == Token.PARAMS and token.label == 'TOOL_BLOCK_START':428 tool_id = token.param[0]429 if tool_id != -1:430 if tool_id != current_tool.tool_id:431 raise ToolChangeException(message = "Tool id {tool_id} from TOOL_BLOCK_START doesn't match last active tool in layer".format(tool_id = tool_id), tool_id = tool_id)432 current_tool.block_start = token433 continue434 # End of Tool block435 if token.type == Token.PARAMS and token.label == 'TOOL_BLOCK_END':436 tool_id = token.param[0]437 if tool_id != -1:438 if tool_id != current_tool.tool_id:439 raise ToolChangeException(message = "Tool id {tool_id} from TOOL_BLOCK_END doesn't match last active tool in layer".format(tool_id = tool_id), tool_id = tool_id)440 current_tool.block_end = token441 continue442 443 # Generate the active/idle/disabled list444 #-----------------------------------------------------------445 self.analyze_tool_status()446 # Calc band and brim info447 self.generate_pillar_bands()448 t_end = time.time()449 logger.info("PrimeTower: analysis done [elapsed: {elapsed:0.2f}s]".format(elapsed = t_end - t_start))450 return True451 # Optimize the layers of prime tower452 # Squish the layers of prime tower following the rules:453 # For layer {prev,next}454 # - only squish if tool changes in layer next are not in tool changes for layer prev455 # - only squish if layer_height after squish is less then max layer height for new active toolset456 def optimize_layers(self):457 # New layers458 optimized_layers = [self.layers[0]]459 optimized_layer_indx = 0460 for layer_info in self.layers[1:]:461 # 0) number of active tools is just 1 - no need to continue462 if len(layer_info.tools_active) == 1 and len(layer_info.tools_idle) == 0:463 break464 # 1) tool changes not in previous layer tool changes465 prev_layer_tool_seq = [tool.tool_id for tool in optimized_layers[optimized_layer_indx].tools_sequence]466 next_layer_tool_seq = [tool.tool_id for tool in layer_info.tools_sequence]467 can_squish = False468 # Can only squish if:469 # - last tool of the previous layer is same as first tool of next layer (i.e. no immediedate change on layer)470 # AND471 # - every tool used in next layer (after first) is different from every tool used in previous layer (except the last)472 if prev_layer_tool_seq[-1] == next_layer_tool_seq[0] and len(set(prev_layer_tool_seq[:-1]) & set(next_layer_tool_seq[1:])) == 0:473 can_squish = True474 # Update existing475 if can_squish:476 # New tool change sequence477 optimized_layer_height = optimized_layers[optimized_layer_indx].layer_height + layer_info.layer_height478 optimized_active_tools = copy.copy(optimized_layers[optimized_layer_indx].tools_active)479 optimized_active_tools.update(next_layer_tool_seq[1:])480 min_layer_height = conf.min_layer_height(optimized_active_tools)481 max_layer_height = conf.max_layer_height(optimized_active_tools)482 # 2) new layer height within margins483 if min_layer_height <= optimized_layer_height <= max_layer_height:484 # Update the old layer485 optimized_layers[optimized_layer_indx].tool_change_seq += copy.copy(layer_info.tool_change_seq)486 optimized_layers[optimized_layer_indx].tools_active = optimized_active_tools487 optimized_layers[optimized_layer_indx].tools_sequence += layer_info.tools_sequence[1:]488 optimized_layers[optimized_layer_indx].layer_z = layer_info.layer_z489 optimized_layers[optimized_layer_indx].layer_height = round(optimized_layer_height, 2)490 optimized_layers[optimized_layer_indx].layer_end = layer_info.layer_end491 492 logger.debug("Optimized layer height : {height:0.2f} within [{min:0.2f},{max:0.2f}] for tools active [{tools}]".format(493 height = optimized_layer_height, 494 min = min_layer_height, 495 max = max_layer_height,496 tools = ','.join([str(tool.tool_id) for tool in optimized_layers[optimized_layer_indx].tools_sequence])))497 logger.debug("Prime tower layer #{layer_num} can be combined with previous layer, squashing...".format(layer_num = layer_info.layer_num))498 logger.debug(" >> prev layer tools active : {seq}".format(seq = [str(tool) for tool in prev_layer_tool_seq]))499 logger.debug(" >> next layer tools active : {seq}".format(seq = [str(tool) for tool in next_layer_tool_seq]))500 continue501 # Not able to squash - just copying502 optimized_layer_indx += 1503 optimized_layers.append(layer_info)504 optimized_layers[optimized_layer_indx].layer_num = optimized_layer_indx505 # Copy over506 self.layers = optimized_layers507 # Update the statuses508 self.analyze_tool_status()509 return True510 # Inject code into the token list511 def inject_gcode(self):512 # Inject code for all layers513 for layer in self.layers:514 layer.inject_gcode()515 # Generate report on the prime tower composition516 def print_report(self):517 # Dict with layer information518 num_layers_by_height = {}519 for layer in self.layers:520 if layer.layer_height not in num_layers_by_height:521 num_layers_by_height[layer.layer_height] = 1522 else:523 num_layers_by_height[layer.layer_height] += 1524 # Print info525 logger.info("Prime Tower Info :")526 logger.info(" - num layers : {layers_num}".format(layers_num = len(self.layers)))...
judgeAst.py
Source:judgeAst.py
1#!/usr/bin/pythin2#-*- coding: utf-8 -*-3import json4import os5from colorPrint import * #该头æ件ä¸å®ä¹äºè²å½©æ¾ç¤ºçä¿¡æ¯6import re7import subprocess8#ç¼åè·¯å¾9CACHE_PATH = "./cache/"10#注å
¥æéä¿¡æ¯åå¨è·¯å¾11INJECT_INFO_PATH = "./injectInfo/"12#注å
¥ä¿¡æ¯æºä»£ç é®å¼13SRC_KEY = "srcPos"14#å¸å°çå¼15BOOL_TRUE_FLAG = True16#fallbackæ å¿17FALLBACK_FLAG = "fallback"18#é¢å¤æ¿æ¢è¯å¥19INJECT_STATE = ".call.gas(2301).value"20#触åè°ç¨è¯å¥21CALL_CALL_STATE = "(\"\")"22class judgeAst:23 def __init__(self, _json, _sourceCode, _filename):24 self.cacheContractPath = "./cache/temp.sol"25 self.cacheFolder = "./cache/"26 self.json = _json27 self.filename = _filename28 self.sourceCode = _sourceCode29 def run(self):30 injectInfo = dict()31 injectInfo[SRC_KEY] = list()32 #1. ææææçfallbackå½æ°33 fallbackFuncAstList = list()34 for func in self.findASTNode(self.json, "name", "FunctionDefinition"):35 #è¦æ±å½æ°å®ç°36 if func["attributes"]["implemented"] == BOOL_TRUE_FLAG and func["attributes"]["kind"] == FALLBACK_FLAG:37 #æè·fallbackå½æ°38 fallbackFuncAstList.append(func)39 else:40 continue41 #2. è¿å
¥æ¯ä¸ªfallbackå½æ°ä¸ï¼æ¾å°transfer/send/call.valueè¯å¥42 expStatePosList = self.getExpStatePos()43 #æ¼æ¥åºæå
¥è¯å¥ï¼ç¶åè®°å½ä½ç½®44 for func in fallbackFuncAstList:45 for item in self.findASTNode(func, "name", "MemberAccess"):46 if item["attributes"]["member_name"] == "transfer" and item["attributes"]["type"] == "function (uint256)" and item["attributes"]["referencedDeclaration"] == None:47 sPos, ePos = self.srcToPos(item["src"])48 #è·å¾æ¥æ¶è½¬è´¦çå°å49 receiver = item["children"][0]50 receiverSpos, receiverEpos = self.srcToPos(receiver["src"])51 injectInfo[SRC_KEY].append([sPos, ePos, self.sourceCode[receiverSpos: receiverEpos] + INJECT_STATE])52 #[bug fix] transferè¯å¥éè¦å¨æåè¡¥å
è°ç¨è¯å¥53 #ç¡®å®transferè¯å¥ç»æä½ç½®54 for exp in expStatePosList:55 if exp[0] <= sPos and exp[1] >= ePos:56 #æ¾å°äºï¼è®°å½ä½ç½®åæå
¥è¯å¥57 injectInfo[SRC_KEY].append([exp[1], exp[1], CALL_CALL_STATE])58 else:59 continue60 #[bug fix] sendè¯å¥ä¸ææ61 '''62 if item["attributes"]["member_name"] == "send" and item["attributes"]["type"] == "function (uint256) returns (bool)" and item["attributes"]["referencedDeclaration"] == None:63 sPos, ePos = self.srcToPos(item["src"])64 receiver = item["children"][0]65 receiverSpos, receiverEpos = self.srcToPos(receiver["src"])66 injectInfo[SRC_KEY].append([sPos, ePos, self.sourceCode[receiverSpos: receiverEpos] + INJECT_STATE])67 '''68 if item["attributes"]["member_name"] == "value" and item["attributes"]["type"] == "function (uint256) pure returns (function (bytes memory) payable returns (bool,bytes memory))" and item["attributes"]["referencedDeclaration"] == None:69 if item["children"][0]["attributes"]["member_name"] == "call" and item["children"][0]["attributes"]["type"] == "function (bytes memory) payable returns (bool,bytes memory)":70 sPos, ePos = self.srcToPos(item["src"])71 receiver = item["children"][0]["children"][0]72 receiverSpos, receiverEpos = self.srcToPos(receiver["src"])73 injectInfo[SRC_KEY].append([sPos, ePos, self.sourceCode[receiverSpos: receiverEpos] + INJECT_STATE])74 else:75 continue76 if injectInfo[SRC_KEY]:77 self.storeInjectInfo(injectInfo)78 return True79 else:80 return False81 def getExpStatePos(self):82 expPosList = list()83 for exp in self.findASTNode(self.json, "name", "ExpressionStatement"):84 sPos, ePos = self.srcToPos(exp["src"])85 expPosList.append([sPos, ePos])86 return expPosList87 def cleanComment(self, _code):88 #使ç¨æ£å表达å¼ææåè¡åå¤è¡æ³¨é89 singleLinePattern = re.compile(r"(//)(.)+") #æåç¼è¯ï¼ä»¥æé«é度90 multipleLinePattern = re.compile(r"(/\*)(.)+?(\*/)")91 #è®°å½æ³¨éçä¸æ 92 indexList = list()93 for item in singleLinePattern.finditer(_code):94 indexList.append(item.span())95 for item in multipleLinePattern.finditer(_code, re.S):96 #å¤è¡æ³¨éï¼è¦å
许å¤è¡å¹é
97 indexList.append(item.span())98 #æ¼æ¥æ°ç»æ99 startIndedx = 0100 newCode = str()101 for item in indexList:102 newCode += _code[startIndedx: item[0]] #ä¸å
æ¬item[0]103 startIndedx = item[1] + 1 #å ä¸çç®çæ¯ä¸è¦çååºç尾巴104 newCode += _code[startIndedx:]105 return newCode106 def storeInjectInfo(self, _injectInfo):107 try:108 #ä¿åä¿¡æ¯109 with open(os.path.join(INJECT_INFO_PATH, self.filename.split(".")[0] + ".json"), "w", encoding = "utf-8") as f:110 json.dump(_injectInfo, f, indent = 1)111 #print("%s %s %s" % (info, self.filename + " target injected information...saved", end))112 except:113 #print("%s %s %s" % (bad, self.filename + " target injected information...failed", end))114 pass115 def findASTNode(self, _ast, _name, _value):116 queue = [_ast]117 result = list()118 literalList = list()119 while len(queue) > 0:120 data = queue.pop()121 for key in data:122 if key == _name and data[key] == _value:123 result.append(data)124 elif type(data[key]) == dict:125 queue.append(data[key])126 elif type(data[key]) == list:127 for item in data[key]:128 if type(item) == dict:129 queue.append(item)130 return result131 #ä¼ å
¥ï¼657:17:0132 #ä¼ åºï¼657, 674133 def srcToPos(self, _src):134 temp = _src.split(":")...
relaxedIK_mt_utils.py
Source:relaxedIK_mt_utils.py
...15def inject_subchain(x, x_subchain_idx, indices, subchains, numDOF):16 ret_subchains = copy.deepcopy(subchains)17 ret_subchains[x_subchain_idx] = x18 return glue_subchains(indices, ret_subchains, numDOF)19def inject_state(x, subchain, subchain_indices):20 x_ret = copy.deepcopy(x)21 for i, s in enumerate(subchain_indices):22 x_ret[s] = subchain[i]23 return x_ret24if __name__ == '__main__':25 x = [0.0, 2.0, 1.0, 3.0, 4.0, 5., 6., 7., 8.]26 indices = [[0,2], [1,3,4], [8,6,7,5]]27 subchains = [[0.0, 1.0], [2.0, 3.0, 4.0], [5., 6., 7., 8.]]28 print inject_state(x, [100.,100., 100., 100.], [0,1,4,5])...
Learn to execute automation testing from scratch with LambdaTest Learning Hub. Right from setting up the prerequisites to run your first automation test, to following best practices and diving deeper into advanced test scenarios. LambdaTest Learning Hubs compile a list of step-by-step guides to help you be proficient with different test automation frameworks i.e. Selenium, Cypress, TestNG etc.
You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.
Get 100 minutes of automation test minutes FREE!!