Klarf 文件可视化工具

2023-11-15

1.技术框架

1.1 前端:

  • Vue3 网页版
  • Electron + Quasar 可生成 EXEAPK 等客户端
  • Element-Plus 控件
  • axios 跨域

1.2 后端:

  • Flask 提供接口

2. Web 版和客户端版

2.1 Web 版页面

在这里插入图片描述

2.2 客户端界面

在这里插入图片描述

2.3 使用流程

  • SenseTools-Klarf-Parser/data/test_file/ 路径下放入待可视化的 KLA 文件: 例,CPS3TwithoutReview.001.
  • 执行 klarf-parser/FlaskWeb.py ,启动 Flask 后端程序,Flask 调用 Process.py 进行 KLA 文件的解析,将 KLA 文件转换成 Json 格式。
  • Flask 将解析后的 Json 数据发送到 10086 端口。
  • 启动前端程序或者启动 exe 客户端软件,由前端或客户端向本地 10086 端口发送 Get 请求,获取 Json 数据。
  • 前端和客户端程序从获取到的 Json 数据中提取关键信息,在页面绘制缺陷示意图。

3. 后端

3.1 接口设计

  • Server Host: 127.0.0.1

  • Server Port: 10086

@app.route('/parse')
def parse():
    json_data = process()
    return json_data

访问 /parse 路径可以获取 KLA 文件转换的 Json 数据。

Json 数据如下所示:

{'sampling_coord': 
 '[{"x":-2.0,"y":0.0},{"x":-1.0,"y":-4.0},{"x":-1.0,"y":-3.0},{"x":-1.0,"y":-2.0},{"x":-1.0,"y":-1.0},{"x":-1.0,"y":0.0},{"x":-1.0,"y":1.0},{"x":-1.0,"y":2.0},{"x":0.0,"y":-4.0},{"x":0.0,"y":-3.0},{"x":0.0,"y":-2.0},{"x":0.0,"y":-1.0},{"x":0.0,"y":0.0},{"x":0.0,"y":1.0},{"x":0.0,"y":2.0},{"x":1.0,"y":-5.0},{"x":1.0,"y":-4.0},{"x":1.0,"y":-3.0},{"x":1.0,"y":-2.0},{"x":1.0,"y":-1.0},{"x":1.0,"y":0.0},{"x":1.0,"y":1.0},{"x":1.0,"y":2.0},{"x":1.0,"y":3.0},{"x":2.0,"y":-5.0},{"x":2.0,"y":-4.0},{"x":2.0,"y":-3.0},{"x":2.0,"y":-2.0},{"x":2.0,"y":-1.0},{"x":2.0,"y":0.0},{"x":2.0,"y":1.0},{"x":2.0,"y":2.0},{"x":2.0,"y":3.0},{"x":3.0,"y":-5.0},{"x":3.0,"y":-4.0},{"x":3.0,"y":-3.0},{"x":3.0,"y":-2.0},{"x":3.0,"y":-1.0},{"x":3.0,"y":0.0},{"x":3.0,"y":1.0},{"x":3.0,"y":2.0},{"x":3.0,"y":3.0},{"x":4.0,"y":-4.0},{"x":4.0,"y":-3.0},{"x":4.0,"y":-2.0},{"x":4.0,"y":-1.0},{"x":4.0,"y":0.0},{"x":4.0,"y":1.0},{"x":4.0,"y":2.0},{"x":5.0,"y":-4.0},{"x":5.0,"y":-3.0},{"x":5.0,"y":-2.0},{"x":5.0,"y":-1.0},{"x":5.0,"y":0.0},{"x":5.0,"y":1.0},{"x":5.0,"y":2.0},{"x":6.0,"y":0.0}]', 'die_pitch_x': 15299.4, 'die_pitch_y': 14399.7, 'sampling_edge': {"DEFECTID":26.0,"X":80399.5694359711,"Y":-31533.8008700403,"XREL":3902.5694359711,"YREL":11665.2991299597,"XINDEX":5.0,"YINDEX":-3.0,"XSIZE":13.612,"YSIZE":17.015,"DEFECTAREA":196.866953,"DSIZE":13.612,"CLASSNUMBER":49.0,"TEST":1.0,"IMAGECOUNT":26.0,"IMAGELIST":0.0},{"DEFECTID":27.0,"X":80454.0234144374,"Y":-31549.1160538724,"XREL":3957.0234144374,"YREL":11649.9839461276,"XINDEX":5.0,"YINDEX":-3.0,"XSIZE":34.03,"YSIZE":34.03,"DEFECTAREA":590.600859,"DSIZE":24.302,"CLASSNUMBER":49.0,"TEST":1.0,"IMAGECOUNT":27.0,"IMAGELIST":0.0},{"DEFECTID":28.0,"X":80508.4773929036,"Y":-31557.6244893347,"XREL":4011.4773929036,"YREL":11641.4755106653,"XINDEX":5.0,"YINDEX":-3.0,"XSIZE":17.015,"YSIZE":17.015,"DEFECTAREA":185.286544,"DSIZE":13.612,"CLASSNUMBER":49.0,"TEST":1.0,"IMAGECOUNT":28.0,"IMAGELIST":0.0},{"DEFECTID":29.0,"X":88339.8571464383,"Y":35346.7059481177,"XREL":11842.8571464383,"YREL":6547.3059481177,"XINDEX":5.0,"YINDEX":2.0,"XSIZE":10.209,"YSIZE":13.612,"DEFECTAREA":92.643272,"DSIZE":9.625,"CLASSNUMBER":49.0,"TEST":1.0,"IMAGECOUNT":29.0,"IMAGELIST":0.0},{"DEFECTID":30.0,"X":99546.267008286,"Y":11819.4874144129,"XREL":7749.867008286,"YREL":11819.4874144129,"XINDEX":6.0,"YINDEX":0.0,"XSIZE":37.433,"YSIZE":40.836,"DEFECTAREA":1076.978037,"DSIZE":32.817,"CLASSNUMBER":49.0,"TEST":1.0,"IMAGECOUNT":30.0,"IMAGELIST":0.0}]'}
....

3.2 后端函数库

########################################
#  解析 KLARF 文件函数库
########################################
import os
import time
import pandas as pd

def get_parsed_content(file_path):
    """
    :param file_path:
    :return:
    """

def klarf_parser(file_path, file_name):
    """
    :param file_path:
    :param file_name:
    :return:
    """

def klf_timestamp_parser(klf_str):
    """
    :param klf_str:
    :return:
    """

def find_klf_str_keyword_connect_result(klf_str, keyword):
    """
    :param klf_str:
    :param keyword:
    :return:
    """

def klf_tool_parser(klf_str):
    """
    :param klf_str:
    :return:
    """
    
def klf_waferid_and_img(klf_str):
    """
    :param klf_str:
    :return:
    """

def klf_batch_info_parser(klf_str, info_str):
    """
    :param klf_str:
    :param info_str:
    :return:
    """

def klf_sampling_coordinate_parser(klf_str, key_str):
    """
    :param klf_str:
    :param key_str:
    :return:
    """

def klf_defect_coordinate_parser(klf_str, waferID_list):
    """
    :param klf_str:
    :param waferID_list:
    :return:
    """

4. 前端

创建 Quasar 项目:

yarn create quasar

运行 Quasar 项目:

yarn quasar dev

Quasar 安装 axios:

yarn add axios

Quasar 安装 element-plus:

yarn add element-plus --save

src/boot/ 路径下创建 element-plus.js 文件:

// import something here
import { boot } from 'quasar/wrappers'
import ElementUI from 'element-plus'
import 'element-plus/dist/index.css'
export default boot(({ app }) => {
  // Set i18n instance on app

  app.use(ElementUI)
})
export { ElementUI }

src/pages/ 路径下创建 KlaParse.vue

<template>
  <div>
    <h1>Kla Parse Web Page</h1>
    <div>
      <el-button @click="get_data" type="success">解析</el-button>
      <br />
      <el-progress
          :text-inside="true"
          :stroke-width="24"
          :percentage=sta
          status="success"
      />
    </div>
    <br>
    <div>
      <el-button @click="draw" type="primary">画图</el-button>
    </div>
    <div>
      <h3 id="h31">Wafer Id: {{ this.wafer_id }}</h3>
      <h3 id="h32">Kla To Image</h3>
      <canvas id="defectmap" width = "500" height = "500" style="background-color:#fcfafa;"></canvas>
    </div>
  </div>
</template>

<script>
import axios from "axios";
import { ElMessage } from 'element-plus'

export default {
  name: "KlaParse",
  data() {
    return {
      count: 1,
      kla_content: [],
      wafer_id: null,
      sta: 0
    }
  },
  methods: {
    get_data() {
      axios({
        // url: "/api/parse",
        url: "http://127.0.0.1:10086/parse",
        method: 'get',
      }).then(res => {
        ElMessage({
          message: 'Congrats, this is a success message.',
          type: 'success',
        })
        this.sta = 100
        this.kla_content = res.data
      })
    },

    draw() {
      var sampling_coord = JSON.parse(this.kla_content['sampling_coord']);
      var defect_coord = JSON.parse(this.kla_content['defect_coord']);
      var sampling_edge = this.kla_content['sampling_edge'];
      var die_pitch_x = this.kla_content['die_pitch_x'];
      var die_pitch_y = this.kla_content['die_pitch_y'];
      var wafer_id = this.kla_content['waferID'];
      var recipe_id = this.kla_content['Recipe'];
      var lotid = this.kla_content['lotid'];
      var tool_id = this.kla_content['Tool_ID'];
      this.wafer_id = wafer_id
      const canvas = document.getElementById("defectmap");
      var map = canvas.getContext("2d");
      map.translate(0, 0);
      map.lineWidth = 0.05;

      for (var item in sampling_coord){
        var index_defy = parseInt(sampling_edge['def_yl']) + 1  - parseInt(sampling_coord[item]['y']);
        var index_defx = Math.abs(parseInt(sampling_edge['def_xl'])) + 1 + parseInt(sampling_coord[item]['x']);
        var x_pixel = parseFloat(die_pitch_x) / 352.73;
        var y_pixel = parseFloat(die_pitch_y) / 352.73;
        //draw die pitch
        map.strokeRect(index_defx * x_pixel, index_defy * y_pixel, x_pixel, y_pixel);
        map.save();
        for(var item_defect in Object.values(defect_coord)){
          if(defect_coord[item_defect]['XINDEX'] == sampling_coord[item]['x'] && defect_coord[item_defect]['YINDEX'] == sampling_coord[item]['y']){
            map.strokeStyle  = "#FF0000";
            map.lineWidth = 2
            map.strokeRect(index_defx * x_pixel + parseFloat(defect_coord[item_defect]['XREL'])/352.73, index_defy * y_pixel + y_pixel - parseFloat(defect_coord[item_defect]['YREL'])/352.73, 0.03, 0.02);
            map.restore();
          }
        }
      }
      var map_image = new Image();
      map_image.src =  canvas.toDataURL("image/png");
      var map_link = document.createElement("a");
      map_link.src = map_image;
      map_link.href = map_image.src;
      map_link.download = lotid + "-" + tool_id + "-" + recipe_id +"-"+ wafer_id;
      // map_link.click();
      // map.clearRect(0, 0, 500, 500);
      if(canvas.getContext) {
        var ctx = canvas.getContext('2d');
        ctx.drawImage(map_image, 0, 0, 500, 500);
      }
      // this.sta = 0;
    }
  }
}
</script>

<style scoped>
h1 {
  font-size: 40px;
  color: #26A69A;
  margin-left: 20px;
}

#h31 {
  font-size: 20px;
  margin-left: 20px;
}

#h32 {
  font-size: 20px;
  margin-left: 20px;
}

defectmap {
  color: #26A69A;
  margin-left: 20px;
}

.el-progress {
  width: 50%;
  margin-left: 20px;
}

.el-button {
  margin-bottom: 10px;
  margin-left: 20px;
}
</style>

4.1 Quasar 启动 Web Page

WebStorm 软件的 Terminal 中执行:

yarn quasar dev

在浏览器中输入:http://192.168.3.42:8080
在这里插入图片描述

4.2 Quasar 编译生成 .exe 文件

WebStorm 软件的 Terminal 中执行:

quasar build -m electron

quasar-project/dist/electron/klarf_tool-win32-x64/ 中生成 klarf_tool.exe 可执行文件,双击 exe 软件即可启动客户端页面。
在这里插入图片描述

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Klarf 文件可视化工具 的相关文章

  • Python中Decimal类型的澄清

    每个人都知道 或者至少 每个程序员都应该知道 http docs oracle com cd E19957 01 806 3568 ncg goldberg html 即使用float类型可能会导致精度错误 然而 在某些情况下 精确的解决方
  • Python - 将宽字符字符串从二进制文件转换为 Python unicode 字符串

    这是漫长的一天 我有点困惑 我正在读取一个包含大量宽字符字符串的二进制文件 我想将它们转储为 Python unicode 字符串 为了解压非字符串数据 我使用 struct 模块 但我不知道如何对字符串执行相同的操作 例如 阅读 系列 一
  • python 模拟第三方模块

    我正在尝试测试一些处理推文的类 我使用 Sixohsix twitter 来处理 Twitter API 我有一个类充当 Twitter 类的外观 我的想法是模拟实际的 Sixohsix 类 通过随机生成新推文或从数据库检索它们来模拟推文的
  • 如何使用 Plotly 中的直方图将所有离群值分入一个分箱?

    所以问题是 我可以在 Plotly 中绘制直方图 其中所有大于某个阈值的值都将被分组到一个箱中吗 所需的输出 但使用标准情节Histogram类我只能得到这个输出 import pandas as pd from plotly import
  • 通过列表理解压平列表列表

    我正在尝试使用 python 中的列表理解来展平列表 我的清单有点像 1 2 3 4 5 6 7 8 只是为了打印这个列表列表中的单个项目 我编写了这个函数 def flat listoflist for item in listoflis
  • Pandas 数据帧到 numpy 数组 [重复]

    这个问题在这里已经有答案了 我对 Python 很陌生 经验也很少 我已经设法通过复制 粘贴和替换我拥有的数据来使一些代码正常工作 但是我一直在寻找如何从数据框中选择数据 但无法理解这些示例并替换我自己的数据 总体目标 如果有人真的可以帮助
  • 使用 Python pandas 计算调整后的成本基础(股票买入/卖出的投资组合分析)

    我正在尝试对我的交易进行投资组合分析 并尝试计算调整后的成本基础价格 我几乎尝试了一切 但似乎没有任何效果 我能够计算调整后的数量 但无法获得调整后的购买价格有人可以帮忙吗 这是示例交易日志原始数据 import pandas as pd
  • python suds SOAP 请求中的名称空间前缀错误

    我使用 python suds 来实现客户端 并且在发送的 SOAP 标头中得到了错误的命名空间前缀 用于定义由element ref 在 wsdl 中 wsdl 正在引用数据类型 xsd 文件 请参见下文 问题出在函数上GetRecord
  • TensorFlow的./configure在哪里以及如何启用GPU支持?

    在我的 Ubuntu 上安装 TensorFlow 时 我想将 GPU 与 CUDA 结合使用 但我却停在了这一步官方教程 http www tensorflow org get started os setup md 这到底是哪里 con
  • 奇怪的 MySQL Python mod_wsgi 无法连接到 'localhost' (49) 上的 MySQL 服务器问题

    StackOverflow上也有类似的问题 但我还没有发现完全相同的情况 这是在使用 MySQL 的 OS X Leopard 机器上 一些起始信息 MySQL Server version 5 1 30 Apache 2 2 13 Uni
  • 首先对列表中最长的项目进行排序

    我正在使用 lambda 来修改排序的行为 sorted list key lambda item item lower len item 对包含元素的列表进行排序A1 A2 A3 A B1 B2 B3 B 结果是A A1 A2 A3 B
  • Pandas 根据 diff 列形成簇

    我正在尝试使用 Pandas 根据表示时间 以秒为单位 的列中的差异来消除数据框中的一些接近重复项 例如 import pandas as pd numpy as np df pd DataFrame 1200 1201 1233 1555
  • 无法在 osx-arm64 上安装 Python 3.7

    我正在尝试使用 Conda 创建一个带有 Python 3 7 的新环境 例如 conda create n qnn python 3 7 我收到以下错误 Collecting package metadata current repoda
  • 如何在 OSX 上安装 numpy 和 scipy?

    我是 Mac 新手 请耐心等待 我现在使用的是雪豹 10 6 4 我想安装numpy和scipy 所以我从他们的官方网站下载了python2 6 numpy和scipy dmg文件 但是 我在导入 numpy 时遇到问题 Library F
  • Tkinter - 浮动窗口 - 调整大小

    灵感来自this https stackoverflow com a 22424245 13629335问题 我想为我的根窗口编写自己的调整大小函数 但我刚刚注意到我的代码显示了一些性能问题 如果你快速调整它的大小 你会发现窗口没有像我希望
  • 在Python中按属性获取对象列表中的索引

    我有具有属性 id 的对象列表 我想找到具有特定 id 的对象的索引 我写了这样的东西 index 1 for i in range len my list if my list i id specific id index i break
  • 字典和数组作为类变量与实例变量

    这是赚取积分的简单方法 请解释以下内容 class C a b 0 c def init self self x def d self k v self x k v self a k v self b v self c append v d
  • 如何读取Python字节码?

    我很难理解 Python 的字节码及其dis module import dis def func x 1 dis dis func 上述代码在解释器中输入时会产生以下输出 0 LOAD CONST 1 1 3 STORE FAST 0 x
  • 从 Twitter API 2.0 获取 user.fields 时出现问题

    我想从 Twitter API 2 0 端点加载推文 并尝试获取标准字段 作者 文本 和一些扩展字段 尤其是 用户 字段 端点和参数的定义工作没有错误 在生成的 json 中 我只找到标准字段 但没有找到所需的 user fields 用户
  • 您可以使用关键字参数而不提供默认值吗?

    我习惯于在 Python 中使用这样的函数 方法定义 def my function arg1 None arg2 default do stuff here 如果我不供应arg1 or arg2 那么默认值None or default

随机推荐

  • tf好朋友之matplotlib的使用——subplot分格显示

    tf好朋友之matplotlib的使用 subplot分格显示 分格显示的方法 利用plt subplot2grid进行分格显示 利用gridspec GridSpec进行分格显示 应用示例 在学习matlab的时候 图像是可以分格显示的
  • 1032. 挖掘机技术哪家强(20)

    1032 挖掘机技术哪家强 20 时间限制 200 ms 内存限制 65536 kB 代码长度限制 8000 B 判题程序 Standard 作者 CHEN Yue 为了用事实说明挖掘机技术到底哪家强 PAT组织了一场挖掘机技能大赛 现请你
  • maven仓库中_remote.repositories的作用

    首先直接给结论 remote repositories的作用是当maven本地仓库缓存了jar pom的情况下修改了maven的配置文件 settings xml 后依然会去远程仓库获取 以org slf4j slf4j api 1 5 6
  • 科创板、香港主板、纳斯达克三地部门上市条件和要求

    转自 https zhuanlan zhihu com p 69144513 科创板 香港主板 纳斯达克三地部门上市条件和要求 发布于 2019 06 14
  • 一、创建型模式:工厂方法模式(Factory Method)

    请MM去麦当劳吃汉堡 不同的MM有不同的口味 要每个都记住是一件烦人的事情 我一般采用Factory Method模式 带着MM到服务员那儿 说 要一个汉堡 具体要什么样的汉堡呢 让MM直接跟服务员说就行了 定义 核心工厂类不再负责所有产品
  • MySQL-多表关联

    多表关联 多张数据表之间是可以有一定的关联关系 这种关联关系可以通过外键约束实现 多表的分类 一对一 一对多 多对多 一对一 一张表对应另一张表 适用场景 人和身份证 一个人只能有一个身份证 一个身份证只能对应一个人 建表原则 在任意一个表
  • python爬虫实战练手——————淘宝网站的爬取

    python爬虫是很好的数据分析手段 可以进行爬虫程序来进行爬取网站 下面是淘宝的爬取 淘宝搜索书包 然后得到以下的界面 注意到下面的分页 可以通过进行分页的改变来进行多页数据的爬取 爬取多页 这里用到了和重要的re库 也就是正则表达式库
  • Windows10下Linux子系统Ubuntu使用教程(8)——升级WSL2,及解决遇到的问题

    WSL 2 是 WSL 中体系结构的新版本 它更改 Linux 发行版与 Windows 交互的方式 WSL 2 的主要目标是提高文件系统性能并增加系统调用的完全兼容性 每个 Linux 发行版都可以作为 WSL 1 或 WSL 2 发行版
  • vue 获取服务端base64位图片之后的处理

    目录 Base64是什么 Base64可以在Url中传输吗 Base64是加密算法么 Base64的应用场景有哪些 Base64的优点 Base64的缺点 关于vue中img无法展示base64位图片的原因分析 Base64是什么 Base
  • CSS-选择器的基本用法

    目录 一 CSS的分类 1 行内样式 2 内部样式 3 外部样式 二 选择器是什么 三 选择器具体种类 1 类选择器 2 标签选择器 3 ID选择器 4 通配符选择器 一 CSS的分类 1 行内样式 通过 style 属性 来指定某个标签的
  • Java实现Token的生成与验证

    二 基于JWT的token认证实现 JWT JSON Web Token 其实token就是一段字符串 由三部分组成 Header Payload Signature 1 引入依赖
  • 爬虫之简单js逆向

    本次js逆向没有存在代码混淆 所以还是比较简单的 重要的就是js逆向的思路 目标网站https notice qb com detail noticeId 215让我们开始吧 进入网站后按F12 查看DOC中的 可以看出该网页一部分内容是异
  • vue3解读—reactivity响应式实现

    前言 Vue3 中引入了proxy进行数据劫持 而effect是响应式系统的核心 而响应式系统又是 vue3 中的核心 所以vue3的解读要从 effect 开始讲起 1 reactivity和effect的使用 目前vue3的各个模块都可
  • 蓝桥杯:基础练习 特殊的数字(java实现)

    问题描述 153是一个非常特殊的数 它等于它的每位数字的立方和 即153 111 555 333 编程求所有满足这种条件的三位十进制数 输出格式 按从小到大的顺序输出满足条件的三位十进制数 每个数占一行 public class Main
  • 2014阿里巴巴9月14北京校园招聘笔试及参考答案

    form http blog csdn net lingfengtengfei article details 12344511 from http blog csdn net lingfengtengfei article details
  • java实现根据pdf文件模板生成pdf文件

    一 如何制作pdf模板 1 首先创建template doc 2 根据doc文件制作pdf模板 3 将doc文件输出为pdf 文件 gt 输出为pdf 4 输出的pdf文件 5 使用Adobe Acrobat DC打开template pd
  • HTML+CSS炫酷效果(小伙伴赶紧收藏起来吧)

    制作不易 点赞加关注哦 目录 1 实现奥运徽效果 2 实现3D效果 3 翻开葵花宝典 4 实现漂浮文字 动图 5 手机充电特效 动态 6 滚动时针 7 立体相册 1 实现奥运徽效果 由于图片违规 就不给老铁发了哈 亲自试试呗 HTML如下
  • 对 Electron 架构的理解

    Electron 的架构可以分为三层 Chromium Node js 和应用程序层 Electron 是一种基于 Chromium 和 Node js 的开源框架 可以用于快速构建跨平台的桌面应用程序 Chromium 层 Chromiu
  • 【并发编程】CPU cache结构和缓存一致性(MESI协议)

    一 cache cpu cache已经发展到了三级缓存结构 基本上现在买的个人电脑都是L3结构 1 cache的意义 为什么需要CPU cache 因为CPU的频率太快了 快到主存跟不上 这样在处理器时钟周期内 CPU常常需要等待主存 浪费
  • Klarf 文件可视化工具

    1 技术框架 1 1 前端 Vue3 网页版 Electron Quasar 可生成 EXE APK 等客户端 Element Plus 控件 axios 跨域 1 2 后端 Flask 提供接口 2 Web 版和客户端版 2 1 Web