Andrew Moa Blog Site

PyCFF——一款基于Python的曲线拟合工具

最近工作中经常遇到需要通过散点数据拟合函数曲线的情况,比较典型的例子是通过换热器的压降拟合多孔介质参数,以及拟合流体介质的多项式密度。虽然相关的工作可以通过Excel、Origin等实现,但是操作繁琐而且支持的函数类型有限。这里使用Python编写了一个简单的工具包,通过numpy和scipy实现函数拟合功能,用PySide编写了用户界面,实现了从输入数据到输出拟合函数参数的功能,并且支持数据预测和自定义函数功能。

1. 软件简介

源码地址:PyCFF

1.1 用户界面

下面是软件的启动界面。软件界面通过PySide(Qt)实现。支持函数绘图功能,用户可以自定义绘图内容及输出保存图片。

c6219195050ac1b0866829f371239172.png

下面是软件的输入界面。输入数据通过表格的方式展示,用户通过指定列来选择要拟合函数的自变量(x)和因变量(y)。用户不仅可以在表格中手动输入数据,也可以通过Excel等表格软件粘贴输入,还可以通过粘贴替换列的方式快速输入大量数据。

1dbefea8b95c2677587b4f885c9df838.png

下面是软件的输出界面。软件预定义了一些常用函数,用户点击运算后在左侧表格中输出函数参数,并且在文本框中输出函数的完整表达式。用户可以自定义输出参数的精度和是否采用科学计数法,输出参数默认采用的是6位小数的科学计数法表示,满足大部分工程计算的需求。

98ecd6a60f59bed8a70596750a11fd4d.png

阅读时长1分钟
Andrew Moa

使用pyinstaller打包exe程序

使用qt动态链接库编译出来的可执行程序会依赖一大堆动态链接库文件,想要将本机上编写的程序发布到其他人的计算机上,就需要将依赖的动态链接库文件和可执行程序一起打包发布。打包发布的方法有很多,原理都是一样的,通过压缩程序将可执行程序和依赖文件一起打包压缩成单独的可执行文件,用户执行该可执行文件时自动解压并运行。

常见的打包方案有WinRAR1、7-Zip2等,通过压缩软件的自解压模块制作带脚本的自解压程序,但这些方案有一个共同的缺点,没办法传递命令行参数。本文提供新的思路,通过pyinstaller打包功能,实现qt程序打包,并且通过python实现命令行参数传递。

1. 示例程序

编写一个CGAL程序,调用qt显示面网格。下面的代码参考CGAL文档3并做了一些调整,在程序启动时开启对话框接收文件输入,也可以通过命令行传入网格文件。

#include <CGAL/Simple_cartesian.h>
#include <CGAL/Surface_mesh.h>
#include <CGAL/draw_surface_mesh.h>
#include <fstream>
#include <QApplication>
#include <QFileDialog>

typedef CGAL::Simple_cartesian<double> Kernel;
typedef Kernel::Point_3 Point;
typedef CGAL::Surface_mesh<Point> Mesh;

int main(int argc, char *argv[])
{
  QApplication app(argc, argv);
  const std::string filename = (argc > 1) ? argv[1] : QFileDialog::getOpenFileName(nullptr, "Open a mesh file", "", "Supported formats (*.off *.stl *.obj *.ply);;OFF format (*.off);;STL format (*.stl);;OBJ format (*.obj);;PLY format (*.ply)").toStdString();
  if (filename.empty())
    return EXIT_FAILURE;

  Mesh sm;
  if (!CGAL::IO::read_polygon_mesh(filename, sm))
  {
    if (filename.substr(filename.find_last_of(".") + 1) == "stl")
      std::cerr << "Invalid STL file: " << filename << std::endl;
    else if (filename.substr(filename.find_last_of(".") + 1) == "obj")
      std::cerr << "Invalid OBJ file: " << filename << std::endl;
    else if (filename.substr(filename.find_last_of(".") + 1) == "ply")
      std::cerr << "Invalid PLY file: " << filename << std::endl;
    else if (filename.substr(filename.find_last_of(".") + 1) == "off")
      std::cerr << "Invalid OFF file: " << filename << std::endl;
    else
      std::cerr << "Invalid file: " << filename << "(Unknown file format.)" << std::endl;
    return EXIT_FAILURE;
  }

  // Internal color property maps are used if they exist and are called
  // "v:color", "e:color" and "f:color".
  auto vcm =
      sm.add_property_map<Mesh::Vertex_index, CGAL::IO::Color>("v:color").first;
  auto ecm =
      sm.add_property_map<Mesh::Edge_index, CGAL::IO::Color>("e:color").first;
  auto fcm = sm.add_property_map<Mesh::Face_index>(
                   "f:color", CGAL::IO::white() /*default*/)
                 .first;

  for (auto v : vertices(sm))
  {
    if (v.idx() % 2)
    {
      put(vcm, v, CGAL::IO::black());
    }
    else
    {
      put(vcm, v, CGAL::IO::blue());
    }
  }

  for (auto e : edges(sm))
  {
    put(ecm, e, CGAL::IO::gray());
  }

  put(fcm, *(sm.faces().begin()), CGAL::IO::red());

  // Draw!
  CGAL::draw(sm);

  return EXIT_SUCCESS;
}

cmake配置文件CMakeLists.txt编写如下,输出的可执行文件名称包含文件夹名、工具链名称、编译器命名和版本等。

阅读时长3分钟
Andrew Moa

Ubuntu搭建软路由

把原先工作用的工作站改成了Ubuntu 24.04,需要通过Windows办公笔记本直连工作站进行操作。一开始在无线网下连接,上传下载数据太慢。后来通过有线网卡桥接,但有时候数据却不通过有线网卡传输反而走无线网卡。禁用笔记本无线网卡无法上网办公,也不是一个好办法。

1. 临时方案

工作站作为主机A,笔记本作为主机B,主机B通过有线共享主机A的无线网络1

1.1 查询当前设备网卡

查询两台机子的网卡信息

iwconfig

1.2 配置主机A的静态IP并作为软路由

可以通过GUI配置,主机A只需要设置IP地址和子网掩码信息。

sudo ifconfig eno1 192.168.68.1/24 # enol 为A主机内接的有线网卡名称
ifconfig # 查询效果

1.3 配置主机B的静态IP、网关和DNS

这一步也可以通过GUI配置,主机B需要配置IP地址、子网掩码,网关设置成主机A的IP地址,另外还需要设置DNS地址。

sudo ifconfig enp0s31f6 192.168.68.2/24 # enp0s31f6 为A主机有线网卡名称
sudo route add -net 0.0.0.0/0 gw 192.168.68.1 # 添加网关
sudo chmod +666 /etc/resolv.conf 
sudo echo "nameserver 114.114.114.114" > /etc/resolv.conf # 添加DNS

1.4 打开IP转发功能

Linux默认是禁止IP转发的,需要手动打开该功能。

sudo bash -c 'echo 1 > /proc/sys/net/ipv4/ip_forward'   # 打开ip转发

1.5 配置NAT

通过iptables设置路由转发。

sudo iptables -F
sudo iptables -P INPUT ACCEPT
sudo iptables -P FORWARD ACCEPT
sudo iptables -t nat -A POSTROUTING -o wlp0s20f3 -j MASQUERADE     # wlp0s20f3为A主机接外网的无线网卡

这个方案每次主机A重启都要重新按1.4、1.5设置一遍,非常不方便。

阅读时长1分钟
Andrew Moa