Finance利用 高斯溅射和 等值面提取技术可视化金融数据

一:主要的知识点

1、说明

本文只是教程内容的一小段,因博客字数限制,故进行拆分。主教程链接:vtk教程------逐行解析官网所有Python示例-CSDN博客

2、知识点纪要

本段代码主要涉及的有①高斯泼溅的意义及用法

二:代码及注释

python 复制代码
import vtkmodules.vtkRenderingOpenGL2
from vtkmodules.vtkCommonColor import vtkNamedColors
from vtkmodules.vtkCommonCore import vtkPoints, vtkFloatArray
from vtkmodules.vtkCommonDataModel import vtkUnstructuredGrid
from vtkmodules.vtkImagingHybrid import vtkGaussianSplatter
from vtkmodules.vtkFiltersCore import vtkContourFilter, vtkTubeFilter
from vtkmodules.vtkFiltersGeneral import vtkAxes
from vtkmodules.vtkRenderingCore import (
    vtkActor,
    vtkPolyDataMapper,
    vtkRenderWindow,
    vtkRenderWindowInteractor,
    vtkRenderer
)


def read_file(filename):
    res = {}

    with open(filename) as ifn:
        k = ''
        v = list()
        for line in ifn:
            cl = ' '.join(line.split()).split()
            if cl:
                if len(cl) == 2 and cl[0] == 'NUMBER_POINTS':
                    k = cl[0]
                    v = [int(cl[1])]
                    has_key = True
                    continue
                if len(cl) == 1 and not has_key:
                    has_key = True
                    k = cl[0]
                    v = list()
                else:
                    v += map(float, cl)
            else:
                if has_key:
                    # Normalise the data.
                    minimum = min(v)
                    maximum = max(v)
                    # Emulate the bug in the C++ code.
                    for i in v:
                        if i > minimum:
                            maximum = i
                    if maximum != minimum:
                        res[k] = list(map(lambda x: minimum + x / (maximum - minimum), v))
                    else:
                        res[k] = v
                    has_key = False
    return res


def make_dataset(filename, keys):
    res = read_file(filename)
    if res:
        newPts = vtkPoints()
        newScalars = vtkFloatArray()
        xyz = list(zip(res[keys[1]], res[keys[2]], res[keys[3]]))  # shape = 3188 * 3
        for i in range(0, res[keys[0]][0]):
            newPts.InsertPoint(i, xyz[i])
            newScalars.InsertValue(i, res[keys[4]][i])

        dataset = vtkUnstructuredGrid()
        dataset.SetPoints(newPts)
        dataset.GetPointData().SetScalars(newScalars)
        return dataset


def main():
    colors = vtkNamedColors()
    colors.SetColor("PopColor", [230, 230, 230, 255])

    fileName = "Data/financial.txt"
    keys = ['NUMBER_POINTS', 'MONTHLY_PAYMENT', 'INTEREST_RATE', 'LOAN_AMOUNT', 'TIME_LATE']

    dataSet = make_dataset(fileName, keys)

    """
    高斯泼溅 用于将离散的点云数据转换成连续的体数据(或图像)
    工作原理:
    想象一下你有一张纸,上面随机散落着一些点。你想用这些点来描绘出一片连续的区域密度。高斯溅射就是这么做的:
    高斯核(Gaussian Kernel): 想象在每一个输入数据点的位置,你放置了一个高斯钟形曲线(类似于正态分布的形状),这就是高斯核。
    溅射(Splatting): 这个高斯核就像一个"墨滴",它将自己的**值(密度或权重)**向周围区域扩散。离点越近,贡献的密度值越高;离点越远,贡献的值越低。
    累积求和: 在你设定的 3D 网格(或 2D 图像)中的每个位置(像素或体素),所有输入点的高斯核贡献的密度值都会被累加起来。
    最终输出:
    最终的输出是一个新的数据集(通常是 vtkImageData),它的值代表了原始点云在空间中的局部密度。数据点密集的地方,输出值就高;数据点稀疏的地方,输出值就低
    """
    popSplatter = vtkGaussianSplatter()
    popSplatter.SetInputData(dataSet)
    popSplatter.SetSampleDimensions(100, 100, 100)
    # SetRadius 设置高斯核半径
    popSplatter.SetRadius(.05)
    """
    ScalarWarpingOff/On  标量变形与否
    输入点的标量值(例如,颜色或温度)会用来缩放高斯核的高度。
    这使得高斯溅射不仅反映点的位置密度,还反映标量值的总和或平均分布
    """
    popSplatter.ScalarWarpingOff()

    popSurface = vtkContourFilter()
    popSurface.SetInputConnection(popSplatter.GetOutputPort())
    popSurface.SetValue(0, 0.01)

    popMapper = vtkPolyDataMapper()
    popMapper.SetInputConnection(popSurface.GetOutputPort())
    popMapper.ScalarVisibilityOff()

    popActor = vtkActor()
    popActor.SetMapper(popMapper)
    popActor.GetProperty().SetOpacity(0.3)
    popActor.GetProperty().SetColor(colors.GetColor3d('PopColor'))
    popSplatter.Update()

    lateSplatter = vtkGaussianSplatter()
    lateSplatter.SetInputData(dataSet)
    lateSplatter.SetSampleDimensions(50, 50, 50)
    lateSplatter.SetRadius(0.05)
    """
    SetScaleFactor 控制输出密度场的整体强度或大小
    当你调用 SetScaleFactor(value) 时,VTK 会执行以下操作:

    最终密度=高斯核贡献的总和×value
    如果 value > 1.0: 输出密度场的值会整体增大。这会使你提取等值面(Contour)时,更容易在较低的等值面值上获得一个更大的曲面。
    如果 value < 1.0: 输出密度场的值会整体减小。这使得密度场更"稀疏",你需要提取一个更低的值才能获得一个可见的曲面。
    逾期贷款只是总人口中的一个子集,点的数量要少得多。如果使用默认的 1.0 缩放因子,它们生成的密度场可能非常弱,难以提取出有意义的等值面。
    """
    lateSplatter.SetScaleFactor(0.005)

    lateSurface = vtkContourFilter()
    lateSurface.SetInputConnection(lateSplatter.GetOutputPort())
    lateSurface.SetValue(0, 0.01)

    lateMapper = vtkPolyDataMapper()
    lateMapper.SetInputConnection(lateSurface.GetOutputPort())
    lateMapper.ScalarVisibilityOff()

    lateActor = vtkActor()
    lateActor.SetMapper(lateMapper)
    lateActor.GetProperty().SetColor(colors.GetColor3d('Red'))

    bounds = popSplatter.GetOutput().GetBounds()

    axes = vtkAxes()
    # SetOrigin 设置原点坐标
    axes.SetOrigin(bounds[0], bounds[2], bounds[4])  # xmin,ymin, zmin
    # SetScaleFactor 设置坐标轴(vtkAxes)的长度
    axes.SetScaleFactor(popSplatter.GetOutput().GetLength() / 5)
    # axes.GetOutput()  -> PolyData

    axesTubes = vtkTubeFilter()
    axesTubes.SetInputConnection(axes.GetOutputPort())
    axesTubes.SetRadius(axes.GetScaleFactor() / 25.0)
    axesTubes.SetNumberOfSides(6)

    axesMapper = vtkPolyDataMapper()
    axesMapper.SetInputConnection(axesTubes.GetOutputPort())

    axesActor = vtkActor()
    axesActor.SetMapper(axesMapper)

    # Graphics stuff.
    renderer = vtkRenderer()

    renWin = vtkRenderWindow()
    renWin.AddRenderer(renderer)

    interactor = vtkRenderWindowInteractor()
    interactor.SetRenderWindow(renWin)

    # Set up the renderer.
    renderer.AddActor(lateActor)
    renderer.AddActor(axesActor)
    renderer.AddActor(popActor)
    renderer.SetBackground(colors.GetColor3d('Wheat'))
    renWin.SetSize(640, 480)
    renWin.SetWindowName('Finance')

    renderer.ResetCamera()
    renderer.GetActiveCamera().Dolly(1.3)
    renderer.ResetCameraClippingRange()

    # Interact with the data.
    renWin.Render()
    interactor.Start()

    print("")


if __name__ == '__main__':
    main()
相关推荐
Joseph 乔11 分钟前
【Python】卸载与重装
经验分享·python
归去来?13 分钟前
Python 常用优雅写法
开发语言·python
名字还没想好☜15 分钟前
Java 21 switch 模式匹配实战:sealed 接口 + record 替代 if-instanceof 链
java·人工智能·后端·python·spring
深蓝海拓15 分钟前
基于QtPy (PySide6) 的PLC-HMI工程实战记录(五)为当前动作画面的信号连接变量
网络·笔记·python·学习·pyqt
何以解忧,唯有..32 分钟前
Python 异常处理完全指南:从基础到高级实践
开发语言·前端·python
DLYSB_38 分钟前
让 PLC“开口说话”:基于 Modbus TCP 的声光语音告警设计与 Python 调试
python·网络协议·tcp/ip·报警灯
今日热点38 分钟前
微信小程序主体变更公证全流程实操解析:场景条件、材料规范、驳回避坑与Python校验脚本实现
python·微信小程序·小程序
O。O蛋黄酥啊39 分钟前
GraphRAG 和 LightRAG 详解与对比
人工智能·python·算法·rag·graphrag·lightrag
Buke..43 分钟前
【小程序逆向】某游快爆 AI 逆向 sign参数:AI 辅助分析与 MCP 工具链实战
前端·人工智能·爬虫·python·小程序·notepad++
一只旭宝1 小时前
预约系统版本2(pyhton+flask可视化版本)
服务器·数据库·c++·笔记·python·flask