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')