Related
I have made a pbiviz custom visual using developer tools of Normal distribution curve over a Histogram plot with R - ggplot2 and plotly libraries in a pbiviz.package
The visual works fine. Now I want to add interactivity of the Histogram with other Power BI visuals.
i.e. If user clicks on a bar of the Histogram, it should filter out a Table on my PBI report with rows relevant to the histogram bar data.
Considering the limitations of using R script with Power BI, I do not know if it is possible with my current visual as I am new to scripting.
Is there a better way (Typescript, JS, Python, etc.) other than what I have done to make an Interactive Histogram & Distribution Curve in Power BI?
This is the R script along with sample data and Visual Image
Histogram represents the projects falling in different durations
There are two bell curves - One for closed projects and Other for Active Projects
source('./r_files/flatten_HTML.r')
############### Library Declarations ###############
libraryRequireInstall("ggplot2");
libraryRequireInstall("plotly");
libraryRequireInstall("tidyverse");
libraryRequireInstall("scales");
libraryRequireInstall("htmlwidgets");
library(ggplot2)
library(tidyverse)
library(scales)
library(plotly)
theme_set(theme_bw())
##### Making DataSet for All Selected Projects #####
Duration <- dataset$Duration
Status <- (rep(dataset$ProjectStatus))
da <- data.frame(Duration,Status)
lenx <- length(Duration)
meanall <- mean(da$Duration)
sdx <- sd(da$Duration)
binwidth <- 30
font_label <- list(family = "Segoe UI", size = 21, colour = "black")
hovlabel <- list(bordercolor = "black", font = font_label)
#Filtering Out Closed Projects from Dataset
#Creating Data Frame for Closed Projects
closedproj <- dataset %>%
select(Duration,ProjectStatus) %>%
filter(ProjectStatus == "Closed")
closed <- closedproj$Duration
df <- data.frame(closed)
xclosed <- closedproj$
df2 <- data.frame(xclosed)
lenc <- length(xclosed)
mean_closed <- mean(df2$xclosed)
sdc <- sd(df2$xclosed)
a <-
(ggplot(da,aes(x=Duration, fill = Status, text = paste("Duration: ",x,"-", x + binwidth,"<br />Project Count", ..count..)))+
#Histogram
geom_histogram(aes(y=..count..),alpha=0.5, position='identity',binwidth = binwidth)+
# #Distribution Curve
annotate(
geom = "line",
x = da$Duration,
y = dnorm(da$Duration, mean = meanall, sd = sdx) * lenx * binwidth,
width = 3,
color = "red"
) +
annotate(
geom = "line",
x = df2$xclosed,
y = dnorm(df2$xclosed, mean = mean_closed, sd = sdc)* lenc * binwidth,
width = 3,
color = "blue"
) +
labs(
x = "Project Duration (Days)",
y = "Project_Count",
fill = "Project Status")+
#Mean
geom_vline(aes(xintercept=meanall),color="red",linetype="dashed",size = 0.8,label=paste("Mean :",round(meanall,0)))+
geom_vline(aes(xintercept=mean_closed),color="blue",linetype="dashed",size = 0.8,label=paste("Mean (Closed):",round(mean_closed,0)))+
# 1 Sigma
geom_vline(aes(xintercept = (meanall + sdx)), color = "red", size = 1, linetype = "dashed") +
geom_vline(aes(xintercept = (meanall - sdx)), color = "red", size = 1, linetype = "dashed")+
geom_vline(aes(xintercept = (mean_closed + sdc)), color = "blue", size = 1, linetype = "dashed") +
geom_vline(aes(xintercept = (mean_closed - sdc)), color = "blue", size = 1, linetype = "dashed")+
# Theme
theme(
plot.background = element_rect(fill = "transparent"),
legend.background = element_rect(fill = "lightgray"),
axis.title.x = element_text(colour = "Black",size = 18,face = "bold"),
axis.title.y = element_text(colour = "Black",size = 18,face = "bold"),
axis.text.x = element_text(colour = "Black",size = 15),
axis.text.y = element_text(colour = "Black",size = 15),
panel.grid.major = element_blank(), panel.grid.minor = element_blank())+
scale_x_continuous(labels = comma,
breaks = seq(0, max(Duration),50)) +
scale_y_continuous(labels = comma,
breaks = seq(0,max(Duration),10)))
############# Create and save widget ###############
p = ggplotly(a, tooltip = c("text")) %>%
style(hoverlabel = hovlabel) %>%
layout(legend = list(
orientation = "h",
x = 0,
y = 1.13,
title = list(text = "Project Status",font = list(family = "Segoe UI", size = 23)),
font = font_label
),
yaxis = list(title = list(standoff = 25L)),
xaxis = list(title = list(standoff = 25L)),
annotations = list(showarrow=FALSE,align = "left",valign = "top",x = 0.95, xref = "paper",yref = "paper",y = 0.955,
font = list(family = "Segoe UI", size = 22, color = "#cc0000"),
text = paste("Max Duration: ", comma(round(max(da$Duration),0)),
"<br>Mean (Closed): ", comma(round(mean_closed,0)),
"<br>Mean (All) : ", comma(round(meanall,0))))
) %>%
config(modeBarButtonsToRemove = c("select2d","hoverClosestCartesian", "lasso2d","hoverCompareCartesian","toggleSpikelines"), displaylogo = FALSE);
internalSaveWidget(p, 'out.html');
}
####################################################
################ Reduce paddings ###################
ReadFullFileReplaceString('out.html', 'out.html', ',"padding":[0-5]*,', ',"padding":0,')
What I expect is -- If user clicks on a bar of the Histogram, it should reflect on a Table visual on my PBI report with rows relevant to the histogram bar data.
Any help will be highly appreciated !
Regards
It seems we don't have an np.delete equivalent in libtorch yet, so how can we emulate its behavior? For example I'm trying to rewrite the following bit of code in libtorch:
ids = np.delete( ids, np.concatenate([[last], np.where(overlap > overlap_threshold)[0]] ) )
How should I go about this? I thought about slicing, but I'm not sure if there are implications involved that I'm not aware of. This is what I came up with:
neg = torch.where(overlap < overlap_threshold)[0]
ids = ids[neg].clone()
libtorch:
auto neg = torch::where(overlap <over_threshold)[0];
ids.index_put_({Slice()}, ids.index({neg}));
//or simply
ids = ids.index({neg}).clone();
And this is an example demo to test out their result is the same:
x1 = np.asarray([125.,152., 155., 155., 202.])
y1 = np.asarray( [52., 72., 92., 95., 95.])
x2 = np.asarray( [145., 172., 175., 175., 222.])
y2 = np.asarray( [ 72., 92., 112., 115., 115.])
score = np.asarray([0.60711509, 0.63444906, 0.85604602, 0.60021192, 0.70115328])
area = (x2 - x1 + 1.0) * (y2 - y1 + 1.0)
ids = np.argsort(score)
overlap_threshold = 0.5
mode = 'union'
while len(ids) > 0:
# grab index of the largest value
last = len(ids) - 1
i = ids[last]
# left top corner of intersection boxes
ix1 = np.maximum(x1[i], x1[ids[:last]])
iy1 = np.maximum(y1[i], y1[ids[:last]])
# right bottom corner of intersection boxes
ix2 = np.minimum(x2[i], x2[ids[:last]])
iy2 = np.minimum(y2[i], y2[ids[:last]])
# width and height of intersection boxes
w = np.maximum(0.0, ix2 - ix1 + 1.0)
h = np.maximum(0.0, iy2 - iy1 + 1.0)
# intersections' areas
inter = w * h
if mode == 'min':
overlap = inter / np.minimum(area[i], area[ids[:last]])
elif mode == 'union':
# intersection over union (IoU)
overlap = inter / (area[i] + area[ids[:last]] - inter)
# delete all boxes where overlap is too big
# ids = np.delete(ids,np.concatenate([[last], np.where(overlap > overlap_threshold)[0]]))
neg = np.where(overlap <= overlap_threshold)[0]
ids = ids[neg]
print(f'ids: {ids}')
And here is the cpp counter part in libtorch:
void test5()
{
auto x1 = torch::tensor({ 125., 152., 155., 155., 202. });
auto y1 = torch::tensor({ 52., 72., 92., 95., 95. });
auto x2 = torch::tensor({ 145., 172., 175., 175., 222. });
auto y2 = torch::tensor({ 72., 92., 112., 115., 115. });
auto score = torch::tensor({ 0.60711509, 0.63444906, 0.85604602, 0.60021192, 0.70115328 });
auto area = (x2 - x1 + 1.0) * (y2 - y1 + 1.0);
auto ids = torch::argsort(score);
auto overlap_threshold = 0.5;
auto mode = "union";
while (ids.sizes()[0] > 0)
{
//# grab index of the largest value
auto last = ids.sizes()[0] - 1;
auto i = ids[last];
//# left top corner of intersection boxes
auto ix1 = torch::max(x1[i], x1.index({ ids.index({ Slice(None,last) }) }));
auto iy1 = torch::max(y1[i], y1.index({ ids.index({ Slice(None,last) }) }));
//# right bottom corner of intersection boxes
auto ix2 = torch::min(x2[i], x2.index({ ids.index({Slice(None,last)}) }));
auto iy2 = torch::min(y2[i], y2.index({ ids.index({Slice(None,last)}) }));
//# width and height of intersection boxes
auto w = torch::max(torch::tensor(0.0), ix2 - ix1 + 1.0);
auto h = torch::max(torch::tensor(0.0), iy2 - iy1 + 1.0);
//# intersections' areas
auto inter = w * h;
torch::Tensor overlap;
if (mode == "min")
{
overlap = inter / torch::min(area[i], area.index({ ids.index({Slice(None,last)}) }));
}
else if (mode == "union")
{ //# intersection over union (IoU)
overlap = inter / (area[i] + area.index({ ids.index({Slice(None,last)}) }) - inter);
}
//# delete all boxes where overlap is too big
//# ids = np.delete(ids, np.concatenate([[last], np.where(overlap > overlap_threshold)[0]] ))
auto neg = torch::where(overlap < overlap_threshold)[0];
ids = ids.index({ neg });
std::cout << "ids: " << ids << std::endl;
}
}
Both of them print the same output, so is there something that I'm missing here or this is actually the reasonable way of implementing delete in libtorch?
What other possibly more efficient ways do I have to implement/emulate np.delete()?
It seems this is the reasonable way of doing it as pointed out in the comments. That is to reverse the condition and only filter out based on the new condition.
I also would like to fix a slight issue in my original post.
the correct form that would be equivalent to the Pythons :
ids = np.delete(ids, np.concatenate([[last], np.where(overlap > overlap_threshold)[0]] ))
would be :
auto neg = torch::where(overlap <= overlap_threshold)[0];
ids = ids.index({ neg });
mind the <=!
I'm trying to find the points of intersection between the line passing through point V and conic. The conic graph is not solvable relative to y ( or x), so it was depicted using contour. Is there a method for finding the intersection points of contour graphs?
enter image description here
Here is the code:
import numpy as np
import matplotlib.pyplot as plt
p = (input("choose point P on axis OX: "))
print(p)
q = (input("choose point Q on axis OX: "))
print(q)
v = (input("choose point V on axis OX: "))
print(v)
k=3
X = np.arange(-50, 50, 0.05)
Y = k*X
plt.plot(X,Y)
plt.plot(0,0)
plt.scatter(0.0, 0.0, color='white', marker='o')
plt.text(0.0, 0.0, "O", horizontalalignment="center")
plt.plot(-v,0)
plt.scatter(-v, 0, color='red', marker='o')
plt.text(-v, 0.8, "V", horizontalalignment="center")
xmin= -10
xmax= 10
ymin= -10
ymax= 10
ax = plt.gca()
ax.get_xlim()
ax.set_xlim([xmin,xmax])
ax.set_ylim([ymin,ymax])
ax.spines['left'].set_position('center')
ax.spines['bottom'].set_position('center')
ax.spines['top'].set_visible(False)
ax.spines['right'].set_visible(False)
#Create random point B1
b1=4
plt.plot(0.0,b1)
plt.scatter(0.0, b1, color='blue', marker='o')
plt.text(0.8, b1, "B1", horizontalalignment="center")
x, y = np.meshgrid(X, X)
#Create VB1
l3 = b1*x+b1*v - v*y
vb = plt.contour(x,y, l3, [0], colors='k')
# l3 = b1*X/v + b1
# plt.plot(X,l3)
#Create conic
conic = x*x*b1*2*p*k-x*x*b1*2*q*k+x*x*k*k+y*y-b1*2*y+2*b1*q*x*y
cnc = plt.contour(x, y, (conic), [0], colors='k')
I tried to do something like that:
c = cnc.intersection(vb)
print(c)
or
# https://stackoverflow.com/questions/28766692/intersection-of-two-graphs-in-python-find-the-x-value
idx = np.argwhere(np.diff(np.sign(cnc - vb))).flatten()
plt.plot(x[idx], y[idx], 'ro')
My last attempt:
import numpy as np
import matplotlib.pyplot as plt
p,q,v,k,b=5,7,2,3,4
X = np.arange(-50, 50, 0.05)
plt.plot(-v,0)
plt.scatter(-v, 0, color='red', marker='o')
plt.text(-v, 0.8, "V", horizontalalignment="center")
xmin,xmax,ymin,ymax=-10,10,-10,10
ax = plt.gca()
ax.get_xlim()
ax.set_xlim([xmin,xmax])
ax.set_ylim([ymin,ymax])
ax.spines['left'].set_position('center')
ax.spines['bottom'].set_position('center')
ax.spines['top'].set_visible(False)
ax.spines['right'].set_visible(False)
plt.plot(0.0,b)
plt.scatter(0.0, 1, color='blue', marker='o')
x, y = np.meshgrid(X, X)
l = b*x+b*v-v*y
vb = plt.contour(x,y, l, [0], colors='k')
conic = x*x*b*2*p*k-x*x*b*2*q*k+x*x*k*k+y*y-b*2*y+2*b*q*x*y
cnc = plt.contour(x, y, (conic), [0], colors='k')
c = cnc.collections[0].get_paths()[1]
v = c.vertices
x1 = v[:,0]
y1 = v[:,1]
plt.plot(x1,y1)
vb1 = vb.collections[0].get_paths()[0]
v1 = vb1.vertices
x2 = v1[:,0]
y2 = v1[:,1]
plt.plot(x2,y2,color='red')
# def find_roots(x,y):
# s = np.abs(np.diff(np.sign(y))).astype(bool)
# return x[:-1][s] + np.diff(x)[s]/(np.abs(y[1:][s]/y[:-1][s])+1)
#
# z = find_roots(x1-x2,y1-y2)
# plt.plot(z, np.zeros(len(z)), marker="o", ls="", ms=4)
plt.show()
enter image description here
It's a little more complicated. The problem is that (a) the points in the contour are not necessarily sorted and (b) the two contours do not have a common support.
So one would need to (a) sort the points along x, and (b) create an array of common values, on which to interpolate first.
import numpy as np
import matplotlib.pyplot as plt
p,q,v,k,b=5,7,2,3,4
X = np.arange(-50, 50, 0.05)
plt.plot(-v,0)
plt.scatter(-v, 0, color='red', marker='o')
plt.text(-v, 0.8, "V", horizontalalignment="center")
xmin,xmax,ymin,ymax=-10,10,-10,10
ax = plt.gca()
ax.get_xlim()
ax.set_xlim([xmin,xmax])
ax.set_ylim([ymin,ymax])
ax.spines['left'].set_position('center')
ax.spines['bottom'].set_position('center')
ax.spines['top'].set_visible(False)
ax.spines['right'].set_visible(False)
x, y = np.meshgrid(X, X)
l = b*x+b*v-v*y
vb = plt.contour(x,y, l, [0], colors='red')
conic = x*x*b*2*p*k-x*x*b*2*q*k+x*x*k*k+y*y-b*2*y+2*b*q*x*y
cnc = plt.contour(x, y, (conic), [0], colors='blue')
c = cnc.collections[0].get_paths()[1]
v = c.vertices
x1 = np.sort(v[:,0])
y1 = v[np.argsort(v[:,0]),1]
vb1 = vb.collections[0].get_paths()[0]
v1 = vb1.vertices
x2 = np.sort(v1[:,0])
y2 = v1[np.argsort(v1[:,0]),1]
def find_roots(x,y):
s = np.abs(np.diff(np.sign(y))).astype(bool)
return x[:-1][s] + np.diff(x)[s]/(np.abs(y[1:][s]/y[:-1][s])+1)
x = np.linspace(max(x1.min(), x2.min()), min(x1.max(), x2.max()), 1000)
y1i = np.interp(x, x1, y1 ) # blue
y2i = np.interp(x, x2, y2 ) # red
x_intersect = find_roots(x,y2i-y1i)
y_intersect = np.interp(x_intersect, x, y2i)
plt.plot(x_intersect, y_intersect, marker="X", ms=5, color="limegreen")
plt.show()
The point of intersection is the green dot.
Of course one needs to do the same for the other arm of the conic contour (cnc.collections[0].get_paths()[0]) if desired.
I am using wx.python along with VPython to make an orbit simulator, however i'm having trouble trying to get the sliders in the GUI to effect the simulation, I assume it's because I am trying to get the number associated with the slider button to go into a while loop when it is running.
So my question is, how do i get the function SetRate to update in the while loop located at the bottom of the code? (I have checked to see that the slider is retuning values)
Here is my code for reference:
Value = 1.0
dt = 100.0
def InputValue(Value):
dt = Value
def SetRate(evt):
global Value
Value = SpeedOfSimulation.GetValue()
return Value
w = window(menus=True, title="Planetary Orbits",x=0, y=0, width = 1000, height = 1000)
Screen = display(window = w, x = 30, y = 30, width = 700, height = 500)
gdisplay(window = w, x = 80, y = 80 , width = 40, height = 20)
p = w.panel # Refers to the full region of the window in which to place widgets
SpeedOfSimulation = wx.Slider(p, pos=(800,10), size=(200,100), minValue=0, maxValue=1000)
SpeedOfSimulation.Bind(wx.EVT_SCROLL, SetRate)
TestData = [2, 0, 0, 0, 6371e3, 5.98e24, 0, 0, 0, 384400e3, 0, 0, 1737e3, 7.35e22, 0, 1e3, 0]
Nstars = TestData[0] # change this to have more or fewer stars
G = 6.7e-11 # Universal gravitational constant
# Typical values
Msun = 2E30
Rsun = 2E9
vsun = 0.8*sqrt(G*Msun/Rsun)
Stars = []
colors = [color.red, color.green, color.blue,
color.yellow, color.cyan, color.magenta]
PositionList = []
MomentumList = []
MassList = []
RadiusList = []
for i in range(0,Nstars):
s=i*8
x = TestData[s+1]
y = TestData[s+2]
z = TestData[s+3]
Radius = TestData[s+4]
Stars = Stars+[sphere(pos=(x,y,z), radius=Radius, color=colors[i % 6],
make_trail=True, interval=10)]
Mass = TestData[s+5]
SpeedX = TestData[s+6]
SpeedY = TestData[s+7]
SpeedZ = TestData[s+8]
px = Mass*(SpeedX)
py = Mass*(SpeedY)
pz = Mass*(SpeedZ)
PositionList.append((x,y,z))
MomentumList.append((px,py,pz))
MassList.append(Mass)
RadiusList.append(Radius)
pos = array(PositionList)
Momentum = array(MomentumList)
Mass = array(MassList)
Mass.shape = (Nstars,1) # Numeric Python: (1 by Nstars) vs. (Nstars by 1)
Radii = array(RadiusList)
vcm = sum(Momentum)/sum(Mass) # velocity of center of mass
Momentum = Momentum-Mass*vcm # make total initial momentum equal zero
Nsteps = 0
time = clock()
Nhits = 0
while True:
InputValue(Value) #Reprensents the change in time
rate(100000) #No more than 100 loops per second on fast computers
# Compute all forces on all stars
r = pos-pos[:,newaxis] # all pairs of star-to-star vectors (Where r is the Relative Position Vector
for n in range(Nstars):
r[n,n] = 1e6 # otherwise the self-forces are infinite
rmag = sqrt(sum(square(r),-1)) # star-to-star scalar distances
hit = less_equal(rmag,Radii+Radii[:,newaxis])-identity(Nstars)
hitlist = sort(nonzero(hit.flat)[0]).tolist() # 1,2 encoded as 1*Nstars+2
F = G*Mass*Mass[:,newaxis]*r/rmag[:,:,newaxis]**3 # all force pairs
for n in range(Nstars):
F[n,n] = 0 # no self-forces
Momentum = Momentum+sum(F,1)*dt
# Having updated all momenta, now update all positions
pos = pos+(Momentum/Mass)*dt
# Update positions of display objects; add trail
for i in range(Nstars):
Stars[i].pos = pos[i]
I know nothing about vpython but in a normal wxPython app, you will use wx.Timer instead of while loop.
here is an example of wx.Timer modified from https://www.blog.pythonlibrary.org/2009/08/25/wxpython-using-wx-timers/
You will want to separate the while loop part from your SetRate class method and put it in update.
import wx
class MyForm(wx.Frame):
def __init__(self):
wx.Frame.__init__(self, None, wx.ID_ANY, "Timer Tutorial 1",
size=(500,500))
# Add a panel so it looks the correct on all platforms
panel = wx.Panel(self, wx.ID_ANY)
self.timer = wx.Timer(self)
self.Bind(wx.EVT_TIMER, self.update, self.timer)
SpeedOfSimulation = wx.Slider(p, pos=(800,10), size=(200,100), minValue=0, maxValue=1000)
SpeedOfSimulation.Bind(wx.EVT_SCROLL, SetRate)
self.SpeedOfSimulation = SpeedOfSimulation
def update(self, event):
# Compute all forces on all stars
SpeedOfSimulation = self.SpeedOfSimulation.GetValue()
I can't figure out why I'm getting this index out of bounds error. I've done test prints of the values at those indices and they print out correctly. Can someone explain where exactly my array is being restructured?
class Particle:
def __init__(self,fourvector = [1.0,1.0,1.0,-1.0],
origin=(0,0)):
self.mass = 2.5 # Mass in kg
self.fourvector = np.asarray(fourvector,dtype='float')
self.Vx_init = self.fourvector[2]
self.x_init = self.fourvector[0]
self.y_init = self.fourvector[1]
self.Vy_init = self.fourvector[3]
self.time_passed = 0
self.origin = origin
print fourvector[0]
print fourvector[2]
def position(self):
x0 = self.origin[0]
x1 = self.fourvector[0]
Vx = self.fourvector[2]
y0 = self.origin[1]
y1 = self.fourvector[1]
Vy = self.fourvector[3]
x = x0 + x1 * Vx
y = x0 + y1 * Vy
return (x,y)
def derivs(self,fourvector):
'''derivative computation setup'''
x_pos = fourvector[0]
y_pos = fourvector[1]
dydx = np.zeros_like(fourvector)
dydx[0] = fourvector[2] #x-comp of velocity
dydx[1] = (-x_pos)/((x_pos)**2 + (y_pos)**2)**1.5
dydx[2] = fourvector[3] #y-comp of velocity
dydx[3] = (-y_pos)/((x_pos)**2 + (y_pos)**2)**1.5
return dydx
def time_step(self,dt):
'''Time progression and state fourvector update'''
self.fourvector = integrate.odeint(self.derivs,0,dt)
self.time_passed += dt
body = Particle([1.0,1.0,1.0,2.0]) #Object of Particle created.
dt = 1./30
fig = plt.figure()
ax = fig.add_subplot(111,aspect='equal',autoscale_on=False,xlim=(-3,3),ylim=(-3,3))
ax.grid()
line, = ax.plot([],[],'o-',lw=2)
time_text = ax.text(0.02,0.95,'',transform=ax.transAxes)
def init():
line.set_data([],[])
time_text.set_text('')
return line, time_text
def animate(i):
global body, dt
body.time_step(dt)
line.set_data(*body.position())
time_text.set_text('time = %.1f' %body.time_passed)
return line, time_text
from time import time
t0 = time()
animate(0)
t1 = time()
interval = 1000*dt - (t1 - t0)
ani = animation.FuncAnimation(fig, animate, frames = 300,
interval = interval, blit=True, init_func=init)
plt.show()
The error traceback:
bash-3.2$ python MoreCrap.py
1.0
1.0
Traceback (most recent call last):
File "MoreCrap.py", line 80, in <module>
animate(0)
File "MoreCrap.py", line 74, in animate
line.set_data(*body.position())
File "MoreCrap.py", line 26, in position
Vx = self.fourvector[2]
IndexError: index out of bounds
Your call to integrate.odeint is wrong. Look in the manual if it really does what you think.
In any case, the fourvector has value [1. 1. 1. 2.] before the call to it and value [[0.]] after the call to it, so it doesn't contain any value with index [2].
The manpage for odeint is here.