From 15062d88849d7daf9a92418972cd0ab69c909917 Mon Sep 17 00:00:00 2001 From: Tibo De Peuter Date: Thu, 18 Dec 2025 16:06:26 +0100 Subject: [PATCH] feat: Graphs checkpoint --- pyproject.toml | 2 + results/make_graphs.py | 289 ++++++++++++++++++++++++++++++++++++++- results/measurements.csv | 49 +++++++ uv.lock | 117 ++++++++++++++++ 4 files changed, 453 insertions(+), 4 deletions(-) create mode 100644 results/measurements.csv diff --git a/pyproject.toml b/pyproject.toml index 96c0308..1393dc1 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -11,6 +11,8 @@ dependencies = [ "arithmeticencodingpython", "pandas-stubs==2.3.3.251201", "seaborn>=0.13.2", + "scipy>=1.16.3", + "scipy-stubs==1.16.3.3", ] [project.optional-dependencies] diff --git a/results/make_graphs.py b/results/make_graphs.py index f02fe24..934d22b 100644 --- a/results/make_graphs.py +++ b/results/make_graphs.py @@ -1,9 +1,290 @@ -import pandas as pd +import os + import matplotlib.pyplot as plt -import seaborn as sns import numpy as np +import pandas as pd +import scipy +import seaborn as sns +from matplotlib.figure import Figure + +ALGORITHM_COL = 'compressor' +LABEL_COL = 'label' +CONTEXT_COL = 'context_size' +INPUT_SIZE_COL = 'input_size' +OUTPUT_SIZE_COL = 'compressed_size' +COMPRESS_TIME_COL = 'compression_time' +DECOMPRESS_TIME_COL = 'decompression_time' +RATE_COL = 'compression_ratio' +DISTORTION_COL = 'mse_loss' + + +def original_v_compressed_filesize( + df: pd.DataFrame, + unique_labels: list[str], + palette_dict, + markers_dict +) -> Figure: + """The "rate" graph""" + plt.figure() + + break_point = 0.1 + + ax_small, ax_large = split_graph(df, INPUT_SIZE_COL, 'Input size (MB)', + OUTPUT_SIZE_COL, 'Compressed size (log, MB)', + break_point, 'Compressor', 'upper left', LABEL_COL, + unique_labels, palette_dict, markers_dict) + + # Add Baseline (y=x) + df_small, df_large = df[df[INPUT_SIZE_COL] < break_point], df[df[INPUT_SIZE_COL] > break_point] + baseline_label = 'Compression ratio 1.0' + baseline_alpha = 0.5 + min_xy, max_xy = df_small[INPUT_SIZE_COL].min(), df_small[INPUT_SIZE_COL].max() + ax_small.plot([min_xy, max_xy], [min_xy, max_xy], + color='gray', linestyle='--', label=baseline_label, alpha=baseline_alpha) + min_xy, max_xy = df_large[INPUT_SIZE_COL].min(), df_large[INPUT_SIZE_COL].max() + ax_large.plot([min_xy, max_xy], [min_xy, max_xy], + color='gray', linestyle='--', label=baseline_label, alpha=baseline_alpha) + + plt.yscale('log') + + return plt.gcf() + + +def filesize_v_compression_time( + df: pd.DataFrame, + unique_labels: list[str], + palette_dict, + markers_dict +) -> Figure: + """The "execution time" graph""" + plt.figure() + + split_graph(df, INPUT_SIZE_COL, 'Input size (MB)', + COMPRESS_TIME_COL, 'Compression time (log, s)', + 0.1, 'Compressor', 'center left', LABEL_COL, + unique_labels, palette_dict, markers_dict) + + plt.yscale('log') + + return plt.gcf() + + +def filesize_v_decompression_time( + df: pd.DataFrame, + unique_labels: list[str], + palette_dict, + markers_dict +) -> Figure: + """The "execution time" graph""" + plt.figure() + + split_graph(df, INPUT_SIZE_COL, 'Input size (MB)', + DECOMPRESS_TIME_COL, 'Decompression time (log, s)', + 0.1, 'Compressor', 'center left', LABEL_COL, + unique_labels, palette_dict, markers_dict) + + plt.yscale('log') + + return plt.gcf() + + +def split_graph( + df, x, x_axis_label, y, y_axis_label, + break_point, legend_title, legend_loc, hue, unique_labels, palette_dict, markers_dict +) -> tuple: + df = df.sort_values(by=x) + + f, (ax_left, ax_right) = plt.subplots(1, 2, sharey=True, figsize=(10, 5)) + + df_left = df[df[x] < break_point] + sns.scatterplot( + data=df_left, + x=x, + y=y, + ax=ax_left, + hue=hue, + hue_order=unique_labels, + palette=palette_dict, + style=hue, + style_order=unique_labels, + markers=markers_dict + ) + ax_left.set_xlabel('') + + df_right = df[df[x] > break_point] + sns.scatterplot( + data=df_right, + x=x, + y=y, + ax=ax_right, + hue=hue, + hue_order=unique_labels, + palette=palette_dict, + style=hue, + style_order=unique_labels, + markers=markers_dict + ) + ax_right.set_xlabel('') + ax_right.set_ylabel('') + + # Combine both plots into one + ax_left.spines['right'].set_visible(False) + ax_right.spines['left'].set_visible(False) + ax_right.yaxis.tick_right() + ax_right.tick_params(labelright=False) + ax_right.yaxis.set_ticks_position('none') + + # Add diagonal slash lines to indicate the break (with help from Gemini) + d = .015 # proportion of vertical to horizontal extent of the slanted line + kwargs = dict(transform=ax_left.transAxes, color='k', clip_on=False) + ax_left.plot((1 - d, 1 + d), (-d, +d), **kwargs) # Top-right diagonal + ax_left.plot((1 - d, 1 + d), (1 - d, 1 + d), **kwargs) # Bottom-right diagonal + + kwargs.update(transform=ax_right.transAxes) # Switch to the other axes + ax_right.plot((-d, +d), (1 - d, 1 + d), **kwargs) # Top-left diagonal + ax_right.plot((-d, +d), (-d, +d), **kwargs) # Bottom-left diagonal + + # Fix legends + handles_left, labels_left = ax_left.get_legend_handles_labels() + handles_right, labels_right = ax_right.get_legend_handles_labels() + unique_legend = dict(zip(labels_left + labels_right, handles_left + handles_right)) + ax_left.get_legend().remove() + ax_right.get_legend().remove() + ax_left.legend(unique_legend.values(), unique_legend.keys(), title=legend_title, loc=legend_loc) + + f.text(0.5, 0, x_axis_label, ha='center', va='center') + ax_left.set_ylabel(y_axis_label) + + ax_left.grid(True) + ax_right.grid(True) + + plt.tight_layout() + return ax_left, ax_right + + +def compression_v_mse_scatter(df: pd.DataFrame) -> Figure: + """The "distortion" graph""" + plt.figure() + + sns.scatterplot( + data=df, + x=RATE_COL, + y=DISTORTION_COL + ) + + plt.xscale('log') + plt.xlabel('Compression ratio (log)') + + # TODO This does not work properly + + plt.yscale('log') + plt.ylabel('MSE (log)') + + return plt.gcf() + + +def compression_ratios(df: pd.DataFrame) -> Figure: + """The "distortion" graph""" + plt.figure() + + fig, ax = plt.subplots() + sns.boxplot( + data=df, + x=RATE_COL, + y=LABEL_COL, + ax=ax + ) + + ax.set_xlabel('Compression ratio') + ax.set_ylabel('') + + ax.grid(True) + + return plt.gcf() + + +def generate( + df: pd.DataFrame, unique_labels, palette_dict, markers_dict, + tgt_dir: str, dpi: int = 300 +) -> None: + """Generate all the plots""" + # Make plots + + original_v_compressed_filesize(df, unique_labels, palette_dict, markers_dict).savefig( + os.path.join(tgt_dir, 'original_v_compressed_filesize.png'), + bbox_inches='tight', + dpi=dpi + ) + + filesize_v_compression_time(df, unique_labels, palette_dict, markers_dict).savefig( + os.path.join(tgt_dir, 'filesize_v_compression_time.png'), + bbox_inches='tight', + dpi=dpi + ) + filesize_v_decompression_time(df, unique_labels, palette_dict, markers_dict).savefig( + os.path.join(tgt_dir, 'filesize_v_decompression_time.png'), + bbox_inches='tight', + dpi=dpi + ) + + # compression_v_mse_scatter(df).savefig(os.path.join(tgt_dir, 'compression_v_mse.png'), bbox_inches='tight') + compression_ratios(df).savefig(os.path.join(tgt_dir, 'compression_ratios.png'), bbox_inches='tight') + + +def setup(tgt_dir): + # Create the targ directory if it does not exist + os.makedirs(tgt_dir, exist_ok=True) + + # Prepare matplotlib for use with LaTeX (makes it look less out of place, less Pythonesque) + params = {'text.usetex': True, + 'font.size': 11, + 'font.family': 'serif', + } + plt.rcParams.update(params) + + +def preprocessing(df: pd.DataFrame) -> tuple: + # Convert byts to MB + df[INPUT_SIZE_COL] /= 1e6 + df[OUTPUT_SIZE_COL] /= 1e6 + + # Convert ns to s + df[COMPRESS_TIME_COL] /= 1e9 + + # Add labels to differentiate between algorithms with context lengths + def create_label(row): + compressor = row[ALGORITHM_COL] + return compressor if pd.isna(row[CONTEXT_COL]) else f"{compressor} ($L = {int(row[CONTEXT_COL])}$)" + + df[LABEL_COL] = df.apply(create_label, axis=1) + + # Add the compression ratio + df[RATE_COL] = df[INPUT_SIZE_COL] / df[OUTPUT_SIZE_COL] + + # Identify all categories upfront + unique_labels = sorted(df[LABEL_COL].unique()) + n_labels = len(unique_labels) + + # Create fixed palette and marker mapping + palette_dict = dict(zip(unique_labels, sns.color_palette("tab10", n_labels))) + markers_dict = dict(zip(unique_labels, ['x', '+', '1', '2', '3', '4'])) + + return df, unique_labels, palette_dict, markers_dict + + +def main(): + """Load the data and generate the plots.""" + df = pd.read_csv("measurements.csv") + + tgt_dir = "figures" + setup(tgt_dir) + generate(*preprocessing(df), tgt_dir=tgt_dir, dpi=150) + if __name__ == "__main__": + main() + exit() + # read in the csv df = pd.read_csv("compression_results.csv") @@ -43,7 +324,8 @@ if __name__ == "__main__": plt.xlabel("file size [MB]") plt.ylabel("Time [s]") plt.yscale("log") - plt.legend([f"{style}, {c_type}" for style, c_type in zip(["Solid", "Dashed"], ["compression", "decompression"])]) + plt.legend( + [f"{style}, {c_type}" for style, c_type in zip(["Solid", "Dashed"], ["compression", "decompression"])]) plt.tight_layout() plt.savefig(f"./graphs/{model_type}_{dataset_type}_execution_time.png") @@ -60,7 +342,6 @@ if __name__ == "__main__": plt.legend() plt.savefig(f"./graphs/{model_type}_{dataset_type}_compression_ratio.png") - # if model_type == "cnn": # import numpy as np # diff --git a/results/measurements.csv b/results/measurements.csv new file mode 100644 index 0000000..64037ec --- /dev/null +++ b/results/measurements.csv @@ -0,0 +1,49 @@ +compressor,training_dataset,context_size,input_filename,input_size,compressed_size,compression_time,decompressed_size,decompression_time,mse_loss +gzip,,,genome.fna,4699745,1424004,.681197994,4699745,.015465955,0.0 +gzip,,,genome_large.fna,23498433,7118154,3.384480370,23498433,.067414798,0.0 +gzip,,,genome_small.fna,1367,589,.001937446,1367,.001983156,0.0 +gzip,,,genome_xlarge.fna,46996793,14235842,6.775190783,46996793,.131633333,0.0 +gzip,,,genome_xsmall.fna,1043,475,.002007016,1043,.002012775,0.0 +gzip,,,genome_xxsmall.fna,800,393,.002071485,800,.001958195,0.0 +gzip,,,text_large.txt,12977332,4770044,.613155078,12977332,.043915520,0.0 +gzip,,,text_small.txt,1022,590,.002070305,1022,.001903226,0.0 +gzip,,,text.txt,6488666,2385264,.308393934,6488666,.023656716,0.0 +gzip,,,text_xlarge.txt,25954664,9539638,1.229028819,25954664,.085925486,0.0 +gzip,,,text_xsmall.txt,825,473,.002110205,825,.001980535,0.0 +gzip,,,text_xxsmall.txt,492,325,.001867306,492,.002114055,0.0 +LZ4,,,genome.fna,4699745,2655438,.012701161,4699745,.009190410,0.0 +LZ4,,,genome_large.fna,23498433,13275544,.020719873,23498433,.025022334,0.0 +LZ4,,,genome_small.fna,1367,1041,.001883076,1367,.002144425,0.0 +LZ4,,,genome_xlarge.fna,46996793,26551229,.031734579,46996793,.043495412,0.0 +LZ4,,,genome_xsmall.fna,1043,814,.001954316,1043,.002085566,0.0 +LZ4,,,genome_xxsmall.fna,800,641,.001893416,800,.001943666,0.0 +LZ4,,,text_large.txt,12977332,7879136,.017927300,12977332,.015065196,0.0 +LZ4,,,text_small.txt,1022,857,.001967146,1022,.002040285,0.0 +LZ4,,,text.txt,6488666,3939378,.014891266,6488666,.009709618,0.0 +LZ4,,,text_xlarge.txt,25954664,15758785,.023613977,25954664,.023486747,0.0 +LZ4,,,text_xsmall.txt,825,678,.001757717,825,.002191075,0.0 +LZ4,,,text_xxsmall.txt,492,438,.001869646,492,.002134206,0.0 +Autoencoder,genome,256,genome.fna,4699745,4259288,636915773,,27887947,83.62875366210938 +Autoencoder,genome,256,genome_large.fna,23498433,21295512,1932602305,,7778175,83.59369659423828 +Autoencoder,genome,256,genome_xlarge.fna,46996793,42591024,3850901316,,10996509,83.58621215820312 +Autoencoder,genome,128,genome.fna,4699745,9399552,390656081,,5804539,83.01229095458984 +Autoencoder,genome,128,genome_large.fna,23498433,46996992,1932561312,,10575739,83.01190185546875 +Autoencoder,genome,128,genome_xlarge.fna,46996793,93993728,3873777067,,18670984,83.00253295898438 +Autoencoder,enwik9,256,text.txt,6488666,6184668,551986635,,10536259,786.6799926757812 +Autoencoder,enwik9,256,text_large.txt,12977332,12369092,1065897991,,5763879,786.6173706054688 +Autoencoder,enwik9,256,text_xlarge.txt,25954664,24738184,2139223055,,8369164,786.6337890625 +Autoencoder,enwik9,128,text.txt,6488666,12774636,545577194,,20624030,206.2792510986328 +Autoencoder,enwik9,128,text_large.txt,12977332,25549272,1073396133,,60871642,206.24131774902344 +Autoencoder,enwik9,128,text_xlarge.txt,25954664,51098292,2145601924,,59481825,206.33023071289062 +CNN,genome,256,genome_small.fna,1367,1743,1029290599,,890595665,0.0 +CNN,genome,256,genome_xsmall.fna,1043,1343,686878467,,683701323,0.0 +CNN,genome,256,genome_xxsmall.fna,800,1038,531354486,,527072394,0.0 +CNN,genome,128,genome_small.fna,1367,1682,829554150,,851934528,0.0 +CNN,genome,128,genome_xsmall.fna,1043,1300,654742547,,637221301,0.0 +CNN,genome,128,genome_xxsmall.fna,800,1006,483840337,,488870786,0.0 +CNN,enwik9,256,text_small.txt,1022,1561,693378115,,671294958,0.0 +CNN,enwik9,256,text_xsmall.txt,825,1268,550333502,,550062973,0.0 +CNN,enwik9,256,text_xxsmall.txt,492,790,333745012,,332073466,0.0 +CNN,enwik9,128,text_small.txt,1022,1129,629310179,,621317553,0.0 +CNN,enwik9,128,text_xsmall.txt,825,882,504538600,,504907940,0.0 +CNN,enwik9,128,text_xxsmall.txt,492,571,305443187,,308964670,0.0 diff --git a/uv.lock b/uv.lock index b6f68cf..7d04481 100644 --- a/uv.lock +++ b/uv.lock @@ -1385,6 +1385,18 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/2d/ee/346fa473e666fe14c52fcdd19ec2424157290a032d4c41f98127bfb31ac7/numpy-2.3.5-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:f16417ec91f12f814b10bafe79ef77e70113a2f5f7018640e7425ff979253425", size = 12967213, upload-time = "2025-11-16T22:52:39.38Z" }, ] +[[package]] +name = "numpy-typing-compat" +version = "20251206.2.3" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "numpy" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/77/83/dd90774d6685664cbe5525645a50c4e6c7454207aee552918790e879137f/numpy_typing_compat-20251206.2.3.tar.gz", hash = "sha256:18e00e0f4f2040fe98574890248848c7c6831a975562794da186cf4f3c90b935", size = 5009, upload-time = "2025-12-06T20:02:04.177Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/48/6f/dde8e2a79a3b6cbc31bc1037c1a1dbc07c90d52d946851bd7cba67e730a8/numpy_typing_compat-20251206.2.3-py3-none-any.whl", hash = "sha256:bfa2e4c4945413e84552cbd34a6d368c88a06a54a896e77ced760521b08f0f61", size = 6300, upload-time = "2025-12-06T20:01:56.664Z" }, +] + [[package]] name = "nvidia-cublas-cu12" version = "12.8.4.1" @@ -1550,6 +1562,24 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/7f/12/cba81286cbaf0f0c3f0473846cfd992cb240bdcea816bf2ef7de8ed0f744/optuna-4.5.0-py3-none-any.whl", hash = "sha256:5b8a783e84e448b0742501bc27195344a28d2c77bd2feef5b558544d954851b0", size = 400872, upload-time = "2025-08-18T06:49:20.697Z" }, ] +[[package]] +name = "optype" +version = "0.15.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "typing-extensions", marker = "python_full_version < '3.13'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/d7/93/6b9e43138ce36fbad134bd1a50460a7bbda61105b5a964e4cf773fe4d845/optype-0.15.0.tar.gz", hash = "sha256:457d6ca9e7da19967ec16d42bdf94e240b33b5d70a56fbbf5b427e5ea39cf41e", size = 99978, upload-time = "2025-12-08T12:32:41.422Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/07/8b/93f6c496fc5da062fd7e7c4745b5a8dd09b7b576c626075844fe97951a7d/optype-0.15.0-py3-none-any.whl", hash = "sha256:caba40ece9ea39b499fa76c036a82e0d452a432dd4dd3e8e0d30892be2e8c76c", size = 88716, upload-time = "2025-12-08T12:32:39.669Z" }, +] + +[package.optional-dependencies] +numpy = [ + { name = "numpy" }, + { name = "numpy-typing-compat" }, +] + [[package]] name = "packaging" version = "25.0" @@ -1732,6 +1762,8 @@ dependencies = [ { name = "fsspec" }, { name = "lorem" }, { name = "pandas-stubs" }, + { name = "scipy" }, + { name = "scipy-stubs" }, { name = "seaborn" }, ] @@ -1763,6 +1795,8 @@ requires-dist = [ { name = "optuna", marker = "extra == 'dev'", specifier = "==4.5.0" }, { name = "pandas-stubs", specifier = "==2.3.3.251201" }, { name = "regex", marker = "extra == 'dataset'", specifier = ">=2025.11.3" }, + { name = "scipy", specifier = ">=1.16.3" }, + { name = "scipy-stubs", specifier = "==1.16.3.3" }, { name = "seaborn", specifier = ">=0.13.2" }, { name = "torch", marker = "extra == 'dev'", specifier = "==2.9.0" }, { name = "torchdata", marker = "extra == 'dev'", specifier = "==0.7.1" }, @@ -2133,6 +2167,89 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/25/7a/b0178788f8dc6cafce37a212c99565fa1fe7872c70c6c9c1e1a372d9d88f/rich-14.2.0-py3-none-any.whl", hash = "sha256:76bc51fe2e57d2b1be1f96c524b890b816e334ab4c1e45888799bfaab0021edd", size = 243393, upload-time = "2025-10-09T14:16:51.245Z" }, ] +[[package]] +name = "scipy" +version = "1.16.3" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "numpy" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/0a/ca/d8ace4f98322d01abcd52d381134344bf7b431eba7ed8b42bdea5a3c2ac9/scipy-1.16.3.tar.gz", hash = "sha256:01e87659402762f43bd2fee13370553a17ada367d42e7487800bf2916535aecb", size = 30597883, upload-time = "2025-10-28T17:38:54.068Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/9b/5f/6f37d7439de1455ce9c5a556b8d1db0979f03a796c030bafdf08d35b7bf9/scipy-1.16.3-cp311-cp311-macosx_10_14_x86_64.whl", hash = "sha256:40be6cf99e68b6c4321e9f8782e7d5ff8265af28ef2cd56e9c9b2638fa08ad97", size = 36630881, upload-time = "2025-10-28T17:31:47.104Z" }, + { url = "https://files.pythonhosted.org/packages/7c/89/d70e9f628749b7e4db2aa4cd89735502ff3f08f7b9b27d2e799485987cd9/scipy-1.16.3-cp311-cp311-macosx_12_0_arm64.whl", hash = "sha256:8be1ca9170fcb6223cc7c27f4305d680ded114a1567c0bd2bfcbf947d1b17511", size = 28941012, upload-time = "2025-10-28T17:31:53.411Z" }, + { url = "https://files.pythonhosted.org/packages/a8/a8/0e7a9a6872a923505dbdf6bb93451edcac120363131c19013044a1e7cb0c/scipy-1.16.3-cp311-cp311-macosx_14_0_arm64.whl", hash = "sha256:bea0a62734d20d67608660f69dcda23e7f90fb4ca20974ab80b6ed40df87a005", size = 20931935, upload-time = "2025-10-28T17:31:57.361Z" }, + { url = "https://files.pythonhosted.org/packages/bd/c7/020fb72bd79ad798e4dbe53938543ecb96b3a9ac3fe274b7189e23e27353/scipy-1.16.3-cp311-cp311-macosx_14_0_x86_64.whl", hash = "sha256:2a207a6ce9c24f1951241f4693ede2d393f59c07abc159b2cb2be980820e01fb", size = 23534466, upload-time = "2025-10-28T17:32:01.875Z" }, + { url = "https://files.pythonhosted.org/packages/be/a0/668c4609ce6dbf2f948e167836ccaf897f95fb63fa231c87da7558a374cd/scipy-1.16.3-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:532fb5ad6a87e9e9cd9c959b106b73145a03f04c7d57ea3e6f6bb60b86ab0876", size = 33593618, upload-time = "2025-10-28T17:32:06.902Z" }, + { url = "https://files.pythonhosted.org/packages/ca/6e/8942461cf2636cdae083e3eb72622a7fbbfa5cf559c7d13ab250a5dbdc01/scipy-1.16.3-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:0151a0749efeaaab78711c78422d413c583b8cdd2011a3c1d6c794938ee9fdb2", size = 35899798, upload-time = "2025-10-28T17:32:12.665Z" }, + { url = "https://files.pythonhosted.org/packages/79/e8/d0f33590364cdbd67f28ce79368b373889faa4ee959588beddf6daef9abe/scipy-1.16.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:b7180967113560cca57418a7bc719e30366b47959dd845a93206fbed693c867e", size = 36226154, upload-time = "2025-10-28T17:32:17.961Z" }, + { url = "https://files.pythonhosted.org/packages/39/c1/1903de608c0c924a1749c590064e65810f8046e437aba6be365abc4f7557/scipy-1.16.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:deb3841c925eeddb6afc1e4e4a45e418d19ec7b87c5df177695224078e8ec733", size = 38878540, upload-time = "2025-10-28T17:32:23.907Z" }, + { url = "https://files.pythonhosted.org/packages/f1/d0/22ec7036ba0b0a35bccb7f25ab407382ed34af0b111475eb301c16f8a2e5/scipy-1.16.3-cp311-cp311-win_amd64.whl", hash = "sha256:53c3844d527213631e886621df5695d35e4f6a75f620dca412bcd292f6b87d78", size = 38722107, upload-time = "2025-10-28T17:32:29.921Z" }, + { url = "https://files.pythonhosted.org/packages/7b/60/8a00e5a524bb3bf8898db1650d350f50e6cffb9d7a491c561dc9826c7515/scipy-1.16.3-cp311-cp311-win_arm64.whl", hash = "sha256:9452781bd879b14b6f055b26643703551320aa8d79ae064a71df55c00286a184", size = 25506272, upload-time = "2025-10-28T17:32:34.577Z" }, + { url = "https://files.pythonhosted.org/packages/40/41/5bf55c3f386b1643812f3a5674edf74b26184378ef0f3e7c7a09a7e2ca7f/scipy-1.16.3-cp312-cp312-macosx_10_14_x86_64.whl", hash = "sha256:81fc5827606858cf71446a5e98715ba0e11f0dbc83d71c7409d05486592a45d6", size = 36659043, upload-time = "2025-10-28T17:32:40.285Z" }, + { url = "https://files.pythonhosted.org/packages/1e/0f/65582071948cfc45d43e9870bf7ca5f0e0684e165d7c9ef4e50d783073eb/scipy-1.16.3-cp312-cp312-macosx_12_0_arm64.whl", hash = "sha256:c97176013d404c7346bf57874eaac5187d969293bf40497140b0a2b2b7482e07", size = 28898986, upload-time = "2025-10-28T17:32:45.325Z" }, + { url = "https://files.pythonhosted.org/packages/96/5e/36bf3f0ac298187d1ceadde9051177d6a4fe4d507e8f59067dc9dd39e650/scipy-1.16.3-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:2b71d93c8a9936046866acebc915e2af2e292b883ed6e2cbe5c34beb094b82d9", size = 20889814, upload-time = "2025-10-28T17:32:49.277Z" }, + { url = "https://files.pythonhosted.org/packages/80/35/178d9d0c35394d5d5211bbff7ac4f2986c5488b59506fef9e1de13ea28d3/scipy-1.16.3-cp312-cp312-macosx_14_0_x86_64.whl", hash = "sha256:3d4a07a8e785d80289dfe66b7c27d8634a773020742ec7187b85ccc4b0e7b686", size = 23565795, upload-time = "2025-10-28T17:32:53.337Z" }, + { url = "https://files.pythonhosted.org/packages/fa/46/d1146ff536d034d02f83c8afc3c4bab2eddb634624d6529a8512f3afc9da/scipy-1.16.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:0553371015692a898e1aa858fed67a3576c34edefa6b7ebdb4e9dde49ce5c203", size = 33349476, upload-time = "2025-10-28T17:32:58.353Z" }, + { url = "https://files.pythonhosted.org/packages/79/2e/415119c9ab3e62249e18c2b082c07aff907a273741b3f8160414b0e9193c/scipy-1.16.3-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:72d1717fd3b5e6ec747327ce9bda32d5463f472c9dce9f54499e81fbd50245a1", size = 35676692, upload-time = "2025-10-28T17:33:03.88Z" }, + { url = "https://files.pythonhosted.org/packages/27/82/df26e44da78bf8d2aeaf7566082260cfa15955a5a6e96e6a29935b64132f/scipy-1.16.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:1fb2472e72e24d1530debe6ae078db70fb1605350c88a3d14bc401d6306dbffe", size = 36019345, upload-time = "2025-10-28T17:33:09.773Z" }, + { url = "https://files.pythonhosted.org/packages/82/31/006cbb4b648ba379a95c87262c2855cd0d09453e500937f78b30f02fa1cd/scipy-1.16.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:c5192722cffe15f9329a3948c4b1db789fbb1f05c97899187dcf009b283aea70", size = 38678975, upload-time = "2025-10-28T17:33:15.809Z" }, + { url = "https://files.pythonhosted.org/packages/c2/7f/acbd28c97e990b421af7d6d6cd416358c9c293fc958b8529e0bd5d2a2a19/scipy-1.16.3-cp312-cp312-win_amd64.whl", hash = "sha256:56edc65510d1331dae01ef9b658d428e33ed48b4f77b1d51caf479a0253f96dc", size = 38555926, upload-time = "2025-10-28T17:33:21.388Z" }, + { url = "https://files.pythonhosted.org/packages/ce/69/c5c7807fd007dad4f48e0a5f2153038dc96e8725d3345b9ee31b2b7bed46/scipy-1.16.3-cp312-cp312-win_arm64.whl", hash = "sha256:a8a26c78ef223d3e30920ef759e25625a0ecdd0d60e5a8818b7513c3e5384cf2", size = 25463014, upload-time = "2025-10-28T17:33:25.975Z" }, + { url = "https://files.pythonhosted.org/packages/72/f1/57e8327ab1508272029e27eeef34f2302ffc156b69e7e233e906c2a5c379/scipy-1.16.3-cp313-cp313-macosx_10_14_x86_64.whl", hash = "sha256:d2ec56337675e61b312179a1ad124f5f570c00f920cc75e1000025451b88241c", size = 36617856, upload-time = "2025-10-28T17:33:31.375Z" }, + { url = "https://files.pythonhosted.org/packages/44/13/7e63cfba8a7452eb756306aa2fd9b37a29a323b672b964b4fdeded9a3f21/scipy-1.16.3-cp313-cp313-macosx_12_0_arm64.whl", hash = "sha256:16b8bc35a4cc24db80a0ec836a9286d0e31b2503cb2fd7ff7fb0e0374a97081d", size = 28874306, upload-time = "2025-10-28T17:33:36.516Z" }, + { url = "https://files.pythonhosted.org/packages/15/65/3a9400efd0228a176e6ec3454b1fa998fbbb5a8defa1672c3f65706987db/scipy-1.16.3-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:5803c5fadd29de0cf27fa08ccbfe7a9e5d741bf63e4ab1085437266f12460ff9", size = 20865371, upload-time = "2025-10-28T17:33:42.094Z" }, + { url = "https://files.pythonhosted.org/packages/33/d7/eda09adf009a9fb81827194d4dd02d2e4bc752cef16737cc4ef065234031/scipy-1.16.3-cp313-cp313-macosx_14_0_x86_64.whl", hash = "sha256:b81c27fc41954319a943d43b20e07c40bdcd3ff7cf013f4fb86286faefe546c4", size = 23524877, upload-time = "2025-10-28T17:33:48.483Z" }, + { url = "https://files.pythonhosted.org/packages/7d/6b/3f911e1ebc364cb81320223a3422aab7d26c9c7973109a9cd0f27c64c6c0/scipy-1.16.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:0c3b4dd3d9b08dbce0f3440032c52e9e2ab9f96ade2d3943313dfe51a7056959", size = 33342103, upload-time = "2025-10-28T17:33:56.495Z" }, + { url = "https://files.pythonhosted.org/packages/21/f6/4bfb5695d8941e5c570a04d9fcd0d36bce7511b7d78e6e75c8f9791f82d0/scipy-1.16.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:7dc1360c06535ea6116a2220f760ae572db9f661aba2d88074fe30ec2aa1ff88", size = 35697297, upload-time = "2025-10-28T17:34:04.722Z" }, + { url = "https://files.pythonhosted.org/packages/04/e1/6496dadbc80d8d896ff72511ecfe2316b50313bfc3ebf07a3f580f08bd8c/scipy-1.16.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:663b8d66a8748051c3ee9c96465fb417509315b99c71550fda2591d7dd634234", size = 36021756, upload-time = "2025-10-28T17:34:13.482Z" }, + { url = "https://files.pythonhosted.org/packages/fe/bd/a8c7799e0136b987bda3e1b23d155bcb31aec68a4a472554df5f0937eef7/scipy-1.16.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:eab43fae33a0c39006a88096cd7b4f4ef545ea0447d250d5ac18202d40b6611d", size = 38696566, upload-time = "2025-10-28T17:34:22.384Z" }, + { url = "https://files.pythonhosted.org/packages/cd/01/1204382461fcbfeb05b6161b594f4007e78b6eba9b375382f79153172b4d/scipy-1.16.3-cp313-cp313-win_amd64.whl", hash = "sha256:062246acacbe9f8210de8e751b16fc37458213f124bef161a5a02c7a39284304", size = 38529877, upload-time = "2025-10-28T17:35:51.076Z" }, + { url = "https://files.pythonhosted.org/packages/7f/14/9d9fbcaa1260a94f4bb5b64ba9213ceb5d03cd88841fe9fd1ffd47a45b73/scipy-1.16.3-cp313-cp313-win_arm64.whl", hash = "sha256:50a3dbf286dbc7d84f176f9a1574c705f277cb6565069f88f60db9eafdbe3ee2", size = 25455366, upload-time = "2025-10-28T17:35:59.014Z" }, + { url = "https://files.pythonhosted.org/packages/e2/a3/9ec205bd49f42d45d77f1730dbad9ccf146244c1647605cf834b3a8c4f36/scipy-1.16.3-cp313-cp313t-macosx_10_14_x86_64.whl", hash = "sha256:fb4b29f4cf8cc5a8d628bc8d8e26d12d7278cd1f219f22698a378c3d67db5e4b", size = 37027931, upload-time = "2025-10-28T17:34:31.451Z" }, + { url = "https://files.pythonhosted.org/packages/25/06/ca9fd1f3a4589cbd825b1447e5db3a8ebb969c1eaf22c8579bd286f51b6d/scipy-1.16.3-cp313-cp313t-macosx_12_0_arm64.whl", hash = "sha256:8d09d72dc92742988b0e7750bddb8060b0c7079606c0d24a8cc8e9c9c11f9079", size = 29400081, upload-time = "2025-10-28T17:34:39.087Z" }, + { url = "https://files.pythonhosted.org/packages/6a/56/933e68210d92657d93fb0e381683bc0e53a965048d7358ff5fbf9e6a1b17/scipy-1.16.3-cp313-cp313t-macosx_14_0_arm64.whl", hash = "sha256:03192a35e661470197556de24e7cb1330d84b35b94ead65c46ad6f16f6b28f2a", size = 21391244, upload-time = "2025-10-28T17:34:45.234Z" }, + { url = "https://files.pythonhosted.org/packages/a8/7e/779845db03dc1418e215726329674b40576879b91814568757ff0014ad65/scipy-1.16.3-cp313-cp313t-macosx_14_0_x86_64.whl", hash = "sha256:57d01cb6f85e34f0946b33caa66e892aae072b64b034183f3d87c4025802a119", size = 23929753, upload-time = "2025-10-28T17:34:51.793Z" }, + { url = "https://files.pythonhosted.org/packages/4c/4b/f756cf8161d5365dcdef9e5f460ab226c068211030a175d2fc7f3f41ca64/scipy-1.16.3-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:96491a6a54e995f00a28a3c3badfff58fd093bf26cd5fb34a2188c8c756a3a2c", size = 33496912, upload-time = "2025-10-28T17:34:59.8Z" }, + { url = "https://files.pythonhosted.org/packages/09/b5/222b1e49a58668f23839ca1542a6322bb095ab8d6590d4f71723869a6c2c/scipy-1.16.3-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:cd13e354df9938598af2be05822c323e97132d5e6306b83a3b4ee6724c6e522e", size = 35802371, upload-time = "2025-10-28T17:35:08.173Z" }, + { url = "https://files.pythonhosted.org/packages/c1/8d/5964ef68bb31829bde27611f8c9deeac13764589fe74a75390242b64ca44/scipy-1.16.3-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:63d3cdacb8a824a295191a723ee5e4ea7768ca5ca5f2838532d9f2e2b3ce2135", size = 36190477, upload-time = "2025-10-28T17:35:16.7Z" }, + { url = "https://files.pythonhosted.org/packages/ab/f2/b31d75cb9b5fa4dd39a0a931ee9b33e7f6f36f23be5ef560bf72e0f92f32/scipy-1.16.3-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:e7efa2681ea410b10dde31a52b18b0154d66f2485328830e45fdf183af5aefc6", size = 38796678, upload-time = "2025-10-28T17:35:26.354Z" }, + { url = "https://files.pythonhosted.org/packages/b4/1e/b3723d8ff64ab548c38d87055483714fefe6ee20e0189b62352b5e015bb1/scipy-1.16.3-cp313-cp313t-win_amd64.whl", hash = "sha256:2d1ae2cf0c350e7705168ff2429962a89ad90c2d49d1dd300686d8b2a5af22fc", size = 38640178, upload-time = "2025-10-28T17:35:35.304Z" }, + { url = "https://files.pythonhosted.org/packages/8e/f3/d854ff38789aca9b0cc23008d607ced9de4f7ab14fa1ca4329f86b3758ca/scipy-1.16.3-cp313-cp313t-win_arm64.whl", hash = "sha256:0c623a54f7b79dd88ef56da19bc2873afec9673a48f3b85b18e4d402bdd29a5a", size = 25803246, upload-time = "2025-10-28T17:35:42.155Z" }, + { url = "https://files.pythonhosted.org/packages/99/f6/99b10fd70f2d864c1e29a28bbcaa0c6340f9d8518396542d9ea3b4aaae15/scipy-1.16.3-cp314-cp314-macosx_10_14_x86_64.whl", hash = "sha256:875555ce62743e1d54f06cdf22c1e0bc47b91130ac40fe5d783b6dfa114beeb6", size = 36606469, upload-time = "2025-10-28T17:36:08.741Z" }, + { url = "https://files.pythonhosted.org/packages/4d/74/043b54f2319f48ea940dd025779fa28ee360e6b95acb7cd188fad4391c6b/scipy-1.16.3-cp314-cp314-macosx_12_0_arm64.whl", hash = "sha256:bb61878c18a470021fb515a843dc7a76961a8daceaaaa8bad1332f1bf4b54657", size = 28872043, upload-time = "2025-10-28T17:36:16.599Z" }, + { url = "https://files.pythonhosted.org/packages/4d/e1/24b7e50cc1c4ee6ffbcb1f27fe9f4c8b40e7911675f6d2d20955f41c6348/scipy-1.16.3-cp314-cp314-macosx_14_0_arm64.whl", hash = "sha256:f2622206f5559784fa5c4b53a950c3c7c1cf3e84ca1b9c4b6c03f062f289ca26", size = 20862952, upload-time = "2025-10-28T17:36:22.966Z" }, + { url = "https://files.pythonhosted.org/packages/dd/3a/3e8c01a4d742b730df368e063787c6808597ccb38636ed821d10b39ca51b/scipy-1.16.3-cp314-cp314-macosx_14_0_x86_64.whl", hash = "sha256:7f68154688c515cdb541a31ef8eb66d8cd1050605be9dcd74199cbd22ac739bc", size = 23508512, upload-time = "2025-10-28T17:36:29.731Z" }, + { url = "https://files.pythonhosted.org/packages/1f/60/c45a12b98ad591536bfe5330cb3cfe1850d7570259303563b1721564d458/scipy-1.16.3-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:8b3c820ddb80029fe9f43d61b81d8b488d3ef8ca010d15122b152db77dc94c22", size = 33413639, upload-time = "2025-10-28T17:36:37.982Z" }, + { url = "https://files.pythonhosted.org/packages/71/bc/35957d88645476307e4839712642896689df442f3e53b0fa016ecf8a3357/scipy-1.16.3-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:d3837938ae715fc0fe3c39c0202de3a8853aff22ca66781ddc2ade7554b7e2cc", size = 35704729, upload-time = "2025-10-28T17:36:46.547Z" }, + { url = "https://files.pythonhosted.org/packages/3b/15/89105e659041b1ca11c386e9995aefacd513a78493656e57789f9d9eab61/scipy-1.16.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:aadd23f98f9cb069b3bd64ddc900c4d277778242e961751f77a8cb5c4b946fb0", size = 36086251, upload-time = "2025-10-28T17:36:55.161Z" }, + { url = "https://files.pythonhosted.org/packages/1a/87/c0ea673ac9c6cc50b3da2196d860273bc7389aa69b64efa8493bdd25b093/scipy-1.16.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:b7c5f1bda1354d6a19bc6af73a649f8285ca63ac6b52e64e658a5a11d4d69800", size = 38716681, upload-time = "2025-10-28T17:37:04.1Z" }, + { url = "https://files.pythonhosted.org/packages/91/06/837893227b043fb9b0d13e4bd7586982d8136cb249ffb3492930dab905b8/scipy-1.16.3-cp314-cp314-win_amd64.whl", hash = "sha256:e5d42a9472e7579e473879a1990327830493a7047506d58d73fc429b84c1d49d", size = 39358423, upload-time = "2025-10-28T17:38:20.005Z" }, + { url = "https://files.pythonhosted.org/packages/95/03/28bce0355e4d34a7c034727505a02d19548549e190bedd13a721e35380b7/scipy-1.16.3-cp314-cp314-win_arm64.whl", hash = "sha256:6020470b9d00245926f2d5bb93b119ca0340f0d564eb6fbaad843eaebf9d690f", size = 26135027, upload-time = "2025-10-28T17:38:24.966Z" }, + { url = "https://files.pythonhosted.org/packages/b2/6f/69f1e2b682efe9de8fe9f91040f0cd32f13cfccba690512ba4c582b0bc29/scipy-1.16.3-cp314-cp314t-macosx_10_14_x86_64.whl", hash = "sha256:e1d27cbcb4602680a49d787d90664fa4974063ac9d4134813332a8c53dbe667c", size = 37028379, upload-time = "2025-10-28T17:37:14.061Z" }, + { url = "https://files.pythonhosted.org/packages/7c/2d/e826f31624a5ebbab1cd93d30fd74349914753076ed0593e1d56a98c4fb4/scipy-1.16.3-cp314-cp314t-macosx_12_0_arm64.whl", hash = "sha256:9b9c9c07b6d56a35777a1b4cc8966118fb16cfd8daf6743867d17d36cfad2d40", size = 29400052, upload-time = "2025-10-28T17:37:21.709Z" }, + { url = "https://files.pythonhosted.org/packages/69/27/d24feb80155f41fd1f156bf144e7e049b4e2b9dd06261a242905e3bc7a03/scipy-1.16.3-cp314-cp314t-macosx_14_0_arm64.whl", hash = "sha256:3a4c460301fb2cffb7f88528f30b3127742cff583603aa7dc964a52c463b385d", size = 21391183, upload-time = "2025-10-28T17:37:29.559Z" }, + { url = "https://files.pythonhosted.org/packages/f8/d3/1b229e433074c5738a24277eca520a2319aac7465eea7310ea6ae0e98ae2/scipy-1.16.3-cp314-cp314t-macosx_14_0_x86_64.whl", hash = "sha256:f667a4542cc8917af1db06366d3f78a5c8e83badd56409f94d1eac8d8d9133fa", size = 23930174, upload-time = "2025-10-28T17:37:36.306Z" }, + { url = "https://files.pythonhosted.org/packages/16/9d/d9e148b0ec680c0f042581a2be79a28a7ab66c0c4946697f9e7553ead337/scipy-1.16.3-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:f379b54b77a597aa7ee5e697df0d66903e41b9c85a6dd7946159e356319158e8", size = 33497852, upload-time = "2025-10-28T17:37:42.228Z" }, + { url = "https://files.pythonhosted.org/packages/2f/22/4e5f7561e4f98b7bea63cf3fd7934bff1e3182e9f1626b089a679914d5c8/scipy-1.16.3-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:4aff59800a3b7f786b70bfd6ab551001cb553244988d7d6b8299cb1ea653b353", size = 35798595, upload-time = "2025-10-28T17:37:48.102Z" }, + { url = "https://files.pythonhosted.org/packages/83/42/6644d714c179429fc7196857866f219fef25238319b650bb32dde7bf7a48/scipy-1.16.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:da7763f55885045036fabcebd80144b757d3db06ab0861415d1c3b7c69042146", size = 36186269, upload-time = "2025-10-28T17:37:53.72Z" }, + { url = "https://files.pythonhosted.org/packages/ac/70/64b4d7ca92f9cf2e6fc6aaa2eecf80bb9b6b985043a9583f32f8177ea122/scipy-1.16.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:ffa6eea95283b2b8079b821dc11f50a17d0571c92b43e2b5b12764dc5f9b285d", size = 38802779, upload-time = "2025-10-28T17:37:59.393Z" }, + { url = "https://files.pythonhosted.org/packages/61/82/8d0e39f62764cce5ffd5284131e109f07cf8955aef9ab8ed4e3aa5e30539/scipy-1.16.3-cp314-cp314t-win_amd64.whl", hash = "sha256:d9f48cafc7ce94cf9b15c6bffdc443a81a27bf7075cf2dcd5c8b40f85d10c4e7", size = 39471128, upload-time = "2025-10-28T17:38:05.259Z" }, + { url = "https://files.pythonhosted.org/packages/64/47/a494741db7280eae6dc033510c319e34d42dd41b7ac0c7ead39354d1a2b5/scipy-1.16.3-cp314-cp314t-win_arm64.whl", hash = "sha256:21d9d6b197227a12dcbf9633320a4e34c6b0e51c57268df255a0942983bac562", size = 26464127, upload-time = "2025-10-28T17:38:11.34Z" }, +] + +[[package]] +name = "scipy-stubs" +version = "1.16.3.3" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "optype", extra = ["numpy"] }, +] +sdist = { url = "https://files.pythonhosted.org/packages/08/91/1700d2a1a9f64f19bb019a547e510b99a6af1fef49641a0bce86bc85fb8e/scipy_stubs-1.16.3.3.tar.gz", hash = "sha256:af47578875d5557567225a16ec1b9b38a48c4c4377d92396413ebd65406c44ee", size = 361468, upload-time = "2025-12-08T13:45:38.37Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/7c/e2/3b8826f281f59301e3284989b19cfc56fdccf799134c1befedd38482a23a/scipy_stubs-1.16.3.3-py3-none-any.whl", hash = "sha256:f6316b36cd0fb272c994ae5b10c4a73c644a7e156ed8d32bcd9c35303d0e1b7e", size = 561750, upload-time = "2025-12-08T13:45:36.568Z" }, +] + [[package]] name = "seaborn" version = "0.13.2"