From 8ba327112612a6769658f24af06d31c87ec2a329 Mon Sep 17 00:00:00 2001 From: EmilyTLin Date: Tue, 21 May 2024 01:05:50 -0700 Subject: [PATCH] ruff formatting --- bicytok/distanceMetricFuncs.py | 583 ++++++++++++++++++++++++--------- bicytok/figures/figure5.py | 93 ++++-- poetry.lock | 182 +++++----- 3 files changed, 591 insertions(+), 267 deletions(-) diff --git a/bicytok/distanceMetricFuncs.py b/bicytok/distanceMetricFuncs.py index 54cd551..fa26397 100644 --- a/bicytok/distanceMetricFuncs.py +++ b/bicytok/distanceMetricFuncs.py @@ -12,6 +12,7 @@ path_here = dirname(dirname(__file__)) + def KL_EMD_1D(ax, targCell, numFactors, RNA=False, offTargState=0) -> pd.DataFrame: """ Finds markers which have average greatest difference (EMD and KL) from other cells @@ -25,63 +26,107 @@ def KL_EMD_1D(ax, targCell, numFactors, RNA=False, offTargState=0) -> pd.DataFra """ CITE_DF = importCITE() markerDF = pd.DataFrame(columns=["Marker", "Cell Type", "Amount"]) - for marker in CITE_DF.loc[:, ((CITE_DF.columns != 'CellType1') & (CITE_DF.columns != 'CellType2') & (CITE_DF.columns != 'CellType3') & (CITE_DF.columns != 'Cell'))].columns: + for marker in CITE_DF.loc[ + :, + ( + (CITE_DF.columns != "CellType1") + & (CITE_DF.columns != "CellType2") + & (CITE_DF.columns != "CellType3") + & (CITE_DF.columns != "Cell") + ), + ].columns: markAvg = np.mean(CITE_DF[marker].values) if markAvg > 0.0001: - targCellMark = CITE_DF.loc[CITE_DF["CellType3"] == targCell][marker].values / markAvg + targCellMark = ( + CITE_DF.loc[CITE_DF["CellType3"] == targCell][marker].values / markAvg + ) # Compare to all non-memory Tregs if offTargState == 0: - offTargCellMark = CITE_DF.loc[CITE_DF["CellType3"] != targCell][marker].values / markAvg + offTargCellMark = ( + CITE_DF.loc[CITE_DF["CellType3"] != targCell][marker].values + / markAvg + ) # Compare to all non-Tregs elif offTargState == 1: - offTargCellMark = CITE_DF.loc[CITE_DF["CellType2"] != "Treg"][marker].values / markAvg + offTargCellMark = ( + CITE_DF.loc[CITE_DF["CellType2"] != "Treg"][marker].values / markAvg + ) # Compare to naive Tregs elif offTargState == 2: - offTargCellMark = CITE_DF.loc[CITE_DF["CellType3"] == "Treg Naive"][marker].values / markAvg + offTargCellMark = ( + CITE_DF.loc[CITE_DF["CellType3"] == "Treg Naive"][marker].values + / markAvg + ) if np.mean(targCellMark) > np.mean(offTargCellMark): - kdeTarg = KernelDensity(kernel='gaussian').fit(targCellMark.reshape(-1, 1)) - kdeOffTarg = KernelDensity(kernel='gaussian').fit(offTargCellMark.reshape(-1, 1)) + kdeTarg = KernelDensity(kernel="gaussian").fit( + targCellMark.reshape(-1, 1) + ) + kdeOffTarg = KernelDensity(kernel="gaussian").fit( + offTargCellMark.reshape(-1, 1) + ) minVal = np.minimum(targCellMark.min(), offTargCellMark.min()) - 10 maxVal = np.maximum(targCellMark.max(), offTargCellMark.max()) + 10 outcomes = np.arange(minVal, maxVal + 1).reshape(-1, 1) distTarg = np.exp(kdeTarg.score_samples(outcomes)) distOffTarg = np.exp(kdeOffTarg.score_samples(outcomes)) - KL_div = stats.entropy(distOffTarg.flatten() + 1e-200, distTarg.flatten() + 1e-200, base=2) - markerDF = pd.concat([markerDF, pd.DataFrame({"Marker": [marker], "Wasserstein Distance": stats.wasserstein_distance(targCellMark, offTargCellMark), "KL Divergence": KL_div})]) + KL_div = stats.entropy( + distOffTarg.flatten() + 1e-200, distTarg.flatten() + 1e-200, base=2 + ) + markerDF = pd.concat( + [ + markerDF, + pd.DataFrame( + { + "Marker": [marker], + "Wasserstein Distance": stats.wasserstein_distance( + targCellMark, offTargCellMark + ), + "KL Divergence": KL_div, + } + ), + ] + ) corrsDF = pd.DataFrame() for i, distance in enumerate(["Wasserstein Distance", "KL Divergence"]): ratioDF = markerDF.sort_values(by=distance) posCorrs = ratioDF.tail(numFactors).Marker.values - corrsDF = pd.concat([corrsDF, pd.DataFrame({"Distance": distance, "Marker": posCorrs})]) + corrsDF = pd.concat( + [corrsDF, pd.DataFrame({"Distance": distance, "Marker": posCorrs})] + ) markerDF = markerDF.loc[markerDF["Marker"].isin(posCorrs)] - sns.barplot(data=ratioDF.tail(numFactors), y="Marker", x=distance, ax=ax[i], color='k') + sns.barplot( + data=ratioDF.tail(numFactors), y="Marker", x=distance, ax=ax[i], color="k" + ) ax[i].set(xscale="log") ax[0].set(title="Wasserstein Distance - Surface Markers") ax[1].set(title="KL Divergence - Surface Markers") return corrsDF + def get_conversion_factor(weightDF, receptor_name): - ''' + """ conversion factors used for citeseq dataset :param weightDF: DataFrame containing weight information for receptors :param receptor_name: Name of the receptor for which the conversion factor is needed :return: conversion_factor: Conversion factor for the specified receptor - ''' - IL2Rb_factor = weightDF.loc[weightDF['Receptor'] == 'IL2Rb', 'Weight'].values[0] - IL7Ra_factor = weightDF.loc[weightDF['Receptor'] == 'IL7Ra', 'Weight'].values[0] - IL2Ra_factor = weightDF.loc[weightDF['Receptor'] == 'IL2Ra', 'Weight'].values[0] - if receptor_name == 'CD122': + """ + IL2Rb_factor = weightDF.loc[weightDF["Receptor"] == "IL2Rb", "Weight"].values[0] + IL7Ra_factor = weightDF.loc[weightDF["Receptor"] == "IL7Ra", "Weight"].values[0] + IL2Ra_factor = weightDF.loc[weightDF["Receptor"] == "IL2Ra", "Weight"].values[0] + if receptor_name == "CD122": return IL2Rb_factor - elif receptor_name == 'CD25': + elif receptor_name == "CD25": return IL2Ra_factor - elif receptor_name == 'CD127': + elif receptor_name == "CD127": return IL7Ra_factor - else: return (IL7Ra_factor + IL2Ra_factor + IL2Rb_factor) / 3 + else: + return (IL7Ra_factor + IL2Ra_factor + IL2Rb_factor) / 3 + def EMD_2D(dataset, signal_receptor, target_cells, special_receptor, ax): - ''' + """ returns list of descending EMD values for specified target cell (2 receptors) :param dataset: DataFrame containing the dataset :param signal_receptor: Name of the signal receptor @@ -90,39 +135,68 @@ def EMD_2D(dataset, signal_receptor, target_cells, special_receptor, ax): :param ax: Matplotlib Axes object for plotting (optional) :return: List of tuples format: (recep1, recep2, OT value) containing optimal transport distances and receptor information - ''' + """ CITE_DF = importCITE() weightDF = convFactCalc(CITE_DF) - # filter those outliers! - target_cells_df = dataset[(dataset['CellType3'] == target_cells) | (dataset['CellType2'] == target_cells)] - off_target_cells_df = dataset[~((dataset['CellType3'] == target_cells) | (dataset['CellType2'] == target_cells))] - - if signal_receptor == 'CD122': - conversion_factor_sig = weightDF.loc[weightDF['Receptor'] == 'IL2Rb', 'Weight'].values[0] - elif signal_receptor == 'CD25': - conversion_factor_sig = weightDF.loc[weightDF['Receptor'] == 'IL2Ra', 'Weight'].values[0] - elif signal_receptor == 'CD127': - conversion_factor_sig = weightDF.loc[weightDF['Receptor'] == 'IL7Ra', 'Weight'].values[0] + # filter those outliers! + target_cells_df = dataset[ + (dataset["CellType3"] == target_cells) | (dataset["CellType2"] == target_cells) + ] + off_target_cells_df = dataset[ + ~( + (dataset["CellType3"] == target_cells) + | (dataset["CellType2"] == target_cells) + ) + ] + + if signal_receptor == "CD122": + conversion_factor_sig = weightDF.loc[ + weightDF["Receptor"] == "IL2Rb", "Weight" + ].values[0] + elif signal_receptor == "CD25": + conversion_factor_sig = weightDF.loc[ + weightDF["Receptor"] == "IL2Ra", "Weight" + ].values[0] + elif signal_receptor == "CD127": + conversion_factor_sig = weightDF.loc[ + weightDF["Receptor"] == "IL7Ra", "Weight" + ].values[0] else: - conversion_factor_sig = (weightDF.loc[weightDF['Receptor'] == 'IL7Ra', 'Weight'].values[0] + - weightDF.loc[weightDF['Receptor'] == 'IL2Ra', 'Weight'].values[0] + - weightDF.loc[weightDF['Receptor'] == 'IL2Rb', 'Weight'].values[0]) / 3 + conversion_factor_sig = ( + weightDF.loc[weightDF["Receptor"] == "IL7Ra", "Weight"].values[0] + + weightDF.loc[weightDF["Receptor"] == "IL2Ra", "Weight"].values[0] + + weightDF.loc[weightDF["Receptor"] == "IL2Rb", "Weight"].values[0] + ) / 3 results = [] - non_signal_receptors = ['CD122', 'CD25', 'CD127'] if special_receptor is None else [special_receptor] + non_signal_receptors = ( + ["CD122", "CD25", "CD127"] if special_receptor is None else [special_receptor] + ) for receptor_name in non_signal_receptors: - target_receptor_counts = target_cells_df[[signal_receptor, receptor_name]].values - off_target_receptor_counts = off_target_cells_df[[signal_receptor, receptor_name]].values - if receptor_name == 'CD122': - conversion_factor = weightDF.loc[weightDF['Receptor'] == 'IL2Rb', 'Weight'].values[0] - elif receptor_name == 'CD25': - conversion_factor = weightDF.loc[weightDF['Receptor'] == 'IL2Ra', 'Weight'].values[0] - elif receptor_name == 'CD127': - conversion_factor = weightDF.loc[weightDF['Receptor'] == 'IL7Ra', 'Weight'].values[0] + target_receptor_counts = target_cells_df[ + [signal_receptor, receptor_name] + ].values + off_target_receptor_counts = off_target_cells_df[ + [signal_receptor, receptor_name] + ].values + if receptor_name == "CD122": + conversion_factor = weightDF.loc[ + weightDF["Receptor"] == "IL2Rb", "Weight" + ].values[0] + elif receptor_name == "CD25": + conversion_factor = weightDF.loc[ + weightDF["Receptor"] == "IL2Ra", "Weight" + ].values[0] + elif receptor_name == "CD127": + conversion_factor = weightDF.loc[ + weightDF["Receptor"] == "IL7Ra", "Weight" + ].values[0] else: - avg_weight = (weightDF.loc[weightDF['Receptor'] == 'IL7Ra', 'Weight'].values[0] + - weightDF.loc[weightDF['Receptor'] == 'IL2Ra', 'Weight'].values[0] + - weightDF.loc[weightDF['Receptor'] == 'IL2Rb', 'Weight'].values[0]) / 3 + avg_weight = ( + weightDF.loc[weightDF["Receptor"] == "IL7Ra", "Weight"].values[0] + + weightDF.loc[weightDF["Receptor"] == "IL2Ra", "Weight"].values[0] + + weightDF.loc[weightDF["Receptor"] == "IL2Rb", "Weight"].values[0] + ) / 3 conversion_factor = avg_weight target_receptor_counts[:, 0] *= conversion_factor_sig off_target_receptor_counts[:, 0] *= conversion_factor_sig @@ -130,16 +204,35 @@ def EMD_2D(dataset, signal_receptor, target_cells, special_receptor, ax): target_receptor_counts[:, 1] *= conversion_factor off_target_receptor_counts[:, 1] *= conversion_factor - average_receptor_counts = np.mean(np.concatenate((target_receptor_counts, off_target_receptor_counts)), axis=0) + average_receptor_counts = np.mean( + np.concatenate((target_receptor_counts, off_target_receptor_counts)), axis=0 + ) # Normalize the counts by dividing by the average - if average_receptor_counts[0] > 5 and average_receptor_counts[1] > 5 and np.mean(target_receptor_counts[:, 0]) > np.mean(off_target_receptor_counts[:, 0]) and np.mean(target_receptor_counts[:, 1]) > np.mean(off_target_receptor_counts[:, 1]): - target_receptor_counts = target_receptor_counts.astype(float) / average_receptor_counts - off_target_receptor_counts = off_target_receptor_counts.astype(float) / average_receptor_counts + if ( + average_receptor_counts[0] > 5 + and average_receptor_counts[1] > 5 + and np.mean(target_receptor_counts[:, 0]) + > np.mean(off_target_receptor_counts[:, 0]) + and np.mean(target_receptor_counts[:, 1]) + > np.mean(off_target_receptor_counts[:, 1]) + ): + target_receptor_counts = ( + target_receptor_counts.astype(float) / average_receptor_counts + ) + off_target_receptor_counts = ( + off_target_receptor_counts.astype(float) / average_receptor_counts + ) # Matrix for emd parameter M = ot.dist(target_receptor_counts, off_target_receptor_counts) # optimal transport distance - a = np.ones((target_receptor_counts.shape[0],)) / target_receptor_counts.shape[0] - b = np.ones((off_target_receptor_counts.shape[0],)) / off_target_receptor_counts.shape[0] + a = ( + np.ones((target_receptor_counts.shape[0],)) + / target_receptor_counts.shape[0] + ) + b = ( + np.ones((off_target_receptor_counts.shape[0],)) + / off_target_receptor_counts.shape[0] + ) optimal_transport = ot.emd2(a, b, M, numItermax=1000000000) if special_receptor is not None: return optimal_transport # Return the distance value directly @@ -149,22 +242,26 @@ def EMD_2D(dataset, signal_receptor, target_cells, special_receptor, ax): # end loop sorted_results = sorted(results, reverse=True) - top_receptor_info = [(receptor_name, optimal_transport, signal_receptor) for optimal_transport, receptor_name, signal_receptor in sorted_results[:10]] - # bar graph + top_receptor_info = [ + (receptor_name, optimal_transport, signal_receptor) + for optimal_transport, receptor_name, signal_receptor in sorted_results[:10] + ] + # bar graph receptor_names = [info[0] for info in top_receptor_info] distances = [info[1] for info in top_receptor_info] if ax is not None: ax.bar(range(len(receptor_names)), distances) - ax.set_xlabel('Receptor') - ax.set_ylabel('Distance') - ax.set_title('Top 5 Receptor Distances (2D)') + ax.set_xlabel("Receptor") + ax.set_ylabel("Distance") + ax.set_title("Top 5 Receptor Distances (2D)") ax.set_xticks(range(len(receptor_names))) - ax.set_xticklabels(receptor_names, rotation='vertical') - + ax.set_xticklabels(receptor_names, rotation="vertical") + return sorted_results + def EMD_3D(dataset1, target_cells, ax=None): - ''' + """ returns list of descending EMD values for specified target cell (3 receptors) returns list of descending EMD values for specified target cell (3 receptors) :param dataset1: DataFrame containing the dataset @@ -172,12 +269,12 @@ def EMD_3D(dataset1, target_cells, ax=None): :param ax: Matplotlib Axes object for plotting (optional) :return: List of tuples (format: (recep1, recep2, recep 3, OT value) containing optimal transport distances and receptor information for 3D analysis - - ''' + + """ CITE_DF = importCITE() weightDF = convFactCalc(CITE_DF) - exclude_columns = ['CellType1', 'CellType2', 'CellType3', 'Cell'] + exclude_columns = ["CellType1", "CellType2", "CellType3", "Cell"] threshold_multiplier = 5 # Calculate the mean and standard deviation for each numeric column numeric_columns = [col for col in dataset1.columns if col not in exclude_columns] @@ -193,102 +290,237 @@ def EMD_3D(dataset1, target_cells, ax=None): dataset = dataset1[~outlier_mask.any(axis=1)] # receptor_names = [col for col in dataset.columns if col not in exclude_columns] results = [] - target_cells_df = dataset[(dataset['CellType3'] == target_cells) | (dataset['CellType2'] == target_cells) | (dataset['CellType1'] == target_cells)] - off_target_cells_df = dataset[~((dataset['CellType3'] == target_cells) | (dataset['CellType2'] == target_cells) | (dataset['CellType1'] == target_cells))] - receptor_names = [col for col in dataset.columns if col not in exclude_columns and - np.mean(target_cells_df[col]) > np.mean(off_target_cells_df[col]) and - np.mean(target_cells_df[col]) > 5] - + target_cells_df = dataset[ + (dataset["CellType3"] == target_cells) + | (dataset["CellType2"] == target_cells) + | (dataset["CellType1"] == target_cells) + ] + off_target_cells_df = dataset[ + ~( + (dataset["CellType3"] == target_cells) + | (dataset["CellType2"] == target_cells) + | (dataset["CellType1"] == target_cells) + ) + ] + receptor_names = [ + col + for col in dataset.columns + if col not in exclude_columns + and np.mean(target_cells_df[col]) > np.mean(off_target_cells_df[col]) + and np.mean(target_cells_df[col]) > 5 + ] + for receptor1_name in receptor_names: for receptor2_name in receptor_names: for receptor3_name in receptor_names: - if receptor1_name != receptor2_name and receptor1_name != receptor3_name and receptor2_name != receptor3_name: + if ( + receptor1_name != receptor2_name + and receptor1_name != receptor3_name + and receptor2_name != receptor3_name + ): # Get on and off-target counts for receptor1 2 and 3 receptor1_on_target_counts = target_cells_df[receptor1_name].values - receptor1_off_target_counts = off_target_cells_df[receptor1_name].values + receptor1_off_target_counts = off_target_cells_df[ + receptor1_name + ].values receptor2_on_target_counts = target_cells_df[receptor2_name].values - receptor2_off_target_counts = off_target_cells_df[receptor2_name].values + receptor2_off_target_counts = off_target_cells_df[ + receptor2_name + ].values receptor3_on_target_counts = target_cells_df[receptor3_name].values - receptor3_off_target_counts = off_target_cells_df[receptor3_name].values - conversion_factor_receptor1 = get_conversion_factor(weightDF, receptor1_name) - conversion_factor_receptor2 = get_conversion_factor(weightDF, receptor2_name) - conversion_factor_receptor3 = get_conversion_factor(weightDF, receptor3_name) + receptor3_off_target_counts = off_target_cells_df[ + receptor3_name + ].values + conversion_factor_receptor1 = get_conversion_factor( + weightDF, receptor1_name + ) + conversion_factor_receptor2 = get_conversion_factor( + weightDF, receptor2_name + ) + conversion_factor_receptor3 = get_conversion_factor( + weightDF, receptor3_name + ) # Apply the conversion factors to the counts - receptor1_on_target_counts = receptor1_on_target_counts * conversion_factor_receptor1 - receptor1_off_target_counts = receptor1_off_target_counts * conversion_factor_receptor1 - receptor2_on_target_counts = receptor2_on_target_counts * conversion_factor_receptor2 - receptor2_off_target_counts = receptor2_off_target_counts * conversion_factor_receptor2 - receptor3_on_target_counts = receptor3_on_target_counts * conversion_factor_receptor3 - receptor3_off_target_counts = receptor3_off_target_counts * conversion_factor_receptor3 + receptor1_on_target_counts = ( + receptor1_on_target_counts * conversion_factor_receptor1 + ) + receptor1_off_target_counts = ( + receptor1_off_target_counts * conversion_factor_receptor1 + ) + receptor2_on_target_counts = ( + receptor2_on_target_counts * conversion_factor_receptor2 + ) + receptor2_off_target_counts = ( + receptor2_off_target_counts * conversion_factor_receptor2 + ) + receptor3_on_target_counts = ( + receptor3_on_target_counts * conversion_factor_receptor3 + ) + receptor3_off_target_counts = ( + receptor3_off_target_counts * conversion_factor_receptor3 + ) average_receptor_counts_1_on = np.mean(receptor1_on_target_counts) average_receptor_counts_1_off = np.mean(receptor1_off_target_counts) average_receptor_counts_2_on = np.mean(receptor2_on_target_counts) average_receptor_counts_2_off = np.mean(receptor2_off_target_counts) average_receptor_counts_3_on = np.mean(receptor3_on_target_counts) average_receptor_counts_3_off = np.mean(receptor3_off_target_counts) - average_receptor_counts_1 = np.mean(np.concatenate((receptor1_on_target_counts, receptor1_off_target_counts)), axis=0) - average_receptor_counts_2 = np.mean(np.concatenate((receptor2_on_target_counts, receptor2_off_target_counts)), axis=0) - average_receptor_counts_3 = np.mean(np.concatenate((receptor3_on_target_counts, receptor3_off_target_counts)), axis=0) - if average_receptor_counts_1_on > 5 and average_receptor_counts_2_on > 5 and average_receptor_counts_3_on > 5 and average_receptor_counts_1_on > average_receptor_counts_1_off and average_receptor_counts_2_on > average_receptor_counts_2_off and average_receptor_counts_3_on > average_receptor_counts_3_off: - receptor1_on_target_counts = receptor1_on_target_counts.astype(float) / average_receptor_counts_1 - receptor1_off_target_counts = receptor1_off_target_counts.astype(float) / average_receptor_counts_1 - receptor2_on_target_counts = receptor2_on_target_counts.astype(float) / average_receptor_counts_2 - receptor2_off_target_counts = receptor2_off_target_counts.astype(float) / average_receptor_counts_2 - receptor3_on_target_counts = receptor3_on_target_counts.astype(float) / average_receptor_counts_3 - receptor3_off_target_counts = receptor3_off_target_counts.astype(float) / average_receptor_counts_3 + average_receptor_counts_1 = np.mean( + np.concatenate( + (receptor1_on_target_counts, receptor1_off_target_counts) + ), + axis=0, + ) + average_receptor_counts_2 = np.mean( + np.concatenate( + (receptor2_on_target_counts, receptor2_off_target_counts) + ), + axis=0, + ) + average_receptor_counts_3 = np.mean( + np.concatenate( + (receptor3_on_target_counts, receptor3_off_target_counts) + ), + axis=0, + ) + if ( + average_receptor_counts_1_on > 5 + and average_receptor_counts_2_on > 5 + and average_receptor_counts_3_on > 5 + and average_receptor_counts_1_on > average_receptor_counts_1_off + and average_receptor_counts_2_on > average_receptor_counts_2_off + and average_receptor_counts_3_on > average_receptor_counts_3_off + ): + receptor1_on_target_counts = ( + receptor1_on_target_counts.astype(float) + / average_receptor_counts_1 + ) + receptor1_off_target_counts = ( + receptor1_off_target_counts.astype(float) + / average_receptor_counts_1 + ) + receptor2_on_target_counts = ( + receptor2_on_target_counts.astype(float) + / average_receptor_counts_2 + ) + receptor2_off_target_counts = ( + receptor2_off_target_counts.astype(float) + / average_receptor_counts_2 + ) + receptor3_on_target_counts = ( + receptor3_on_target_counts.astype(float) + / average_receptor_counts_3 + ) + receptor3_off_target_counts = ( + receptor3_off_target_counts.astype(float) + / average_receptor_counts_3 + ) # Calculate the EMD between on-target and off-target counts for both receptors # change this so its two [||] - on_target_counts = np.concatenate((receptor1_on_target_counts[:, np.newaxis], receptor2_on_target_counts[:, np.newaxis], receptor3_on_target_counts[:, np.newaxis]), axis=1) - off_target_counts = np.concatenate((receptor1_off_target_counts[:, np.newaxis], receptor2_off_target_counts[:, np.newaxis], receptor3_off_target_counts[:, np.newaxis]), axis=1) - average_receptor_counts = np.mean(np.concatenate((on_target_counts, off_target_counts)), axis=0) - on_target_counts = on_target_counts.astype(float) / average_receptor_counts - off_target_counts = off_target_counts.astype(float) / average_receptor_counts + on_target_counts = np.concatenate( + ( + receptor1_on_target_counts[:, np.newaxis], + receptor2_on_target_counts[:, np.newaxis], + receptor3_on_target_counts[:, np.newaxis], + ), + axis=1, + ) + off_target_counts = np.concatenate( + ( + receptor1_off_target_counts[:, np.newaxis], + receptor2_off_target_counts[:, np.newaxis], + receptor3_off_target_counts[:, np.newaxis], + ), + axis=1, + ) + average_receptor_counts = np.mean( + np.concatenate((on_target_counts, off_target_counts)), + axis=0, + ) + on_target_counts = ( + on_target_counts.astype(float) / average_receptor_counts + ) + off_target_counts = ( + off_target_counts.astype(float) / average_receptor_counts + ) M = ot.dist(on_target_counts, off_target_counts) - a = np.ones(on_target_counts.shape[0]) / on_target_counts.shape[0] - b = np.ones(off_target_counts.shape[0]) / off_target_counts.shape[0] + a = ( + np.ones(on_target_counts.shape[0]) + / on_target_counts.shape[0] + ) + b = ( + np.ones(off_target_counts.shape[0]) + / off_target_counts.shape[0] + ) optimal_transport = ot.emd2(a, b, M, numItermax=10000000) - results.append((optimal_transport, receptor1_name, receptor2_name, receptor3_name)) - print ('ot:', optimal_transport) + results.append( + ( + optimal_transport, + receptor1_name, + receptor2_name, + receptor3_name, + ) + ) + print("ot:", optimal_transport) else: - results.append((0, receptor1_name, receptor2_name, receptor3_name)) + results.append( + (0, receptor1_name, receptor2_name, receptor3_name) + ) sorted_results = sorted(results, reverse=True) - top_receptor_info = [(receptor1_name, receptor2_name, receptor3_name, optimal_transport) for optimal_transport, receptor1_name, receptor2_name, receptor3_name in sorted_results[:10]] - print ('top 10 dist:', top_receptor_info) + top_receptor_info = [ + (receptor1_name, receptor2_name, receptor3_name, optimal_transport) + for optimal_transport, receptor1_name, receptor2_name, receptor3_name in sorted_results[ + :10 + ] + ] + print("top 10 dist:", top_receptor_info) receptor_pairs = [(info[0], info[1], info[2]) for info in top_receptor_info] distances = [info[3] for info in top_receptor_info] if ax is not None: ax.bar(range(len(receptor_pairs)), distances) - ax.set_xlabel('Receptor Pair', fontsize=14) - ax.set_ylabel('Distance', fontsize=14) - ax.set_title(f'Top 10 Receptor Pair Distances (3D) for {target_cells}', fontsize=14) + ax.set_xlabel("Receptor Pair", fontsize=14) + ax.set_ylabel("Distance", fontsize=14) + ax.set_title( + f"Top 10 Receptor Pair Distances (3D) for {target_cells}", fontsize=14 + ) ax.set_xticks(range(len(receptor_pairs))) - ax.set_xticklabels([f"{pair[0]} - {pair[1]} - {pair[2]}" for pair in receptor_pairs], rotation='vertical', fontsize=14) + ax.set_xticklabels( + [f"{pair[0]} - {pair[1]} - {pair[2]}" for pair in receptor_pairs], + rotation="vertical", + fontsize=14, + ) return sorted_results + def calculate_kl_divergence_2D(targCellMark, offTargCellMark): - ''' + """ calculates the Kullback-Leibler (KL) divergence between two probability distributions *used in combination with 1D or 2D KL functions :param targCellMark: Target cell marker data :param offTargCellMark: Off-target cell marker data :return: KL_div: KL Divergence value - ''' - kdeTarg = KernelDensity(kernel='gaussian').fit(targCellMark.reshape(-1, 2)) - kdeOffTarg = KernelDensity(kernel='gaussian').fit(offTargCellMark.reshape(-1, 2)) + """ + kdeTarg = KernelDensity(kernel="gaussian").fit(targCellMark.reshape(-1, 2)) + kdeOffTarg = KernelDensity(kernel="gaussian").fit(offTargCellMark.reshape(-1, 2)) minVal = np.minimum(targCellMark.min(), offTargCellMark.min()) - 10 maxVal = np.maximum(targCellMark.max(), offTargCellMark.max()) + 10 - X, Y = np.mgrid[minVal:maxVal:((maxVal-minVal) / 100), minVal:maxVal:((maxVal-minVal) / 100)] + X, Y = np.mgrid[ + minVal : maxVal : ((maxVal - minVal) / 100), + minVal : maxVal : ((maxVal - minVal) / 100), + ] outcomes = np.concatenate((X.reshape(-1, 1), Y.reshape(-1, 1)), axis=1) distTarg = np.exp(kdeTarg.score_samples(outcomes)) distOffTarg = np.exp(kdeOffTarg.score_samples(outcomes)) - KL_div = stats.entropy(distOffTarg.flatten() + 1e-200, distTarg.flatten() + 1e-200, base=2) + KL_div = stats.entropy( + distOffTarg.flatten() + 1e-200, distTarg.flatten() + 1e-200, base=2 + ) return KL_div + def KL_divergence_2D(dataset, signal_receptor, target_cells, special_receptor, ax): - - ''' - returns list of descending EMD values for specified target cell (2 receptors) + """ + returns list of descending EMD values for specified target cell (2 receptors) :param dataset: DataFrame containing the dataset :param signal_receptor: Name of the signal receptor :param target_cells: Target cell type for analysis @@ -296,39 +528,68 @@ def KL_divergence_2D(dataset, signal_receptor, target_cells, special_receptor, a :param ax: Matplotlib Axes object for plotting (optional) :return: Sorted list of tuples containing KL Divergence values and receptor information - ''' + """ CITE_DF = importCITE() weightDF = convFactCalc(CITE_DF) - target_cells_df = dataset[(dataset['CellType3'] == target_cells) | (dataset['CellType2'] == target_cells)] - off_target_cells_df = dataset[~((dataset['CellType3'] == target_cells) | (dataset['CellType2'] == target_cells))] + target_cells_df = dataset[ + (dataset["CellType3"] == target_cells) | (dataset["CellType2"] == target_cells) + ] + off_target_cells_df = dataset[ + ~( + (dataset["CellType3"] == target_cells) + | (dataset["CellType2"] == target_cells) + ) + ] - if signal_receptor == 'CD122': - conversion_factor_sig = weightDF.loc[weightDF['Receptor'] == 'IL2Rb', 'Weight'].values[0] - elif signal_receptor == 'CD25': - conversion_factor_sig = weightDF.loc[weightDF['Receptor'] == 'IL2Ra', 'Weight'].values[0] - elif signal_receptor == 'CD127': - conversion_factor_sig = weightDF.loc[weightDF['Receptor'] == 'IL7Ra', 'Weight'].values[0] + if signal_receptor == "CD122": + conversion_factor_sig = weightDF.loc[ + weightDF["Receptor"] == "IL2Rb", "Weight" + ].values[0] + elif signal_receptor == "CD25": + conversion_factor_sig = weightDF.loc[ + weightDF["Receptor"] == "IL2Ra", "Weight" + ].values[0] + elif signal_receptor == "CD127": + conversion_factor_sig = weightDF.loc[ + weightDF["Receptor"] == "IL7Ra", "Weight" + ].values[0] else: - conversion_factor_sig = (weightDF.loc[weightDF['Receptor'] == 'IL7Ra', 'Weight'].values[0] + - weightDF.loc[weightDF['Receptor'] == 'IL2Ra', 'Weight'].values[0] + - weightDF.loc[weightDF['Receptor'] == 'IL2Rb', 'Weight'].values[0]) / 3 + conversion_factor_sig = ( + weightDF.loc[weightDF["Receptor"] == "IL7Ra", "Weight"].values[0] + + weightDF.loc[weightDF["Receptor"] == "IL2Ra", "Weight"].values[0] + + weightDF.loc[weightDF["Receptor"] == "IL2Rb", "Weight"].values[0] + ) / 3 results = [] - non_signal_receptors = ['CD122', 'CD25', 'CD127'] if special_receptor is None else [special_receptor] + non_signal_receptors = ( + ["CD122", "CD25", "CD127"] if special_receptor is None else [special_receptor] + ) for receptor_name in non_signal_receptors: - target_receptor_counts = target_cells_df[[signal_receptor, receptor_name]].values - off_target_receptor_counts = off_target_cells_df[[signal_receptor, receptor_name]].values - if receptor_name == 'CD122': - conversion_factor = weightDF.loc[weightDF['Receptor'] == 'IL2Rb', 'Weight'].values[0] - elif receptor_name == 'CD25': - conversion_factor = weightDF.loc[weightDF['Receptor'] == 'IL2Ra', 'Weight'].values[0] - elif receptor_name == 'CD127': - conversion_factor = weightDF.loc[weightDF['Receptor'] == 'IL7Ra', 'Weight'].values[0] + target_receptor_counts = target_cells_df[ + [signal_receptor, receptor_name] + ].values + off_target_receptor_counts = off_target_cells_df[ + [signal_receptor, receptor_name] + ].values + if receptor_name == "CD122": + conversion_factor = weightDF.loc[ + weightDF["Receptor"] == "IL2Rb", "Weight" + ].values[0] + elif receptor_name == "CD25": + conversion_factor = weightDF.loc[ + weightDF["Receptor"] == "IL2Ra", "Weight" + ].values[0] + elif receptor_name == "CD127": + conversion_factor = weightDF.loc[ + weightDF["Receptor"] == "IL7Ra", "Weight" + ].values[0] else: - avg_weight = (weightDF.loc[weightDF['Receptor'] == 'IL7Ra', 'Weight'].values[0] + - weightDF.loc[weightDF['Receptor'] == 'IL2Ra', 'Weight'].values[0] + - weightDF.loc[weightDF['Receptor'] == 'IL2Rb', 'Weight'].values[0]) / 3 + avg_weight = ( + weightDF.loc[weightDF["Receptor"] == "IL7Ra", "Weight"].values[0] + + weightDF.loc[weightDF["Receptor"] == "IL2Ra", "Weight"].values[0] + + weightDF.loc[weightDF["Receptor"] == "IL2Rb", "Weight"].values[0] + ) / 3 conversion_factor = avg_weight target_receptor_counts[:, 0] *= conversion_factor_sig off_target_receptor_counts[:, 0] *= conversion_factor_sig @@ -336,8 +597,14 @@ def KL_divergence_2D(dataset, signal_receptor, target_cells, special_receptor, a target_receptor_counts[:, 1] *= conversion_factor off_target_receptor_counts[:, 1] *= conversion_factor - KL_div = calculate_kl_divergence_2D(target_receptor_counts[:, 0:2], off_target_receptor_counts[:, 0:2]) - if np.mean(target_receptor_counts[:, 0]) > np.mean(off_target_receptor_counts[:, 0]) and np.mean(target_receptor_counts[:, 1]) > np.mean(off_target_receptor_counts[:, 1]): + KL_div = calculate_kl_divergence_2D( + target_receptor_counts[:, 0:2], off_target_receptor_counts[:, 0:2] + ) + if np.mean(target_receptor_counts[:, 0]) > np.mean( + off_target_receptor_counts[:, 0] + ) and np.mean(target_receptor_counts[:, 1]) > np.mean( + off_target_receptor_counts[:, 1] + ): if special_receptor is not None: return KL_div # Return the distance value directly results.append((KL_div, receptor_name, signal_receptor)) @@ -345,27 +612,31 @@ def KL_divergence_2D(dataset, signal_receptor, target_cells, special_receptor, a results.append((-1, receptor_name, signal_receptor)) sorted_results = sorted(results, reverse=True) - top_receptor_info = [(receptor_name, KL_div, signal_receptor) for KL_div, receptor_name, signal_receptor in sorted_results[:10]] - # bar graph + top_receptor_info = [ + (receptor_name, KL_div, signal_receptor) + for KL_div, receptor_name, signal_receptor in sorted_results[:10] + ] + # bar graph receptor_names = [info[0] for info in top_receptor_info] distances = [info[1] for info in top_receptor_info] if ax is not None: ax.bar(range(len(receptor_names)), distances) - ax.set_xlabel('Receptor') - ax.set_ylabel('Distance') - ax.set_title('Top 5 Receptor Distances (2D)') + ax.set_xlabel("Receptor") + ax.set_ylabel("Distance") + ax.set_title("Top 5 Receptor Distances (2D)") ax.set_xticks(range(len(receptor_names))) - ax.set_xticklabels(receptor_names, rotation='vertical') + ax.set_xticklabels(receptor_names, rotation="vertical") return sorted_results + def correlation(cell_type, relevant_epitopes): - '''Calculates the Pearson correlation between two celltypes receptor counts''' + """Calculates the Pearson correlation between two celltypes receptor counts""" epitopesList = pd.read_csv("./bicytok/data/epitopeList.csv") - epitopes = list(epitopesList['Epitope'].unique()) + epitopes = list(epitopesList["Epitope"].unique()) epitopesDF = getSampleAbundances(epitopes, np.array([cell_type])) - epitopesDF = epitopesDF[epitopesDF['CellType2'] == (cell_type)] - corr = epitopesDF[relevant_epitopes].corr(method='pearson') + epitopesDF = epitopesDF[epitopesDF["CellType2"] == (cell_type)] + corr = epitopesDF[relevant_epitopes].corr(method="pearson") sorted_corr = corr.stack().sort_values(ascending=False) - sorted_corr_df = pd.DataFrame({'Correlation': sorted_corr}) - return sorted_corr_df \ No newline at end of file + sorted_corr_df = pd.DataFrame({"Correlation": sorted_corr}) + return sorted_corr_df diff --git a/bicytok/figures/figure5.py b/bicytok/figures/figure5.py index 7efd03d..522aeb6 100644 --- a/bicytok/figures/figure5.py +++ b/bicytok/figures/figure5.py @@ -8,12 +8,19 @@ from scipy.optimize import least_squares -from ..selectivityFuncs import get_cell_bindings, getSampleAbundances, get_rec_vecs, optimizeDesign, minSelecFunc +from ..selectivityFuncs import ( + get_cell_bindings, + getSampleAbundances, + get_rec_vecs, + optimizeDesign, + minSelecFunc, +) from ..imports import importCITE from random import sample, seed path_here = dirname(dirname(__file__)) + def makeFigure(): """KL divergence, EMD, and anti-correlation with selectivity at a given dose.""" ax, f = getSetup((9, 3), (1, 3)) @@ -21,45 +28,87 @@ def makeFigure(): CITE_DF = importCITE() new_df = CITE_DF.sample(1000, random_state=42) - signal_receptor = 'CD122' + signal_receptor = "CD122" signal_valency = 1 valencies = [1, 2, 4] - allTargets = [['CD25', 'CD278'], ['CD25', 'CD4-2'], ['CD25', 'CD45RB']] + allTargets = [["CD25", "CD278"], ["CD25", "CD4-2"], ["CD25", "CD45RB"]] dose = 10e-2 - cells = np.array(['CD8 Naive', 'NK', 'CD8 TEM', 'CD4 Naive', 'CD4 CTL', 'CD8 TCM', 'CD8 Proliferating','Treg']) - targCell = 'Treg' + cells = np.array( + [ + "CD8 Naive", + "NK", + "CD8 TEM", + "CD4 Naive", + "CD4 CTL", + "CD8 TCM", + "CD8 Proliferating", + "Treg", + ] + ) + targCell = "Treg" offTCells = cells[cells != targCell] epitopesList = pd.read_csv(join(path_here, "data/epitopeList.csv")) - epitopes = list(epitopesList['Epitope'].unique()) + epitopes = list(epitopesList["Epitope"].unique()) epitopesDF = getSampleAbundances(epitopes, cells, numCells=1000) - df = pd.DataFrame(columns=['KL Divergence', "Earth Mover's Distance", 'Correlation', 'Selectivity', 'Valency']) + df = pd.DataFrame( + columns=[ + "KL Divergence", + "Earth Mover's Distance", + "Correlation", + "Selectivity", + "Valency", + ] + ) for val in valencies: prevOptAffs = [8.0, 8.0, 8.0] for targets in allTargets: vals = [signal_valency, val, val] - optParams = optimizeDesign(signal_receptor, targets, targCell, offTCells, epitopesDF, dose, vals, prevOptAffs) + optParams = optimizeDesign( + signal_receptor, + targets, + targCell, + offTCells, + epitopesDF, + dose, + vals, + prevOptAffs, + ) prevOptAffs = optParams[1] - select = 1 / optParams[0], - KLD = KL_divergence_2D(new_df, targets[0], targCell, targets[1], ax = None) - EMD = EMD_2D(new_df, targets[0], targCell, targets[1], ax = None) - corr = correlation(targCell, targets).loc[targets[0], targets[1]]['Correlation'] + select = (1 / optParams[0],) + KLD = KL_divergence_2D(new_df, targets[0], targCell, targets[1], ax=None) + EMD = EMD_2D(new_df, targets[0], targCell, targets[1], ax=None) + corr = correlation(targCell, targets).loc[targets[0], targets[1]][ + "Correlation" + ] - data = {'KL Divergence': [KLD], + data = { + "KL Divergence": [KLD], "Earth Mover's Distance": [EMD], - 'Correlation': [corr], - 'Selectivity': select, - 'Valency': [val] + "Correlation": [corr], + "Selectivity": select, + "Valency": [val], } - df_temp = pd.DataFrame(data, columns=['KL Divergence', "Earth Mover's Distance", 'Correlation', 'Selectivity', 'Valency']) + df_temp = pd.DataFrame( + data, + columns=[ + "KL Divergence", + "Earth Mover's Distance", + "Correlation", + "Selectivity", + "Valency", + ], + ) df = pd.concat([df, df_temp], ignore_index=True) - sns.lineplot(data=df, x='KL Divergence', y='Selectivity', hue='Valency', ax=ax[0]) - sns.lineplot(data=df, x="Earth Mover's Distance", y='Selectivity', hue='Valency', ax=ax[1]) - sns.lineplot(data=df, x='Correlation', y='Selectivity', hue='Valency', ax=ax[2]) - ax[0].set(xscale='log') - ax[1].set(xscale='log') + sns.lineplot(data=df, x="KL Divergence", y="Selectivity", hue="Valency", ax=ax[0]) + sns.lineplot( + data=df, x="Earth Mover's Distance", y="Selectivity", hue="Valency", ax=ax[1] + ) + sns.lineplot(data=df, x="Correlation", y="Selectivity", hue="Valency", ax=ax[2]) + ax[0].set(xscale="log") + ax[1].set(xscale="log") return f diff --git a/poetry.lock b/poetry.lock index f3a84f7..c781ce8 100644 --- a/poetry.lock +++ b/poetry.lock @@ -120,63 +120,63 @@ test-no-images = ["pytest", "pytest-cov", "pytest-xdist", "wurlitzer"] [[package]] name = "coverage" -version = "7.5.0" +version = "7.5.1" description = "Code coverage measurement for Python" optional = false python-versions = ">=3.8" files = [ - {file = "coverage-7.5.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:432949a32c3e3f820af808db1833d6d1631664d53dd3ce487aa25d574e18ad1c"}, - {file = "coverage-7.5.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:2bd7065249703cbeb6d4ce679c734bef0ee69baa7bff9724361ada04a15b7e3b"}, - {file = "coverage-7.5.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bbfe6389c5522b99768a93d89aca52ef92310a96b99782973b9d11e80511f932"}, - {file = "coverage-7.5.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:39793731182c4be939b4be0cdecde074b833f6171313cf53481f869937129ed3"}, - {file = "coverage-7.5.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:85a5dbe1ba1bf38d6c63b6d2c42132d45cbee6d9f0c51b52c59aa4afba057517"}, - {file = "coverage-7.5.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:357754dcdfd811462a725e7501a9b4556388e8ecf66e79df6f4b988fa3d0b39a"}, - {file = "coverage-7.5.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:a81eb64feded34f40c8986869a2f764f0fe2db58c0530d3a4afbcde50f314880"}, - {file = "coverage-7.5.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:51431d0abbed3a868e967f8257c5faf283d41ec882f58413cf295a389bb22e58"}, - {file = "coverage-7.5.0-cp310-cp310-win32.whl", hash = "sha256:f609ebcb0242d84b7adeee2b06c11a2ddaec5464d21888b2c8255f5fd6a98ae4"}, - {file = "coverage-7.5.0-cp310-cp310-win_amd64.whl", hash = "sha256:6782cd6216fab5a83216cc39f13ebe30adfac2fa72688c5a4d8d180cd52e8f6a"}, - {file = "coverage-7.5.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:e768d870801f68c74c2b669fc909839660180c366501d4cc4b87efd6b0eee375"}, - {file = "coverage-7.5.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:84921b10aeb2dd453247fd10de22907984eaf80901b578a5cf0bb1e279a587cb"}, - {file = "coverage-7.5.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:710c62b6e35a9a766b99b15cdc56d5aeda0914edae8bb467e9c355f75d14ee95"}, - {file = "coverage-7.5.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c379cdd3efc0658e652a14112d51a7668f6bfca7445c5a10dee7eabecabba19d"}, - {file = "coverage-7.5.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fea9d3ca80bcf17edb2c08a4704259dadac196fe5e9274067e7a20511fad1743"}, - {file = "coverage-7.5.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:41327143c5b1d715f5f98a397608f90ab9ebba606ae4e6f3389c2145410c52b1"}, - {file = "coverage-7.5.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:565b2e82d0968c977e0b0f7cbf25fd06d78d4856289abc79694c8edcce6eb2de"}, - {file = "coverage-7.5.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:cf3539007202ebfe03923128fedfdd245db5860a36810136ad95a564a2fdffff"}, - {file = "coverage-7.5.0-cp311-cp311-win32.whl", hash = "sha256:bf0b4b8d9caa8d64df838e0f8dcf68fb570c5733b726d1494b87f3da85db3a2d"}, - {file = "coverage-7.5.0-cp311-cp311-win_amd64.whl", hash = "sha256:9c6384cc90e37cfb60435bbbe0488444e54b98700f727f16f64d8bfda0b84656"}, - {file = "coverage-7.5.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:fed7a72d54bd52f4aeb6c6e951f363903bd7d70bc1cad64dd1f087980d309ab9"}, - {file = "coverage-7.5.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:cbe6581fcff7c8e262eb574244f81f5faaea539e712a058e6707a9d272fe5b64"}, - {file = "coverage-7.5.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ad97ec0da94b378e593ef532b980c15e377df9b9608c7c6da3506953182398af"}, - {file = "coverage-7.5.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bd4bacd62aa2f1a1627352fe68885d6ee694bdaebb16038b6e680f2924a9b2cc"}, - {file = "coverage-7.5.0-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:adf032b6c105881f9d77fa17d9eebe0ad1f9bfb2ad25777811f97c5362aa07f2"}, - {file = "coverage-7.5.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:4ba01d9ba112b55bfa4b24808ec431197bb34f09f66f7cb4fd0258ff9d3711b1"}, - {file = "coverage-7.5.0-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:f0bfe42523893c188e9616d853c47685e1c575fe25f737adf473d0405dcfa7eb"}, - {file = "coverage-7.5.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:a9a7ef30a1b02547c1b23fa9a5564f03c9982fc71eb2ecb7f98c96d7a0db5cf2"}, - {file = "coverage-7.5.0-cp312-cp312-win32.whl", hash = "sha256:3c2b77f295edb9fcdb6a250f83e6481c679335ca7e6e4a955e4290350f2d22a4"}, - {file = "coverage-7.5.0-cp312-cp312-win_amd64.whl", hash = "sha256:427e1e627b0963ac02d7c8730ca6d935df10280d230508c0ba059505e9233475"}, - {file = "coverage-7.5.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:9dd88fce54abbdbf4c42fb1fea0e498973d07816f24c0e27a1ecaf91883ce69e"}, - {file = "coverage-7.5.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:a898c11dca8f8c97b467138004a30133974aacd572818c383596f8d5b2eb04a9"}, - {file = "coverage-7.5.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:07dfdd492d645eea1bd70fb1d6febdcf47db178b0d99161d8e4eed18e7f62fe7"}, - {file = "coverage-7.5.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d3d117890b6eee85887b1eed41eefe2e598ad6e40523d9f94c4c4b213258e4a4"}, - {file = "coverage-7.5.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6afd2e84e7da40fe23ca588379f815fb6dbbb1b757c883935ed11647205111cb"}, - {file = "coverage-7.5.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:a9960dd1891b2ddf13a7fe45339cd59ecee3abb6b8326d8b932d0c5da208104f"}, - {file = "coverage-7.5.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:ced268e82af993d7801a9db2dbc1d2322e786c5dc76295d8e89473d46c6b84d4"}, - {file = "coverage-7.5.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:e7c211f25777746d468d76f11719e64acb40eed410d81c26cefac641975beb88"}, - {file = "coverage-7.5.0-cp38-cp38-win32.whl", hash = "sha256:262fffc1f6c1a26125d5d573e1ec379285a3723363f3bd9c83923c9593a2ac25"}, - {file = "coverage-7.5.0-cp38-cp38-win_amd64.whl", hash = "sha256:eed462b4541c540d63ab57b3fc69e7d8c84d5957668854ee4e408b50e92ce26a"}, - {file = "coverage-7.5.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:d0194d654e360b3e6cc9b774e83235bae6b9b2cac3be09040880bb0e8a88f4a1"}, - {file = "coverage-7.5.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:33c020d3322662e74bc507fb11488773a96894aa82a622c35a5a28673c0c26f5"}, - {file = "coverage-7.5.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0cbdf2cae14a06827bec50bd58e49249452d211d9caddd8bd80e35b53cb04631"}, - {file = "coverage-7.5.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3235d7c781232e525b0761730e052388a01548bd7f67d0067a253887c6e8df46"}, - {file = "coverage-7.5.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:db2de4e546f0ec4b2787d625e0b16b78e99c3e21bc1722b4977c0dddf11ca84e"}, - {file = "coverage-7.5.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:4d0e206259b73af35c4ec1319fd04003776e11e859936658cb6ceffdeba0f5be"}, - {file = "coverage-7.5.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:2055c4fb9a6ff624253d432aa471a37202cd8f458c033d6d989be4499aed037b"}, - {file = "coverage-7.5.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:075299460948cd12722a970c7eae43d25d37989da682997687b34ae6b87c0ef0"}, - {file = "coverage-7.5.0-cp39-cp39-win32.whl", hash = "sha256:280132aada3bc2f0fac939a5771db4fbb84f245cb35b94fae4994d4c1f80dae7"}, - {file = "coverage-7.5.0-cp39-cp39-win_amd64.whl", hash = "sha256:c58536f6892559e030e6924896a44098bc1290663ea12532c78cef71d0df8493"}, - {file = "coverage-7.5.0-pp38.pp39.pp310-none-any.whl", hash = "sha256:2b57780b51084d5223eee7b59f0d4911c31c16ee5aa12737c7a02455829ff067"}, - {file = "coverage-7.5.0.tar.gz", hash = "sha256:cf62d17310f34084c59c01e027259076479128d11e4661bb6c9acb38c5e19bb8"}, + {file = "coverage-7.5.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:c0884920835a033b78d1c73b6d3bbcda8161a900f38a488829a83982925f6c2e"}, + {file = "coverage-7.5.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:39afcd3d4339329c5f58de48a52f6e4e50f6578dd6099961cf22228feb25f38f"}, + {file = "coverage-7.5.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4a7b0ceee8147444347da6a66be737c9d78f3353b0681715b668b72e79203e4a"}, + {file = "coverage-7.5.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4a9ca3f2fae0088c3c71d743d85404cec8df9be818a005ea065495bedc33da35"}, + {file = "coverage-7.5.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5fd215c0c7d7aab005221608a3c2b46f58c0285a819565887ee0b718c052aa4e"}, + {file = "coverage-7.5.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:4bf0655ab60d754491004a5efd7f9cccefcc1081a74c9ef2da4735d6ee4a6223"}, + {file = "coverage-7.5.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:61c4bf1ba021817de12b813338c9be9f0ad5b1e781b9b340a6d29fc13e7c1b5e"}, + {file = "coverage-7.5.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:db66fc317a046556a96b453a58eced5024af4582a8dbdc0c23ca4dbc0d5b3146"}, + {file = "coverage-7.5.1-cp310-cp310-win32.whl", hash = "sha256:b016ea6b959d3b9556cb401c55a37547135a587db0115635a443b2ce8f1c7228"}, + {file = "coverage-7.5.1-cp310-cp310-win_amd64.whl", hash = "sha256:df4e745a81c110e7446b1cc8131bf986157770fa405fe90e15e850aaf7619bc8"}, + {file = "coverage-7.5.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:796a79f63eca8814ca3317a1ea443645c9ff0d18b188de470ed7ccd45ae79428"}, + {file = "coverage-7.5.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:4fc84a37bfd98db31beae3c2748811a3fa72bf2007ff7902f68746d9757f3746"}, + {file = "coverage-7.5.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6175d1a0559986c6ee3f7fccfc4a90ecd12ba0a383dcc2da30c2b9918d67d8a3"}, + {file = "coverage-7.5.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1fc81d5878cd6274ce971e0a3a18a8803c3fe25457165314271cf78e3aae3aa2"}, + {file = "coverage-7.5.1-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:556cf1a7cbc8028cb60e1ff0be806be2eded2daf8129b8811c63e2b9a6c43bca"}, + {file = "coverage-7.5.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:9981706d300c18d8b220995ad22627647be11a4276721c10911e0e9fa44c83e8"}, + {file = "coverage-7.5.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:d7fed867ee50edf1a0b4a11e8e5d0895150e572af1cd6d315d557758bfa9c057"}, + {file = "coverage-7.5.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:ef48e2707fb320c8f139424a596f5b69955a85b178f15af261bab871873bb987"}, + {file = "coverage-7.5.1-cp311-cp311-win32.whl", hash = "sha256:9314d5678dcc665330df5b69c1e726a0e49b27df0461c08ca12674bcc19ef136"}, + {file = "coverage-7.5.1-cp311-cp311-win_amd64.whl", hash = "sha256:5fa567e99765fe98f4e7d7394ce623e794d7cabb170f2ca2ac5a4174437e90dd"}, + {file = "coverage-7.5.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:b6cf3764c030e5338e7f61f95bd21147963cf6aa16e09d2f74f1fa52013c1206"}, + {file = "coverage-7.5.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2ec92012fefebee89a6b9c79bc39051a6cb3891d562b9270ab10ecfdadbc0c34"}, + {file = "coverage-7.5.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:16db7f26000a07efcf6aea00316f6ac57e7d9a96501e990a36f40c965ec7a95d"}, + {file = "coverage-7.5.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:beccf7b8a10b09c4ae543582c1319c6df47d78fd732f854ac68d518ee1fb97fa"}, + {file = "coverage-7.5.1-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8748731ad392d736cc9ccac03c9845b13bb07d020a33423fa5b3a36521ac6e4e"}, + {file = "coverage-7.5.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:7352b9161b33fd0b643ccd1f21f3a3908daaddf414f1c6cb9d3a2fd618bf2572"}, + {file = "coverage-7.5.1-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:7a588d39e0925f6a2bff87154752481273cdb1736270642aeb3635cb9b4cad07"}, + {file = "coverage-7.5.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:68f962d9b72ce69ea8621f57551b2fa9c70509af757ee3b8105d4f51b92b41a7"}, + {file = "coverage-7.5.1-cp312-cp312-win32.whl", hash = "sha256:f152cbf5b88aaeb836127d920dd0f5e7edff5a66f10c079157306c4343d86c19"}, + {file = "coverage-7.5.1-cp312-cp312-win_amd64.whl", hash = "sha256:5a5740d1fb60ddf268a3811bcd353de34eb56dc24e8f52a7f05ee513b2d4f596"}, + {file = "coverage-7.5.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:e2213def81a50519d7cc56ed643c9e93e0247f5bbe0d1247d15fa520814a7cd7"}, + {file = "coverage-7.5.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:5037f8fcc2a95b1f0e80585bd9d1ec31068a9bcb157d9750a172836e98bc7a90"}, + {file = "coverage-7.5.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5c3721c2c9e4c4953a41a26c14f4cef64330392a6d2d675c8b1db3b645e31f0e"}, + {file = "coverage-7.5.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ca498687ca46a62ae590253fba634a1fe9836bc56f626852fb2720f334c9e4e5"}, + {file = "coverage-7.5.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0cdcbc320b14c3e5877ee79e649677cb7d89ef588852e9583e6b24c2e5072661"}, + {file = "coverage-7.5.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:57e0204b5b745594e5bc14b9b50006da722827f0b8c776949f1135677e88d0b8"}, + {file = "coverage-7.5.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:8fe7502616b67b234482c3ce276ff26f39ffe88adca2acf0261df4b8454668b4"}, + {file = "coverage-7.5.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:9e78295f4144f9dacfed4f92935fbe1780021247c2fabf73a819b17f0ccfff8d"}, + {file = "coverage-7.5.1-cp38-cp38-win32.whl", hash = "sha256:1434e088b41594baa71188a17533083eabf5609e8e72f16ce8c186001e6b8c41"}, + {file = "coverage-7.5.1-cp38-cp38-win_amd64.whl", hash = "sha256:0646599e9b139988b63704d704af8e8df7fa4cbc4a1f33df69d97f36cb0a38de"}, + {file = "coverage-7.5.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:4cc37def103a2725bc672f84bd939a6fe4522310503207aae4d56351644682f1"}, + {file = "coverage-7.5.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:fc0b4d8bfeabd25ea75e94632f5b6e047eef8adaed0c2161ada1e922e7f7cece"}, + {file = "coverage-7.5.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0d0a0f5e06881ecedfe6f3dd2f56dcb057b6dbeb3327fd32d4b12854df36bf26"}, + {file = "coverage-7.5.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9735317685ba6ec7e3754798c8871c2f49aa5e687cc794a0b1d284b2389d1bd5"}, + {file = "coverage-7.5.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d21918e9ef11edf36764b93101e2ae8cc82aa5efdc7c5a4e9c6c35a48496d601"}, + {file = "coverage-7.5.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:c3e757949f268364b96ca894b4c342b41dc6f8f8b66c37878aacef5930db61be"}, + {file = "coverage-7.5.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:79afb6197e2f7f60c4824dd4b2d4c2ec5801ceb6ba9ce5d2c3080e5660d51a4f"}, + {file = "coverage-7.5.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:d1d0d98d95dd18fe29dc66808e1accf59f037d5716f86a501fc0256455219668"}, + {file = "coverage-7.5.1-cp39-cp39-win32.whl", hash = "sha256:1cc0fe9b0b3a8364093c53b0b4c0c2dd4bb23acbec4c9240b5f284095ccf7981"}, + {file = "coverage-7.5.1-cp39-cp39-win_amd64.whl", hash = "sha256:dde0070c40ea8bb3641e811c1cfbf18e265d024deff6de52c5950677a8fb1e0f"}, + {file = "coverage-7.5.1-pp38.pp39.pp310-none-any.whl", hash = "sha256:6537e7c10cc47c595828b8a8be04c72144725c383c4702703ff4e42e44577312"}, + {file = "coverage-7.5.1.tar.gz", hash = "sha256:54de9ef3a9da981f7af93eafde4ede199e0846cd819eb27c88e2b712aae9708c"}, ] [package.extras] @@ -308,13 +308,13 @@ files = [ [[package]] name = "joblib" -version = "1.4.0" +version = "1.4.2" description = "Lightweight pipelining with Python functions" optional = false python-versions = ">=3.8" files = [ - {file = "joblib-1.4.0-py3-none-any.whl", hash = "sha256:42942470d4062537be4d54c83511186da1fc14ba354961a2114da91efa9a4ed7"}, - {file = "joblib-1.4.0.tar.gz", hash = "sha256:1eb0dc091919cd384490de890cb5dfd538410a6d4b3b54eef09fb8c50b409b1c"}, + {file = "joblib-1.4.2-py3-none-any.whl", hash = "sha256:06d478d5674cbc267e7496a410ee875abd68e4340feff4490bcb7afb88060ae6"}, + {file = "joblib-1.4.2.tar.gz", hash = "sha256:2382c5816b2636fbd20a09e0f4e9dad4736765fdfb7dca582943b9c1366b3f0e"}, ] [[package]] @@ -462,39 +462,40 @@ files = [ [[package]] name = "matplotlib" -version = "3.8.4" +version = "3.9.0" description = "Python plotting package" optional = false python-versions = ">=3.9" files = [ - {file = "matplotlib-3.8.4-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:abc9d838f93583650c35eca41cfcec65b2e7cb50fd486da6f0c49b5e1ed23014"}, - {file = "matplotlib-3.8.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8f65c9f002d281a6e904976007b2d46a1ee2bcea3a68a8c12dda24709ddc9106"}, - {file = "matplotlib-3.8.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ce1edd9f5383b504dbc26eeea404ed0a00656c526638129028b758fd43fc5f10"}, - {file = "matplotlib-3.8.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ecd79298550cba13a43c340581a3ec9c707bd895a6a061a78fa2524660482fc0"}, - {file = "matplotlib-3.8.4-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:90df07db7b599fe7035d2f74ab7e438b656528c68ba6bb59b7dc46af39ee48ef"}, - {file = "matplotlib-3.8.4-cp310-cp310-win_amd64.whl", hash = "sha256:ac24233e8f2939ac4fd2919eed1e9c0871eac8057666070e94cbf0b33dd9c338"}, - {file = "matplotlib-3.8.4-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:72f9322712e4562e792b2961971891b9fbbb0e525011e09ea0d1f416c4645661"}, - {file = "matplotlib-3.8.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:232ce322bfd020a434caaffbd9a95333f7c2491e59cfc014041d95e38ab90d1c"}, - {file = "matplotlib-3.8.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6addbd5b488aedb7f9bc19f91cd87ea476206f45d7116fcfe3d31416702a82fa"}, - {file = "matplotlib-3.8.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cc4ccdc64e3039fc303defd119658148f2349239871db72cd74e2eeaa9b80b71"}, - {file = "matplotlib-3.8.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:b7a2a253d3b36d90c8993b4620183b55665a429da8357a4f621e78cd48b2b30b"}, - {file = "matplotlib-3.8.4-cp311-cp311-win_amd64.whl", hash = "sha256:8080d5081a86e690d7688ffa542532e87f224c38a6ed71f8fbed34dd1d9fedae"}, - {file = "matplotlib-3.8.4-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:6485ac1f2e84676cff22e693eaa4fbed50ef5dc37173ce1f023daef4687df616"}, - {file = "matplotlib-3.8.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:c89ee9314ef48c72fe92ce55c4e95f2f39d70208f9f1d9db4e64079420d8d732"}, - {file = "matplotlib-3.8.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:50bac6e4d77e4262c4340d7a985c30912054745ec99756ce213bfbc3cb3808eb"}, - {file = "matplotlib-3.8.4-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f51c4c869d4b60d769f7b4406eec39596648d9d70246428745a681c327a8ad30"}, - {file = "matplotlib-3.8.4-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:b12ba985837e4899b762b81f5b2845bd1a28f4fdd1a126d9ace64e9c4eb2fb25"}, - {file = "matplotlib-3.8.4-cp312-cp312-win_amd64.whl", hash = "sha256:7a6769f58ce51791b4cb8b4d7642489df347697cd3e23d88266aaaee93b41d9a"}, - {file = "matplotlib-3.8.4-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:843cbde2f0946dadd8c5c11c6d91847abd18ec76859dc319362a0964493f0ba6"}, - {file = "matplotlib-3.8.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:1c13f041a7178f9780fb61cc3a2b10423d5e125480e4be51beaf62b172413b67"}, - {file = "matplotlib-3.8.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fb44f53af0a62dc80bba4443d9b27f2fde6acfdac281d95bc872dc148a6509cc"}, - {file = "matplotlib-3.8.4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:606e3b90897554c989b1e38a258c626d46c873523de432b1462f295db13de6f9"}, - {file = "matplotlib-3.8.4-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:9bb0189011785ea794ee827b68777db3ca3f93f3e339ea4d920315a0e5a78d54"}, - {file = "matplotlib-3.8.4-cp39-cp39-win_amd64.whl", hash = "sha256:6209e5c9aaccc056e63b547a8152661324404dd92340a6e479b3a7f24b42a5d0"}, - {file = "matplotlib-3.8.4-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:c7064120a59ce6f64103c9cefba8ffe6fba87f2c61d67c401186423c9a20fd35"}, - {file = "matplotlib-3.8.4-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a0e47eda4eb2614300fc7bb4657fced3e83d6334d03da2173b09e447418d499f"}, - {file = "matplotlib-3.8.4-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:493e9f6aa5819156b58fce42b296ea31969f2aab71c5b680b4ea7a3cb5c07d94"}, - {file = "matplotlib-3.8.4.tar.gz", hash = "sha256:8aac397d5e9ec158960e31c381c5ffc52ddd52bd9a47717e2a694038167dffea"}, + {file = "matplotlib-3.9.0-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:2bcee1dffaf60fe7656183ac2190bd630842ff87b3153afb3e384d966b57fe56"}, + {file = "matplotlib-3.9.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:3f988bafb0fa39d1074ddd5bacd958c853e11def40800c5824556eb630f94d3b"}, + {file = "matplotlib-3.9.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fe428e191ea016bb278758c8ee82a8129c51d81d8c4bc0846c09e7e8e9057241"}, + {file = "matplotlib-3.9.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eaf3978060a106fab40c328778b148f590e27f6fa3cd15a19d6892575bce387d"}, + {file = "matplotlib-3.9.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:2e7f03e5cbbfacdd48c8ea394d365d91ee8f3cae7e6ec611409927b5ed997ee4"}, + {file = "matplotlib-3.9.0-cp310-cp310-win_amd64.whl", hash = "sha256:13beb4840317d45ffd4183a778685e215939be7b08616f431c7795276e067463"}, + {file = "matplotlib-3.9.0-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:063af8587fceeac13b0936c42a2b6c732c2ab1c98d38abc3337e430e1ff75e38"}, + {file = "matplotlib-3.9.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:9a2fa6d899e17ddca6d6526cf6e7ba677738bf2a6a9590d702c277204a7c6152"}, + {file = "matplotlib-3.9.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:550cdda3adbd596078cca7d13ed50b77879104e2e46392dcd7c75259d8f00e85"}, + {file = "matplotlib-3.9.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:76cce0f31b351e3551d1f3779420cf8f6ec0d4a8cf9c0237a3b549fd28eb4abb"}, + {file = "matplotlib-3.9.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:c53aeb514ccbbcbab55a27f912d79ea30ab21ee0531ee2c09f13800efb272674"}, + {file = "matplotlib-3.9.0-cp311-cp311-win_amd64.whl", hash = "sha256:a5be985db2596d761cdf0c2eaf52396f26e6a64ab46bd8cd810c48972349d1be"}, + {file = "matplotlib-3.9.0-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:c79f3a585f1368da6049318bdf1f85568d8d04b2e89fc24b7e02cc9b62017382"}, + {file = "matplotlib-3.9.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:bdd1ecbe268eb3e7653e04f451635f0fb0f77f07fd070242b44c076c9106da84"}, + {file = "matplotlib-3.9.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d38e85a1a6d732f645f1403ce5e6727fd9418cd4574521d5803d3d94911038e5"}, + {file = "matplotlib-3.9.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0a490715b3b9984fa609116481b22178348c1a220a4499cda79132000a79b4db"}, + {file = "matplotlib-3.9.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8146ce83cbc5dc71c223a74a1996d446cd35cfb6a04b683e1446b7e6c73603b7"}, + {file = "matplotlib-3.9.0-cp312-cp312-win_amd64.whl", hash = "sha256:d91a4ffc587bacf5c4ce4ecfe4bcd23a4b675e76315f2866e588686cc97fccdf"}, + {file = "matplotlib-3.9.0-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:616fabf4981a3b3c5a15cd95eba359c8489c4e20e03717aea42866d8d0465956"}, + {file = "matplotlib-3.9.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:cd53c79fd02f1c1808d2cfc87dd3cf4dbc63c5244a58ee7944497107469c8d8a"}, + {file = "matplotlib-3.9.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:06a478f0d67636554fa78558cfbcd7b9dba85b51f5c3b5a0c9be49010cf5f321"}, + {file = "matplotlib-3.9.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:81c40af649d19c85f8073e25e5806926986806fa6d54be506fbf02aef47d5a89"}, + {file = "matplotlib-3.9.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:52146fc3bd7813cc784562cb93a15788be0b2875c4655e2cc6ea646bfa30344b"}, + {file = "matplotlib-3.9.0-cp39-cp39-win_amd64.whl", hash = "sha256:0fc51eaa5262553868461c083d9adadb11a6017315f3a757fc45ec6ec5f02888"}, + {file = "matplotlib-3.9.0-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:bd4f2831168afac55b881db82a7730992aa41c4f007f1913465fb182d6fb20c0"}, + {file = "matplotlib-3.9.0-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:290d304e59be2b33ef5c2d768d0237f5bd132986bdcc66f80bc9bcc300066a03"}, + {file = "matplotlib-3.9.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7ff2e239c26be4f24bfa45860c20ffccd118d270c5b5d081fa4ea409b5469fcd"}, + {file = "matplotlib-3.9.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:af4001b7cae70f7eaacfb063db605280058246de590fa7874f00f62259f2df7e"}, + {file = "matplotlib-3.9.0.tar.gz", hash = "sha256:e6d29ea6c19e34b30fb7d88b7081f869a03014f66fe06d62cc77d5a6ea88ed7a"}, ] [package.dependencies] @@ -502,12 +503,15 @@ contourpy = ">=1.0.1" cycler = ">=0.10" fonttools = ">=4.22.0" kiwisolver = ">=1.3.1" -numpy = ">=1.21" +numpy = ">=1.23" packaging = ">=20.0" pillow = ">=8" pyparsing = ">=2.3.1" python-dateutil = ">=2.7" +[package.extras] +dev = ["meson-python (>=0.13.1)", "numpy (>=1.25)", "pybind11 (>=2.6)", "setuptools (>=64)", "setuptools_scm (>=7)"] + [[package]] name = "mypy" version = "1.10.0" @@ -913,13 +917,13 @@ diagrams = ["jinja2", "railroad-diagrams"] [[package]] name = "pytest" -version = "8.2.0" +version = "8.2.1" description = "pytest: simple powerful testing with Python" optional = false python-versions = ">=3.8" files = [ - {file = "pytest-8.2.0-py3-none-any.whl", hash = "sha256:1733f0620f6cda4095bbf0d9ff8022486e91892245bb9e7d5542c018f612f233"}, - {file = "pytest-8.2.0.tar.gz", hash = "sha256:d507d4482197eac0ba2bae2e9babf0672eb333017bcedaa5fb1a3d42c1174b3f"}, + {file = "pytest-8.2.1-py3-none-any.whl", hash = "sha256:faccc5d332b8c3719f40283d0d44aa5cf101cec36f88cde9ed8f2bc0538612b1"}, + {file = "pytest-8.2.1.tar.gz", hash = "sha256:5046e5b46d8e4cac199c373041f26be56fdb81eb4e67dc11d4e10811fc3408fd"}, ] [package.dependencies]