Plotly Dash change networkx node colours in based on user input? - python

After creating the minimal working example below, I tried to change the color of the nodes in the graphs based on user input. Specifically, I have n lists of colors (one color per node), and I would like the user to be able to loop (ideally forward and backwards) through the node color lists. (In essence I show firing neurons using the color).
MWE
"""Generates a graph in dash."""
import dash
import dash_core_components as dcc
import dash_html_components as html
import networkx as nx
import plotly.graph_objs as go
# Create graph G
G = nx.DiGraph()
G.add_nodes_from([0, 1, 2])
G.add_edges_from(
[
(0, 1),
(0, 2),
],
weight=6,
)
# Create a x,y position for each node
pos = {
0: [0, 0],
1: [1, 2],
2: [2, 0],
}
# Set the position attribute with the created positions.
for node in G.nodes:
G.nodes[node]["pos"] = list(pos[node])
# add color to node points
colour_set_I = ["rgb(31, 119, 180)", "rgb(255, 127, 14)", "rgb(44, 160, 44)"]
colour_set_II = ["rgb(10, 20, 30)", "rgb(255, 255, 0)", "rgb(0, 255, 255)"]
# Create nodes
node_trace = go.Scatter(
x=[],
y=[],
text=[],
mode="markers",
hoverinfo="text",
marker=dict(size=30, color=colour_set_I),
)
for node in G.nodes():
x, y = G.nodes[node]["pos"]
node_trace["x"] += tuple([x])
node_trace["y"] += tuple([y])
# Create Edges
edge_trace = go.Scatter(
x=[],
y=[],
line=dict(width=0.5, color="#888"),
hoverinfo="none",
mode="lines",
)
for edge in G.edges():
x0, y0 = G.nodes[edge[0]]["pos"]
x1, y1 = G.nodes[edge[1]]["pos"]
edge_trace["x"] += tuple([x0, x1, None])
edge_trace["y"] += tuple([y0, y1, None])
################### START OF DASH APP ###################
app = dash.Dash()
fig = go.Figure(
data=[edge_trace, node_trace],
layout=go.Layout(
xaxis=dict(showgrid=True, zeroline=True, showticklabels=True),
yaxis=dict(showgrid=False, zeroline=False, showticklabels=False),
),
)
app.layout = html.Div(
[
html.Div(dcc.Graph(id="Graph", figure=fig)),
]
)
if __name__ == "__main__":
app.run_server(debug=True)
When you save this as graph.py and run it with: python graph.py, you can open a browser, go to 127.0.0.1:8050 and see:
For colour_set_I, and:
For colour_set_II.
Question
How can I get a slider e.g. from 0 to n or a next> and back< button that loads the next/previous colour list into the nodes?
Hacky
I noticed when I change the graph.py file line:
marker=dict(size=30, color=colour_set_I),
to:
marker=dict(size=30, color=colour_set_II),
it automatically updates the node colors, however, typing the frame index into the colour set and pressing ctrl+s is somewhat elaborate, even though I thoroughly enjoy keyboard control over clicking.

You can use the dash_core_components.Slider component to add a slider to your app that allows the user to change the color of the nodes.You would need to add a callback function that updates the marker color based on the slider value, and use a state variable to keep track of the current color set being displayed.
from dash.dependencies import Input, Output
app = dash.Dash(__name__)
# State variable to keep track of current color set
color_set_index = 0
color_sets = [colour_set_I, colour_set_II]
app.layout = html.Div(
[
dcc.Slider(
id='color-set-slider',
min=0,
max=len(color_sets) - 1,
value=0,
marks={i: str(i) for i in range(len(color_sets))},
step=None
),
html.Div(dcc.Graph(id="Graph", figure=fig))
]
)
#app.callback(
Output("Graph", "figure"),
[Input("color-set-slider", "value")]
)
def update_color(color_set_index):
fig.data[1]["marker"]["color"] = color_sets[color_set_index]
return fig
if __name__ == "__main__":
app.run_server(debug=True)

Here is an example that also updates the directed edge colours for a directed graph. Note it uses annotations as arrows instead of actual lines.
"""Generates a graph in dash."""
from typing import List, Tuple
import dash
import networkx as nx
import plotly
import plotly.graph_objs as go
from dash import dcc, html
from dash.dependencies import Input, Output
# Create graph G
G = nx.DiGraph()
G.add_nodes_from([0, 1, 2])
G.add_edges_from(
[
(0, 1),
(0, 2),
],
weight=6,
)
# Create a x,y position for each node
pos = {
0: [0, 0],
1: [1, 2],
2: [2, 0],
}
# Set the position attribute with the created positions.
for node in G.nodes:
G.nodes[node]["pos"] = list(pos[node])
# add color to node points
colour_set_I = ["rgb(31, 119, 180)", "rgb(255, 127, 14)", "rgb(44, 160, 44)"]
colour_set_II = ["rgb(10, 20, 30)", "rgb(255, 255, 0)", "rgb(0, 255, 255)"]
# Create edge colour lists.
# TODO: make edge colour function of edges
def set_edge_colours() -> List[List[str]]:
"""(Manually) set edge colours into list."""
hardcoded_edge_colours = [
[
"rgb(31, 119, 180)", # edge(0,1)
"rgb(255, 127, 14)", # edge(0,2)
],
[
"rgb(10, 20, 30)", # edge(0,1)
"rgb(255, 255, 0)", # edge(0,2)
],
]
return hardcoded_edge_colours
def get_edge_colour(
t: int, edge: Tuple[int, int], edge_colours: List[List[str]]
) -> str:
"""Returns an edge colour based on edge
TODO: support duplicate edges between nodes."""
if edge == (0, 1):
return edge_colours[t][0]
if edge == (0, 2):
return edge_colours[t][1]
raise ValueError(f"Error, edge{edge} not found.")
# Load edge colour list.
edge_colours: List[List[str]] = set_edge_colours()
# Create nodes
node_trace = go.Scatter(
x=[],
y=[],
text=[],
mode="markers",
hoverinfo="text",
marker=dict(size=30, color=colour_set_I),
)
for node in G.nodes():
x, y = G.nodes[node]["pos"]
node_trace["x"] += tuple([x])
node_trace["y"] += tuple([y])
# Create figure
fig = go.Figure(
# data=[edge_trace, node_trace],
data=[node_trace],
layout=go.Layout(
height=700, # height of image in pixels.
width=1000, # Width of image in pixels.
annotations=[
dict(
ax=G.nodes[edge[0]]["pos"][0], # starting x.
ay=G.nodes[edge[0]]["pos"][1], # starting y.
axref="x",
ayref="y",
x=G.nodes[edge[1]]["pos"][0], # ending x.
y=G.nodes[edge[1]]["pos"][1], # ending y.
xref="x",
yref="y",
arrowwidth=5, # Width of arrow.
arrowcolor="red", # Overwrite in update/using user input.
arrowsize=0.8, # (1 gives head 3 times as wide as arrow line)
showarrow=True,
arrowhead=1, # the arrowshape (index).
hoverlabel=plotly.graph_objs.layout.annotation.Hoverlabel(
bordercolor="red"
),
hovertext="sometext",
text="sometext",
# textangle=-45,
# xanchor='center',
# xanchor='right',
# swag=120,
)
for edge in G.edges()
],
),
)
# Start Dash app.
app = dash.Dash(__name__)
#app.callback(Output("Graph", "figure"), [Input("color-set-slider", "value")])
def update_color(color_set_index: int) -> go.Figure:
"""Updates the colour of the nodes and edges based on user input."""
# Update the annotation colour.
def annotation_colour(
some_val: int,
edge_colours: List[List[str]],
edge: Tuple[int, int],
) -> str:
"""Updates the colour of the edges based on user input."""
return get_edge_colour(
t=some_val, edge=edge, edge_colours=edge_colours
)
# Overwrite annotation with function instead of value.
for i, edge in enumerate(G.edges()):
some_annotation_colour = annotation_colour(
color_set_index, edge_colours=edge_colours, edge=edge
)
print(f"edge={edge}")
print(f"some_annotation_colour={some_annotation_colour}")
fig.layout.annotations[i].arrowcolor = some_annotation_colour
# update the node colour
fig.data[0]["marker"]["color"] = color_sets[color_set_index] # nodes
return fig
# State variable to keep track of current color set
initial_color_set_index = 0
color_sets = [colour_set_I, colour_set_II]
fig = update_color(initial_color_set_index)
app.layout = html.Div(
[
dcc.Slider(
id="color-set-slider",
min=0,
max=len(color_sets) - 1,
value=0,
marks={i: str(i) for i in range(len(color_sets))},
step=None,
),
html.Div(dcc.Graph(id="Graph", figure=fig)),
]
)
if __name__ == "__main__":
app.run_server(debug=True)
Yields:
And here is a more elaborate example, which allows for rotated edge labels, even after stretching the image, as well as recursive edges with labels (both edges are updated based on user selection):
"""Generates a graph in dash."""
from typing import Dict, List, Tuple
import dash
import networkx as nx
import numpy as np
import plotly
import plotly.graph_objs as go
from dash import dcc, html
from dash.dependencies import Input, Output
pixel_width = 1000
pixel_height = 1000
recursive_edge_radius = 0.1
# Create graph G
G = nx.DiGraph()
G.add_nodes_from([0, 1, 2])
G.add_edges_from(
[
(0, 1),
(0, 2),
],
weight=6,
)
# Create a x,y position for each node
pos = {
0: [0, 0],
1: [1, 2],
2: [2, 0],
}
# Set the position attribute with the created positions.
for node in G.nodes:
G.nodes[node]["pos"] = list(pos[node])
# add color to node points
colour_set_I = ["rgb(31, 119, 180)", "rgb(255, 127, 14)", "rgb(44, 160, 44)"]
colour_set_II = ["rgb(10, 20, 30)", "rgb(255, 255, 0)", "rgb(0, 255, 255)"]
# Create edge colour lists.
# TODO: make edge colour function of edges
def set_edge_colours() -> List[List[str]]:
"""(Manually) set edge colours into list."""
hardcoded_edge_colours = [
[
"rgb(31, 119, 180)", # edge(0,1)
"rgb(255, 127, 14)", # edge(0,2)
],
[
"rgb(10, 20, 30)", # edge(0,1)
"rgb(255, 255, 0)", # edge(0,2)
],
]
return hardcoded_edge_colours
def get_edge_colour(
t: int,
edge: Tuple[int, int],
edge_colours: List[List[str]], # pylint: disable = W0621
) -> str:
"""Returns an edge colour based on edge
TODO: support duplicate edges between nodes."""
if edge == (0, 1):
return edge_colours[t][0]
if edge == (0, 2):
return edge_colours[t][1]
raise ValueError(f"Error, edge{edge} not found.")
# pylint: disable = W0621
def get_edge_arrows(G: nx.DiGraph) -> List[Dict]:
"""Returns the annotation dictionaries representing the directed edge
arrows."""
annotations: List[Dict] = []
for edge in G.edges:
# Get coordinates
left_node_name = edge[0]
right_node_name = edge[1]
left_x = G.nodes[left_node_name]["pos"][0]
left_y = G.nodes[left_node_name]["pos"][1]
right_x = G.nodes[right_node_name]["pos"][0]
right_y = G.nodes[right_node_name]["pos"][1]
# Add annotation.
annotations.append(
dict(
ax=left_x,
ay=left_y,
axref="x",
ayref="y",
x=right_x,
y=right_y,
xref="x",
yref="y",
arrowwidth=5, # Width of arrow.
arrowcolor="red", # Overwrite in update/using user input.
arrowsize=0.8, # (1 gives head 3 times as wide as arrow line)
showarrow=True,
arrowhead=1, # the arrowshape (index).
hoverlabel=plotly.graph_objs.layout.annotation.Hoverlabel(
bordercolor="red"
),
hovertext="sometext",
text="sometext",
# textangle=-45,
# xanchor='center',
# xanchor='right',
# swag=120,
)
)
return annotations
# pylint: disable = W0621
def get_edge_labels(G: nx.DiGraph) -> List[Dict]:
"""Returns the annotation dictionaries representing the labels of the
directed edge arrows."""
annotations = []
for edge in G.edges:
mid_x, mid_y = get_edge_mid_point(edge)
annotations.append(
go.layout.Annotation(
x=mid_x,
y=mid_y,
xref="x",
yref="y",
text="dict Text",
align="center",
showarrow=False,
yanchor="bottom",
textangle=get_stretched_edge_angle(
edge, pixel_height=pixel_height, pixel_width=pixel_width
),
)
)
return annotations
# pylint: disable = W0621
def get_recursive_edge_labels(G: nx.DiGraph, radius: float) -> List[Dict]:
"""Returns the annotation dictionaries representing the labels of the
recursive edge circles above the nodes. Note, only place 1 radius above
pos, because recursive edge circles are.
actually ovals with height: radius, width:2 * radius.
"""
annotations = []
for node in G.nodes:
x, y = G.nodes[node]["pos"]
annotations.append(
go.layout.Annotation(
x=x,
y=y + 1 * radius,
xref="x",
yref="y",
text="recur",
align="center",
showarrow=False,
yanchor="bottom",
)
)
return annotations
def get_edge_mid_point(
edge: Tuple[Tuple[int, int], Tuple[int, int]]
) -> Tuple[int, int]:
"""Returns the mid point of an edge."""
left_node_name = edge[0]
right_node_name = edge[1]
left_x = G.nodes[left_node_name]["pos"][0]
left_y = G.nodes[left_node_name]["pos"][1]
right_x = G.nodes[right_node_name]["pos"][0]
right_y = G.nodes[right_node_name]["pos"][1]
mid_x = (right_x + left_x) / 2
mid_y = (right_y + left_y) / 2
return mid_x, mid_y
def get_stretched_edge_angle(
edge: Tuple[Tuple[int, int], Tuple[int, int]],
pixel_height: int,
pixel_width: int,
) -> Tuple[int, int]:
"""Returns the ccw+ mid point of an edge and adjusts for stretching of the
image."""
left_node_name = edge[0]
right_node_name = edge[1]
left_x = G.nodes[left_node_name]["pos"][0]
left_y = G.nodes[left_node_name]["pos"][1]
right_x = G.nodes[right_node_name]["pos"][0]
right_y = G.nodes[right_node_name]["pos"][1]
dx = (right_x - left_x) * (
1 - ((pixel_height - pixel_width) / pixel_height)
)
# dx =
dy = right_y - left_y
angle = np.arctan2(dy, dx)
# return -np.rad2deg((angle) % (2 * np.pi))
return -np.rad2deg(angle)
def get_pure_edge_angle(
edge: Tuple[Tuple[int, int], Tuple[int, int]]
) -> Tuple[int, int]:
"""Returns the ccw+ mid point of an edge."""
left_node_name = edge[0]
right_node_name = edge[1]
left_x = G.nodes[left_node_name]["pos"][0]
left_y = G.nodes[left_node_name]["pos"][1]
right_x = G.nodes[right_node_name]["pos"][0]
right_y = G.nodes[right_node_name]["pos"][1]
dx = right_x - left_x
dy = right_y - left_y
angle = np.arctan2(dy, dx)
# return -np.rad2deg((angle) % (2 * np.pi))
return -np.rad2deg(angle)
def get_annotations(G: nx.DiGraph) -> List[Dict]:
"""Returns the annotations for this graph."""
annotations = []
annotations.extend(get_edge_arrows(G))
annotations.extend(get_edge_labels(G))
annotations.extend(
get_recursive_edge_labels(G, radius=recursive_edge_radius)
)
return annotations
def add_recursive_edges(G: nx.DiGraph, fig: go.Figure, radius: float) -> None:
"""Adds a circle, representing a recursive edge, above a node.
The circle line/edge colour is updated along with the node colour.
"""
for node in G.nodes:
x, y = G.nodes[node]["pos"]
# Add circles
fig.add_shape(
type="circle",
xref="x",
yref="y",
x0=x - radius,
y0=y,
x1=x + radius,
y1=y + radius,
line_color=colour_set_I[node],
)
# Load edge colour list.
edge_colours: List[List[str]] = set_edge_colours()
# Create nodes
node_trace = go.Scatter(
x=[],
y=[],
text=[],
mode="markers",
hoverinfo="text",
marker=dict(size=30, color=colour_set_I),
)
for node in G.nodes():
x, y = G.nodes[node]["pos"]
node_trace["x"] += tuple([x])
node_trace["y"] += tuple([y])
# Create figure
fig = go.Figure(
# data=[edge_trace, node_trace],
data=[node_trace],
layout=go.Layout(
height=pixel_height, # height of image in pixels.
width=pixel_width, # Width of image in pixels.
annotations=get_annotations(G),
),
)
add_recursive_edges(G=G, fig=fig, radius=recursive_edge_radius)
# Start Dash app.
app = dash.Dash(__name__)
#app.callback(Output("Graph", "figure"), [Input("color-set-slider", "value")])
def update_color(color_set_index: int) -> go.Figure:
"""Updates the colour of the nodes and edges based on user input."""
# Update the annotation colour.
def annotation_colour(
some_val: int,
edge_colours: List[List[str]],
edge: Tuple[int, int],
) -> str:
"""Updates the colour of the edges based on user input."""
return get_edge_colour(
t=some_val, edge=edge, edge_colours=edge_colours
)
# Overwrite annotation with function instead of value.
for i, edge in enumerate(G.edges()):
some_annotation_colour = annotation_colour(
color_set_index, edge_colours=edge_colours, edge=edge
)
fig.layout.annotations[i].arrowcolor = some_annotation_colour
# Update the node colour.
fig.data[0]["marker"]["color"] = color_sets[color_set_index] # nodes
# Update the recursive edge node colour.
for node_name in G.nodes:
fig.layout.shapes[node_name]["line"]["color"] = color_sets[
color_set_index
][node_name]
return fig
# State variable to keep track of current color set
initial_color_set_index = 0
color_sets = [colour_set_I, colour_set_II]
fig = update_color(initial_color_set_index)
app.layout = html.Div(
[
dcc.Slider(
id="color-set-slider",
min=0,
max=len(color_sets) - 1,
value=0,
marks={i: str(i) for i in range(len(color_sets))},
step=None,
),
html.Div(dcc.Graph(id="Graph", figure=fig)),
]
)
if __name__ == "__main__":
app.run_server(debug=True)
Yields:

Related

How do I change the color of the area inside the lines?

I'm using python matplotlib and here's my code. I want to change the cyan color inside the lines. How would I go about doing that? Also, if you know how to change the background color, that would also be much appreciated! Thank you, I'm a newbie at this...
Consequently, if you also know how to turn the inner circles into polygons like the outer hexagonal shape, please tell that to me too. Thank you! I've been looking for how to do this change yet nothing came up yet.
import os
import RadarGraph
from pprint import pprint
from string import Template
import matplotlib.pyplot as plt
import numpy as np
from matplotlib.patches import Circle, RegularPolygon
from matplotlib.path import Path
from matplotlib.projections.polar import PolarAxes
from matplotlib.projections import register_projection
from matplotlib.spines import Spine
from matplotlib.transforms import Affine2D
os.chdir(os.path.dirname(os.path.abspath(__file__)))
def radar_factory(num_vars, frame='circle'):
"""Create a radar chart with `num_vars` axes.
This function creates a RadarAxes projection and registers it.
Parameters
----------
num_vars : int
Number of variables for radar chart.
frame : {'circle' | 'polygon'}
Shape of frame surrounding axes.
"""
# calculate evenly-spaced axis angles
theta = np.linspace(0, 2*np.pi, num_vars, endpoint=False)
class RadarAxes(PolarAxes):
name = 'radar'
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
# rotate plot such that the first axis is at the top
self.set_theta_zero_location('N')
def fill(self, *args, closed=True, **kwargs):
"""Override fill so that line is closed by default"""
return super().fill(closed=closed, *args, **kwargs)
def plot(self, *args, **kwargs):
"""Override plot so that line is closed by default"""
lines = super().plot(*args, **kwargs)
for line in lines:
self._close_line(line)
def _close_line(self, line):
x, y = line.get_data()
# FIXME: markers at x[0], y[0] get doubled-up
if x[0] != x[-1]:
x = np.concatenate((x, [x[0]]))
y = np.concatenate((y, [y[0]]))
line.set_data(x, y)
def set_varlabels(self, labels):
self.set_thetagrids(np.degrees(theta), labels)
def _gen_axes_patch(self):
# The Axes patch must be centered at (0.5, 0.5) and of radius 0.5
# in axes coordinates.
if frame == 'circle':
return Circle((0.5, 0.5), 0.5)
elif frame == 'polygon':
return RegularPolygon((0.5, 0.5), num_vars,
radius=.5, edgecolor="k")
else:
raise ValueError("unknown value for 'frame': %s" % frame)
def draw(self, renderer):
""" Draw. If frame is polygon, make gridlines polygon-shaped """
if frame == 'polygon':
gridlines = self.yaxis.get_gridlines()
for gl in gridlines:
gl.get_path()._interpolation_steps = num_vars
super().draw(renderer)
def _gen_axes_spines(self):
if frame == 'circle':
return super()._gen_axes_spines()
elif frame == 'polygon':
# spine_type must be 'left'/'right'/'top'/'bottom'/'circle'.
spine = Spine(axes=self,
spine_type='circle',
path=Path.unit_regular_polygon(num_vars))
# unit_regular_polygon gives a polygon of radius 1 centered at
# (0, 0) but we want a polygon of radius 0.5 centered at (0.5,
# 0.5) in axes coordinates.
spine.set_transform(Affine2D().scale(.5).translate(.5, .5)
+ self.transAxes)
return {'polar': spine}
else:
raise ValueError("unknown value for 'frame': %s" % frame)
register_projection(RadarAxes)
return theta
plt.style.use("dark_background")
data = [
["Defense", "Damage ", "Soloing ", "Farming", "Support", " Group\n DPS", "PVP"],
("Class Stats",[
# [5, 3, 4, 4, 0, 0, 4], #Abyssal
# [2, 0, 0, 0, 0, 0, 4],
# [5, 5, 5, 5, 5, 5, 4],
[6, 3, 4, 3, 4, 3, 4],
])
]
N = len(data[0])
theta = RadarGraph.radar_factory(N, frame='circle')
spoke_labels = data.pop(0)
title, case_data = data[0]
fig, ax = plt.subplots(figsize=(5.5, 5), subplot_kw=dict(projection='radar'))
fig.subplots_adjust(top=0.85, bottom=0.05)
ax.set_rgrids(radii=[0, 1, 2, 3, 4, 5, 6], labels=[" ", "D", "C", "B", "A", "S", "SS"], angle=180)
ax.set_title(title, position=(0.5, 1.1), ha='center')
ax.set_ylim([0,6])
for d in case_data:
line = ax.plot(theta, d)
ax.fill(theta, d, alpha=0.25)
ax.set_varlabels(spoke_labels)
fig.savefig("./demo_.png", transparent=False)
plt.show
()

How can I get Class label from Mosaic augmentation in Object Detection Dataloader?

I'm trying to train an object detection model for a multi-class problem. In my training, I am using the Mosaic augmentation, Paper, for this task.
In my training mechanism, I'm a bit stuck to properly retrieving the class labels of each category, as the augmentation mechanism randomly picks the sub-portion of a sample. However, below is a result of a mosaic augmentation that we've achieved with a relevant bounding box until now.
Data Set
I've created a dummy data set. The df.head():
It has 4 class in total and df.object.value_counts():
human 23
car 13
cat 5
dog 3
Data Loader and Mosaic Augmentation
The data loader is defined as follows. However, the mosaic augmentation should be defined inside but for now, I'll create a separate code snippet for better demonstration:
IMG_SIZE = 2000
class DatasetRetriever(Dataset):
def __init__(self, main_df, image_ids, transforms=None, test=False):
super().__init__()
self.image_ids = image_ids
self.main_df = main_df
self.transforms = transforms
self.size_limit = 1
self.test = test
def __getitem__(self, index: int):
image_id = self.image_ids[index]
image, boxes, labels = self.load_mosaic_image_and_boxes(index)
# labels = torch.tensor(labels, dtype=torch.int64) # for multi-class
labels = torch.ones((boxes.shape[0],), dtype=torch.int64) # for single-class
target = {}
target['boxes'] = boxes
target['cls'] = labels
target['image_id'] = torch.tensor([index])
if self.transforms:
for i in range(10):
sample = self.transforms(**{
'image' : image,
'bboxes': target['boxes'],
'labels': target['cls']
})
assert len(sample['bboxes']) == target['cls'].shape[0], 'not equal!'
if len(sample['bboxes']) > 0:
# image
image = sample['image']
# box
target['boxes'] = torch.tensor(sample['bboxes'])
target['boxes'][:,[0,1,2,3]] = target['boxes'][:,[1,0,3,2]]
# label
target['cls'] = torch.stack(sample['labels'])
break
return image, target
def __len__(self) -> int:
return self.image_ids.shape[0]
Basic Transform
def get_transforms():
return A.Compose(
[
A.Resize(height=IMG_SIZE, width=IMG_SIZE, p=1.0),
ToTensorV2(p=1.0),
],
p=1.0,
bbox_params=A.BboxParams(
format='pascal_voc',
min_area=0,
min_visibility=0,
label_fields=['labels']
)
)
Mosaic Augmentation
Note, It should be defined inside the data loader. The main issue is, in this augmentation, while iterating will all 4 samples to create such augmentation, image and bounding_box is rescaled as follows:
mosaic_image[y1a:y2a, x1a:x2a] = image[y1b:y2b, x1b:x2b]
offset_x = x1a - x1b
offset_y = y1a - y1b
boxes[:, 0] += offset_x
boxes[:, 1] += offset_y
boxes[:, 2] += offset_x
boxes[:, 3] += offset_y
In this way, how would I select the relevant class labels for those selected bounding_box? Please, see the full code below:
def load_mosaic_image_and_boxes(self, index, s=3000,
minfrac=0.25, maxfrac=0.75):
self.mosaic_size = s
xc, yc = np.random.randint(s * minfrac, s * maxfrac, (2,))
# random other 3 sample
indices = [index] + random.sample(range(len(self.image_ids)), 3)
mosaic_image = np.zeros((s, s, 3), dtype=np.float32)
final_boxes = [] # box for the sub-region
final_labels = [] # relevant class labels
for i, index in enumerate(indices):
image, boxes, labels = self.load_image_and_boxes(index)
if i == 0: # top left
x1a, y1a, x2a, y2a = 0, 0, xc, yc
x1b, y1b, x2b, y2b = s - xc, s - yc, s, s # from bottom right
elif i == 1: # top right
x1a, y1a, x2a, y2a = xc, 0, s , yc
x1b, y1b, x2b, y2b = 0, s - yc, s - xc, s # from bottom left
elif i == 2: # bottom left
x1a, y1a, x2a, y2a = 0, yc, xc, s
x1b, y1b, x2b, y2b = s - xc, 0, s, s-yc # from top right
elif i == 3: # bottom right
x1a, y1a, x2a, y2a = xc, yc, s, s
x1b, y1b, x2b, y2b = 0, 0, s-xc, s-yc # from top left
# calculate and apply box offsets due to replacement
offset_x = x1a - x1b
offset_y = y1a - y1b
boxes[:, 0] += offset_x
boxes[:, 1] += offset_y
boxes[:, 2] += offset_x
boxes[:, 3] += offset_y
# cut image, save boxes
mosaic_image[y1a:y2a, x1a:x2a] = image[y1b:y2b, x1b:x2b]
final_boxes.append(boxes)
'''
ATTENTION:
Need some mechanism to get relevant class labels
'''
final_labels.append(labels)
# collect boxes
final_boxes = np.vstack(final_boxes)
final_labels = np.hstack(final_labels)
# clip boxes to the image area
final_boxes[:, 0:] = np.clip(final_boxes[:, 0:], 0, s).astype(np.int32)
w = (final_boxes[:,2] - final_boxes[:,0])
h = (final_boxes[:,3] - final_boxes[:,1])
# discard boxes where w or h <10
final_boxes = final_boxes[(w>=self.size_limit) & (h>=self.size_limit)]
return mosaic_image, final_boxes, final_labels
I parsed the bounding box and class label information at the same time.
Below is the output that we've achieved. To try it with your own data set, for a starter.

Set coordinate origin plotly python

This is my code:
trace1 = go.Scatterpolar(
r = r,
theta = theta,
mode='markers',
marker=dict(
size=12,
color= iris.target,
opacity=1
)
)
dc_1 = go.Scatterpolar( r = [0,V_r[0][0]],
theta = [0,V_r[0][1]],
marker = dict( size = 1,
color = "rgb(84,48,5)"),
line = dict( color = "red",
width = 6),
name = "Var1"
)
dc_2 = go.Scatterpolar( r = [0,V_r[1][0]],
theta = [0,V_r[1][1]],
marker = dict( size = 1,
color = "rgb(84,48,5)"),
line = dict( color = "green",
width = 6),
name = "Var2"
)
dc_3 = go.Scatterpolar( r = [0,V_r[2][0]],
theta = [0,V_r[2][1]],
marker = dict( size = 1,
color = "rgb(84,48,5)"),
line = dict( color = "blue",
width = 6),
name = "Var3"
)
dc_4 = go.Scatterpolar( r = [0,V_r[3][0]],
theta = [0,V_r[3][1]],
marker = dict( size = 1,
color = "rgb(84,48,5)"),
line = dict( color = "yellow",
width = 6),
name = "Var4"
)
data = [dc_1,dc_2,dc_3,dc_4, trace1]
layout = go.Layout(
xaxis=dict(
title='PC1',
rangemode='tozero',
titlefont=dict(
family='Courier New, monospace',
size=18,
color='#080707'
)
)
)
fig = go.Figure(data=data, layout=layout)
plot(fig, filename='Scatter polar, PCA.')
And this is the graph resultant:
enter image description here
As you can see, currently the lines of the variables start from "0", but the origin of coordinates is in r = - 5 (since that is the first value it receives) how can I set it to r = 0?
r has to be represented in absolute value, since the address gives you the value of theta. r cannot be < 0:
r = abs(np.squeeze(np.asarray(P[:,0])))
theta = (np.squeeze(np.asarray(P[:,1])))*(180/math.pi)

How create a slider for a custom chorpleth map using plotly in python?

I'm create a choropleth map using plotly, geojso and matplotlib. Now i want to add a slider.
i'm using python3 and i can't find a answer for this in the internet.all of them used plotly's default choropleth map.
def get_scatter_colors(sm, df):
grey = 'rgba(128,128,128,1)'
return ['rgba' + str(sm.to_rgba(m, bytes = True, alpha = 1)) if not np.isnan(m) else grey for m in df]
for age in columns[3:24]:
age_data = df[age]
age_data.name = 'province'
# print(age_data.head())
df_tmp = age_data.copy()
df_tmp.index = df_tmp.index.map(match_dict)
df_tmp = df_tmp[~df_tmp.index.duplicated(keep=False)]
df_reindexed = df_tmp.reindex(index = provinces_names)
colormap = 'Blues'
cmin = df_reindexed.min()
cmax = df_reindexed.max()
sm = scalarmappable(colormap, cmin, cmax)
scatter_colors = get_scatter_colors(sm, df_reindexed)
colorscale = get_colorscale(sm, df_reindexed, cmin, cmax)
hover_text = get_hover_text(df_reindexed)
scatter_color_list.append(scatter_colors)
tickformat = ""
data = dict(type='scattermapbox',
lat=lats,
lon=lons,
mode='markers',
text=hover_text,
marker=dict(size=10,
color=scatter_colors,
showscale = True,
cmin = df_reindexed.min(),
cmax = df_reindexed.max(),
colorscale = colorscale,
colorbar = dict(tickformat = tickformat)
),
showlegend=False,
hoverinfo='text'
)
data_slider.append(data)
layers=([dict(sourcetype = 'geojson',
source =sources[k],
below="",
type = 'line', # the borders
line = dict(width = 1),
color = 'black',
) for k in range(n_provinces)
] +
# fill_list
[dict(sourcetype = 'geojson',
source =sources[k],
below="water",
type = 'fill',
color = scatter_colors[k],
opacity=0.8,
) for k in range(n_provinces)
]
)
steps = []
for i in range(len(data_slider)):
step = dict(method='restyle',
args=['visible', [False] * len(data_slider)],
label='Age {}' .format(i))
step['args'][1][i] = True
steps.append(step)
sliders = [dict(active=0, steps=steps)]
layout = dict(title="2016 POPULATION",
autosize=False,
width=700,
height=800,
hovermode='closest',
# hoverdistance = 30,
mapbox=dict(accesstoken=MAPBOX_APIKEY,
layers=layers,
bearing=0,
center=dict(
lat=35.715298,
lon=51.404343),
pitch=0,
zoom=4.9,
style = 'light'),
sliders=sliders,
)
when i test this code with data, i want changing color of the map with slides , but the color of map is fixed by the lastest slide color.
Edit step part like this:
visibility = []
for i in range(len(data_slider)):
list = [False] * len(data_slider)
list[i] = True
visibility.append(list)
steps = []
for i in range(len(data_slider)):
step = dict(method='update',
args=[{'visible': visibility[i]},
{'mapbox.layers': layers[i]}],
label='Age {}' .format(i),)
steps.append(step)
And add function for layers:
def get_data_layout(df):
layers = []
for i in range(len(data_slider)):
scatter_colors = df[i]['marker']['color']
layer=([dict(sourcetype = 'geojson',
source =sources[k],
below="",
type = 'line',
line = dict(width = 1),
color = 'black',
) for k in range(n_provinces)
] +
[dict(sourcetype = 'geojson',
source =sources[k],
below="water",
type = 'fill',
color = scatter_colors[k],
opacity=0.8,
) for k in range(n_provinces)]
)
layers.append(layer)
return layers
and change layout to this:
layout = dict(title="IRAN 2016 POPULATION",
autosize=False,
width=700,
height=800,
hovermode='closest',
mapbox=dict(accesstoken=MAPBOX_APIKEY,
bearing=0,
center=dict(
lat=35.715298,
lon=51.404343),
pitch=0,
zoom=4.9,
style = 'dark'),
sliders=sliders,
)
other parts are same:))

3D biplot in Plotly in Python

I want to plot something like a biplot in python Plotly ,but using 3 principal components so as to make a 3d plot.
How do I go about plotting the direction vectors(the red lines) of principal components in plotly python?
There is exactly the same question , but for R, here. I am not able to translate the code perfectly.
With much help from here
from plotly.offline import plot
import plotly.graph_objs as go
pca = PCA(n_components=3).fit(iris.data)
X_reduced = pca.transform(iris.data)
trace1 = go.Scatter3d(
x=X_reduced[:,0],
y = X_reduced[:,1],
z = X_reduced[:,2],
mode='markers',
marker=dict(
size=12,
color= target,
opacity=1
)
)
dc_1 = go.Scatter3d( x = [0,pca.components_.T[0][0]],
y = [0,pca.components_.T[0][1]],
z = [0,pca.components_.T[0][2]],
marker = dict( size = 1,
color = "rgb(84,48,5)"),
line = dict( color = "red",
width = 6),
name = "Var1"
)
dc_2 = go.Scatter3d( x = [0,pca.components_.T[1][0]],
y = [0,pca.components_.T[1][1]],
z = [0,pca.components_.T[1][2]],
marker = dict( size = 1,
color = "rgb(84,48,5)"),
line = dict( color = "green",
width = 6),
name = "Var2"
)
dc_3 = go.Scatter3d( x = [0,pca.components_.T[2][0]],
y = [0,pca.components_.T[2][1]],
z = [0,pca.components_.T[2][2]],
marker = dict( size = 1,
color = "rgb(84,48,5)"),
line = dict( color = "blue",
width = 6),
name = "Var3"
)
dc_4 = go.Scatter3d( x = [0,pca.components_.T[3][0]],
y = [0,pca.components_.T[3][1]],
z = [0,pca.components_.T[3][2]],
marker = dict( size = 1,
color = "rgb(84,48,5)"),
line = dict( color = "yellow",
width = 6),
name = "Var4"
)
data = [trace1,dc_1,dc_2,dc_3,dc_4]
layout = go.Layout(
xaxis=dict(
title='PC1',
titlefont=dict(
family='Courier New, monospace',
size=18,
color='#7f7f7f'
)
)
)
fig = go.Figure(data=data, layout=layout)
plot(fig, filename='3d-scatter-tupac-with-mac')

Categories