python - 如何创建在缩放时动态调整标记大小的 html 绘图

标签 python html matplotlib plotly-python mpld3

我创建了一个 Python使用 Matplotlib 生成条形图的脚本并将其转换为交互式HTML图形使用 mpld3 。该图表显示不同算法和字符串长度的平均哈希时间。但是,我希望通过在放大 HTML 中的图形时动态调整点大小来增强用户体验。文档。

这是脚本的一部分:

import hashlib
import random
import string
import time
import matplotlib.pyplot as plt
import multiprocessing
import os
from datetime import datetime
import mpld3

algorithms = ['sha1', 'sha256', 'sha3_256']
string_lengths = [10, 25, 50, 75, 100]
num_samples = 50000
random_seed = 42
random.seed(random_seed)
custom_colors = ['#1f77b4', '#FFD700', '#2ca02c']

def generate_random_string(length):
    characters = string.ascii_letters + string.digits
    return ''.join(random.choice(characters) for _ in range(length))

def hash_string(input_string, algorithm):
    hash_func = hashlib.new(algorithm)
    hash_func.update(input_string.encode())
    return hash_func.hexdigest()

def hash_and_measure_avg_time(args):
    algorithm, random_strings = args
    num_samples = len(random_strings)
    
    start_time = time.time_ns()
    
    [hash_string(s, algorithm) for s in random_strings]
    
    end_time = time.time_ns()

    total_time = end_time - start_time
    return total_time / num_samples

def main():
    for i in range(10):
        num_cpus = multiprocessing.cpu_count()
        cpu_count = os.cpu_count()

        print(f"\nUsing {num_cpus} CPU cores for analysis")
        print(f"Number of CPU cores available: {cpu_count}")

        random_strings = {}
        for length in string_lengths:
            random_strings[length] = [generate_random_string(length) for _ in range(num_samples)]

        results = {}
        timestamp = datetime.now().strftime("%m-%d-%Y-%H-%M-%S")
        results_folder = f"results_{timestamp}"
        os.makedirs(results_folder, exist_ok=True)

        for algorithm in algorithms:
            results[algorithm] = {}

            print(f"\nTesting hashing algorithm: {algorithm}")
            with multiprocessing.Pool(processes=num_cpus) as pool:
                args = [(algorithm, random_strings[length]) for length in string_lengths]
                results_list = pool.map(hash_and_measure_avg_time, args)

            for length, result in zip(string_lengths, results_list):
                results[algorithm][length] = result

            time.sleep(1)

        plt.figure(figsize=(10, 6))
        for i, (algorithm, avg_times) in enumerate(results.items()):
            avg_times = [avg_times[length] for length in string_lengths]
            plt.plot(
                string_lengths,
                avg_times,
                marker='o',
                markersize=4,
                label=algorithm,
                color=custom_colors[i]
            )

        plt.title('Average Hashing Time vs. String Length')
        plt.xlabel('String Length')
        plt.ylabel('Average Hashing Time (ns)')
        plt.legend()
        plt.grid(True)

        interactive_plot = mpld3.fig_to_html(plt.gcf())
        plot_filename = f"c_result_{timestamp}.html"
        with open(os.path.join(results_folder, plot_filename), 'w') as html_file:
            html_file.write(interactive_plot)

if __name__ == "__main__":
    print("\n----- Welcome to the Hashing Performance Benchmark -----")
    main()

就目前而言,图表显示代表数据点的点,但在 HTML 图形中放大或缩小时,它们的大小保持不变。 我想让点的大小根据缩放级别动态变化,这样当我放大时,点看起来更小,当我缩小时,它们看起来更大。

如果我放大得足够大,标记就会停止缩小并保持“巨大”。有没有办法改变它并使其继续动态减小直到最大缩放级别?

无缩放

enter image description here

带缩放

enter image description here

最大缩放级别

enter image description here

最佳答案

嘿,Olla,据我所知,由于 mpld3 库的限制,在放大或缩小 HTML 图形时,标记不会动态更改其大小。我不知道它是否适合您的项目,但您可以使用 Plotly 库而不是 matplotlibmpld3。这样,您就可以根据缩放级别实现动态标记大小变化,并使其在高缩放级别和许多其他功能的情况下继续减小。

import hashlib
import random
import string
import time
import multiprocessing
import os
from datetime import datetime
import plotly.graph_objects as go

algorithms = ['sha1', 'sha256', 'sha3_256']
string_lengths = [1, 10, 25, 50, 75]
num_samples = 50000
random_seed = 42
random.seed(random_seed)
custom_colors = ['#1f77b4', '#FFD700', '#2ca02c']

def generate_random_string(length):
    characters = string.ascii_letters + string.digits
    return ''.join(random.choice(characters) for _ in range(length))

def hash_string(input_string, algorithm):
    hash_func = hashlib.new(algorithm)
    hash_func.update(input_string.encode())
    return hash_func.hexdigest()

def hash_and_measure_avg_time(args):
    algorithm, random_strings = args
    num_samples = len(random_strings)
    
    start_time = time.time_ns()
    
    [hash_string(s, algorithm) for s in random_strings]
    
    end_time = time.time_ns()

    total_time = end_time - start_time
    return total_time / num_samples

def main():
    for i in range(10):
        num_cpus = multiprocessing.cpu_count()
        cpu_count = os.cpu_count()

        print(f"\nUsing {num_cpus} CPU cores for analysis")
        print(f"Number of CPU cores available: {cpu_count}")

        random_strings = {}
        for length in string_lengths:
            random_strings[length] = [generate_random_string(length) for _ in range(num_samples)]

        results = {}
        timestamp = datetime.now().strftime("%m-%d-%Y-%H-%M-%S")
        results_folder = f"results_{timestamp}"
        os.makedirs(results_folder, exist_ok=True)

        for algorithm in algorithms:
            results[algorithm] = {}

            print(f"\nTesting hashing algorithm: {algorithm}")
            with multiprocessing.Pool(processes=num_cpus) as pool:
                args = [(algorithm, random_strings[length]) for length in string_lengths]
                results_list = pool.map(hash_and_measure_avg_time, args)

            for length, result in zip(string_lengths, results_list):
                results[algorithm][length] = result

            time.sleep(1)

        # Create a Plotly scatter plot
        fig = go.Figure()

        for algorithm in algorithms:
            avg_times = [results[algorithm][length] for length in string_lengths]
            fig.add_trace(go.Scatter(x=string_lengths, y=avg_times, mode='markers', name=algorithm, marker=dict(size=4, color=custom_colors[algorithms.index(algorithm)])))

        # Add lines between the dots
        for i in range(1, len(string_lengths)):
            for algorithm in algorithms:
                x = string_lengths
                y = [results[algorithm][length] for length in x]
                fig.add_trace(go.Scatter(x=x, y=y, mode='lines', name=f'{algorithm} Lines', line=dict(color=custom_colors[algorithms.index(algorithm)], dash='dot')))
        
        # Customize the layout
        fig.update_layout(title='Average Hashing Time vs. String Length', xaxis_title='String Length', yaxis_title='Average Hashing Time (ns)', legend_title='Algorithm')
        fig.update_xaxes(type='log')

        # Save the interactive plot as an HTML file
        html_file = os.path.join(results_folder, f"c_result_{timestamp}.html")
        fig.write_html(html_file)

if __name__ == "__main__":
    print("\n----- Welcome to the Hashing Performance Benchmark -----")
    main()

关于python - 如何创建在缩放时动态调整标记大小的 html 绘图,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/77288859/

相关文章:

python - matplotlib funcanimation 更新函数被第一个参数调用两次

python - 如何将一个热图堆叠在另一个热图之上

python - 如何仅设置 pandas 数据框最后一行的样式?

python - requests.Session() 每次创建不同的 session 。如何重复利用?

python循环并为列的每个值创建新的数据框

javascript - 无法在 Javascript 中使用 getAttribute() 从表中检索数据

javascript - 如何将此 jQuery 代码转换为 AngularJS 代码?

python - SQLAlchemy 查询结果超时

css - div 100% 高度在屏幕中央

python - 绘制的图少于 matplotlib 子图中指定的图