<jupyter_start><jupyter_text>Plotly plot of the kmapper graph associated to the breast cancer dataset<jupyter_code>import sys
try:
    import pandas as pd
except ImportError as e:
    print("pandas is required for this example. Please install with conda or pip  and then try again.")
    sys.exit()

import numpy as np
import sklearn
from sklearn import ensemble
import kmapper as km
from kmapper.plotlyviz import *

import warnings
warnings.filterwarnings("ignore")
import plotly.graph_objs as go
from ipywidgets import (HBox, VBox)
# Data - the Wisconsin Breast Cancer Dataset
# https://www.kaggle.com/uciml/breast-cancer-wisconsin-data
df = pd.read_csv("data.csv")
feature_names = [c for c in df.columns if c not in ["id", "diagnosis"]]
df["diagnosis"] = df["diagnosis"].apply(lambda x: 1 if x == "M" else 0)
X = np.array(df[feature_names].fillna(0))
y = np.array(df["diagnosis"])

# Create a custom 1-D lens with Isolation Forest
model = ensemble.IsolationForest(random_state=1729)
model.fit(X)
lens1 = model.decision_function(X).reshape((X.shape[0], 1))

# Create another 1-D lens with L2-norm
mapper = km.KeplerMapper(verbose=0)
lens2 = mapper.fit_transform(X, projection="l2norm")

# Combine both lenses to get a 2-D [Isolation Forest, L^2-Norm] lens
lens = np.c_[lens1, lens2]

# Define the simplicial complex
scomplex = mapper.map(lens,
                      X,
                      cover = km.Cover(n_cubes = 15, 
                                       perc_overlap=0.7),
                      clusterer=sklearn.cluster.KMeans(n_clusters=2,
                                                       random_state=3471))<jupyter_output><empty_output><jupyter_text>First we visualize the resulting graph via a   `color_function` that associates to lens data   their  x-coordinate distance to min, and  colormap these coordinates  to a given Plotly colorscale. Here we use the brewer colorscale with hex color codes.<jupyter_code>pl_brewer = [[0.0, '#006837'],
             [0.1, '#1a9850'],
             [0.2, '#66bd63'],
             [0.3, '#a6d96a'],
             [0.4, '#d9ef8b'],
             [0.5, '#ffffbf'],
             [0.6, '#fee08b'],
             [0.7, '#fdae61'],
             [0.8, '#f46d43'],
             [0.9, '#d73027'],
             [1.0, '#a50026']]
color_values = lens [:,0] - lens[:,0].min()
my_colorscale = pl_brewer
kmgraph,  mapper_summary, colorf_distribution = get_mapper_graph(scomplex, 
                                                                 color_values,  
                                                                 color_function_name='Distance to x-min', 
                                                                 colorscale=my_colorscale)

# assign to node['custom_tooltips']  the node label (0 for benign, 1 for malignant)
for node in kmgraph['nodes']:
    node['custom_tooltips'] = y[scomplex['nodes'][node['name']]]<jupyter_output><empty_output><jupyter_text>Since the chosen colorscale leads  to a few light colors when it it used for histogram bars,we set a black background color to make the bars visible:<jupyter_code>bgcolor = 'rgba(10,10,10, 0.9)'
y_gridcolor = 'rgb(150,150,150)'# on a black background the gridlines are set on  grey
plotly_graph_data = plotly_graph(kmgraph, graph_layout='fr', colorscale=my_colorscale, 
                                 factor_size=2.5, edge_linewidth=0.5)
layout = plot_layout(title='Topological network representing the<br>  breast cancer  dataset',  
                     width=620, height=570,
                     annotation_text=get_kmgraph_meta(mapper_summary),  
                     bgcolor=bgcolor)

fw_graph = go.FigureWidget(data=plotly_graph_data, layout=layout)
fw_hist = node_hist_fig(colorf_distribution, bgcolor=bgcolor,
                        y_gridcolor=y_gridcolor)
fw_summary = summary_fig(mapper_summary, height=300)
dashboard = hovering_widgets(kmgraph, 
                             fw_graph, 
                             ctooltips=True, # ctooltips = True, because we assigned a label to each 
                                             #cluster member
                             bgcolor=bgcolor,
                             y_gridcolor=y_gridcolor, 
                             member_textbox_width=600)

#Update the fw_graph colorbar, setting its title:
    
fw_graph.data[1].marker.colorbar.title = 'dist to<br>x-min'

VBox([fw_graph, HBox([fw_summary, fw_hist])])
dashboard<jupyter_output><empty_output><jupyter_text>In the following we illustrate how  we can duplicate FigureWidget(s) and update them. This is just a pretext toillustrate how the kmapper graph figure can be manipulated for a more in-depth study or for publication. Here we duplicate the initial FigureWidget, `fw_graph`,  and recolor its  graph nodes according to the proportion of malignant members. The two FigureWidgets are then restyled and plotted alonside each other for comparison.<jupyter_code>breastc_dict = {0: 'benign', 1: 'malignant'}
tooltips = list(fw_graph.data[1].text) # we perform this conversion because fw.data[1].text is a tuple and we want to update
                                     # the tooltips

new_color = []
for j, node in enumerate(kmgraph['nodes']):
    member_label_ids = y[scomplex['nodes'][node['name']]]
    member_labels = [breastc_dict[id] for id in member_label_ids]
    label_type, label_counts = np.unique(member_labels, return_counts=True) 
    
    n_members = label_counts.sum()
    if label_type.shape[0] == 1:
        if label_type[0] == 'benign':
            new_color.append(0)
        else:
            new_color.append(1)
    else:        
        new_color.append(1.0*label_counts[1]/n_members)#multiply by 1 for python 2.7.+
       
    for m in range(len(label_counts)):
        tooltips[j] += '<br>' + str(label_type[m]) + ': ' + str(label_counts[m]) # append  how many benign/malign 
                                                                                 # members exist in each node

fwn_graph = go.FigureWidget(fw_graph) # copy the initial FigureWidget

with fwn_graph.batch_update(): # make updates for the new figure                                                                
    fwn_graph.data[1].text = tooltips # add the new tooltips
    fwn_graph.data[1].marker.colorbar.x = -0.14 # place toolbar at the figure left side
    fwn_graph.layout.width = 550 # change the figure size in order to plot two "parallel" copies
    fwn_graph.layout.height = 550
    fwn_graph.layout.margin.r = 45 # decrease the right margin from 60px (default val) to 45 pixels
    
fw1 = go.FigureWidget(fwn_graph) # define a new figure from  the fwn_graph that will be colored by the new color function  
with fw1.batch_update():
    fw1.data[1].marker.color = new_color # update node colors
    fw1.data[0].line.color = 'rgb(125,125,125)' # update the graph edge color
    fw1.layout.plot_bgcolor = 'rgb(240,240,240)'
    fw1.layout.annotations = None # remove the mapper_summary from the second plot
    fw1.data[1].marker.showscale = False # remove the colorbar
    fw1.layout.title = "Nodes are colored according to the proportion<br> of malignant members"<jupyter_output><empty_output><jupyter_text>Plot  the dashboard consisting in the two figures:<jupyter_code>HBox([fwn_graph, fw1])<jupyter_output><empty_output><jupyter_text>To save any of the FigureWidgets generated above uncomment the two lines  in the next cell, and replace `fw_graph` and the name of pdf fileadequately:<jupyter_code>#import plotly.io as pio
#pio.write_image(fw_graph, 'breast-graph1.pdf') # or png, swg<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.09695290858725762, 'fraction_numerical': 0.02506265664160401, 'mean_word_length': 2.6859504132231407, 'pattern_counts': {'":': 0, '<': 29, '<?xml version=': 0, '>': 29, 'https://': 1, 'lorem ipsum': 0, 'www.': 1, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 18, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '6', 'dir': 'jupyter-structured-clean-dedup', 'id': '283990', 'license': 'MIT', 'n_tokens_mistral': 2443, 'n_tokens_neox': 2287, 'n_words': 643, 'path': 'examples/breast-cancer/breast-cancer.ipynb', 'repo_name': 'kcw0331/kepler-mapper', 'size': '7581'}