Callback for multivalue dropdown - plotly-dash

I am pretty new to Plotly Dash and have been struggling especially with multivalue dropdown callback and would really appreciate any help. Basically I've followed a tutorial and created a pie-chart if a single pillar(from my data) value is selected. I would like to achieve two things:
The default or initial chart should show all pillar and the number of projects
Multi selection of pillar values
My main issue is actually the creating the callback for these. Thank you in advance for any help!!
Here is my code
app = dash.Dash(__name__)
all = df.Pillar.unique()
app.layout=html.Div([
html.H1("PM dashboard"),
dcc.Dropdown(id='pillar-choice',
options=[{'label':x, 'value':x}
for x in all],
value='Service Provider',
multi=False),
dcc.Graph(id='my-graph',
figure={}),
])
#app.callback(
Output(component_id='my-graph', component_property='figure'),
Input(component_id='pillar-choice', component_property='value')
)
def interactive_graphs(value_pillar):
print(value_pillar)
dff = df[df.Pillar==value_pillar]
fig = px.pie(data_frame=dff, names='Pillar', values='Project No')
return fig
if __name__=='__main__':
app.run_server()

I think the problem here is that value_pillar will be a list, so you need to do something like:
dff = df[df.Pillar.isin(value_pillar)]
And if you want to show everything by default, you'll need to check the value of that argument for your default value and, if it matches the default, avoid filtering.

Related

Plot on higher time frame. Security, mutable variable, global variable, function problem

I'm trying to plot the same shape from the 15 min onto the Daily as well. This is the code to plot a shape on the 15 min which works fine;
if crossover(s3K,s3D) and s3K<25 and (s4K-s4D<3 and s4K-s4D>-3) and s4K<35//or s4D-s4K>0 and s4D-s4K<1 and s4K<50 and s1K<40
rwCross:=true
plotshape(rwCross, style = shape.arrowup, location = location.belowbar, color=color.yellow, size=size.small)
But to plot it on the daily i've tried;
rwCrossDaily = security(syminfo.tickerid,'D', rwCross)
plotshape(rwCrossDaily, style = shape.arrowup, location = location.belowbar, color=color.yellow, size=size.small)
Which gives me the mutable variable error. So i tried using a function to get around it;
rwCross_func() =>
if crossover(s3K,s3D) and s3K<25 and (s4K-s4D<3 and s4K-s4D>-3) and s4K<35//or s4D-s4K>0 and s4D-s4K<1 and s4K<50 and s1K<40
rwCross:=true
rwCrossDaily = security(syminfo.tickerid,'D', rwCross_func())
But now it tells me I 'Cannot modify global variable 'rwCross' in function.'
Help please!
Best solution and cleanest solution here is to just make a bool out of your condition in its simplest form:
rwCross = crossover(s3K,s3D) and s3K<25 and (s4K-s4D<3 and s4K-s4D>-3) and s4K<35//or s4D-s4K>0 and s4D-s4K<1 and s4K<50 and s1K<40
rwCross will naturally become true without the if. This way we do not need to have anything mutable, although there are more solutions for situations that we must...
Cheers!

Trying to define a function that creates lists from files and uses random.choices to choose an element from the weighted lists

I'm trying to define a function that will create lists from multiple text files and print a random element from one of the weighted lists. I've managed to get the function to work with random.choice for a single list.
enter code here
def test_rollitems():
my_commons = open('common.txt')
all_common_lines = my_commons.readlines()
common = []
for i in all_common_lines:
common.append(i)
y = random.choice(common)
print(y)
When I tried adding a second list to the function it wouldn't work and my program just closes when the function is called.
enter code here
def Improved_rollitem():
#create the lists from the files#
my_commons = open('common.txt')
all_common_lines= my_commons.readlines()
common = []
for i in all_common_lines:
common.append(i)
my_uncommons = open('uncommon.txt')
all_uncommon_lines =my_uncommons.readlines()
uncommon =[]
for i in all_uncommon_lines:
uncommon.apend(i)
y = random.choices([common,uncommon], [80,20])
print(y)
Can anyone offer any insight into what I'm doing wrong or missing ?
Nevermind. I figured this out on my own! Was having issues with Geany so I installed Pycharm and was able to work through the issue. Correct code is:
enter code here
def Improved_rollitem():
#create the lists from the files#
my_commons = open('common.txt')
all_common_lines= my_commons.readlines()
common = []
for i in all_common_lines:
common.append(i)
my_uncommons = open('uncommon.txt')
all_uncommon_lines =my_uncommons.readlines()
uncommon =[]
for i in all_uncommon_lines:
uncommon.append(i)
y = random.choices([common,uncommon], [.8,.20])
if y == [common]:
for i in [common]:
print(random.choice(i))
if y == [uncommon]:
for i in [uncommon]:
print(random.choice(i))
If there's a better way to do something like this, it would certainly be cool to know though.

PyTorch Experience Replay with multiple inputs

I am running a modified version of the pyTorch deep Q tutorial which I have modified to pass in my own data rather than gym, and one additional input (two inputs in total)
Currently I am generating an individual state for each 'column' of inputs (not sure if this is the correct way though), when trying to pass the second input into my experience replay function it is returning:
__new__() takes 5 positional arguments but 7 were given
Code for expReplay():
class ReplayMemory(object):
def __init__(self, capacity):
self.capacity = capacity
self.memory = []
self.position = 0
def push(self, *args):
"""Saves a transition."""
if len(self.memory) < self.capacity:
self.memory.append(None)
self.memory[self.position] = Transition(*args)
self.position = (self.position + 1) % self.capacity
def sample(self, batch_size):
return random.sample(self.memory, batch_size)
def __len__(self):
return len(self.memory)
And my Triggering of the function:
memory.push(state,rsistate, action, next_state, next_rsi_state, reward)
If anyone has any examples of experience replay using multiple inputs please fire away! <3
My mistake, this was solved by modifying the Transition named tuple to include the additional inputs. Any information on multi input expreplay is still welcome.

"focus" widget in list but keep cursor in another

using urwid, I'm trying to separate the highlight/walk and cursor functionality of a Pile widget. How can I use up/down to change which widget is highlighted, while keeping the cursor in a different widget?
The default focus behavior couples the cursor with attribute (highlighting) behavior. The example below shows one way to decouple these, where a list of SelectableIcons retains the highlight feature, while the cursor is moved to a separate Edit widget. It does this via:
overriding the keypress method to update the focus where the cursor is not
wrapping each SelectableIcon in AttrMap that change their attribute based on their Pile's focus_position
after changing the SelectableIcon attributes, the focus (cursor) is set back to the Edit widget via focus_part='body'
self._w = ... is called to update all widgets on screen
There may be more concise ways of doing this, but this should be rather flexible.
import urwid
def main():
my_widget = MyWidget()
palette = [('unselected', 'default', 'default'),
('selected', 'standout', 'default', 'bold')]
urwid.MainLoop(my_widget, palette=palette).run()
class MyWidget(urwid.WidgetWrap):
def __init__(self):
n = 10
labels = ['selection {}'.format(j) for j in range(n)]
self.header = urwid.Pile([urwid.AttrMap(urwid.SelectableIcon(label), 'unselected', focus_map='selected') for label in labels])
self.edit_widgets = [urwid.Edit('', label + ' edit_text') for label in labels]
self.body = urwid.Filler(self.edit_widgets[0])
super().__init__(urwid.Frame(header=self.header, body=self.body, focus_part='body'))
self.update_focus(new_focus_position=0)
def update_focus(self, new_focus_position=None):
self.header.focus_item.set_attr_map({None: 'unselected'})
try:
self.header.focus_position = new_focus_position
self.body = urwid.Filler(self.edit_widgets[new_focus_position])
except IndexError:
pass
self.header.focus_item.set_attr_map({None: 'selected'})
self._w = urwid.Frame(header=self.header, body=self.body, focus_part='body')
def keypress(self, size, key):
if key == 'up':
self.update_focus(new_focus_position=self.header.focus_position - 1)
if key == 'down':
self.update_focus(new_focus_position=self.header.focus_position + 1)
if key in {'Q', 'q'}:
raise urwid.ExitMainLoop()
super().keypress(size, key)
main()
If you really need this, it probably makes sense to write your own widgets -- maybe based on some classes extending urwid.Text and urwid.Button
There is no real "highlight" feature in the widgets that come with urwid, there is only a "focus" feature, and it doesn't seem to be easy to decouple the focus highlight from the focus behavior.
You probably want to implement your own widgets with some sort of secondary highlighting.

Generate an HTML report based on user interactions in shiny

I have a shiny application that allows my user to explore a dataset. The idea is that the user explores the dataset, and any interesting things the user finds he will share with his client via email. I don't know in advance how many things the user will find interesting. So, next to each table or chart I have an "add this item to the report" button, which isolates the current view and adds it to a reactiveValues list.
Now, what I want to do is the following:
Loop through all the items in the reactiveValues list,
Generate some explanatory text describing the item (This text should preferably be formatted HTML/markdown, rather than code comments)
Display the item
Capture the output of this loop as HTML
Display this HTML in Shiny as a preview
write this HTML to a file
knitr seems to do exactly the reverse of what I want - where knitr allows me to add interactive shiny components in an otherwise static document, I want to generate HTML in shiny (maybe using knitr, I don't know) based on static values the user has created.
I've constructed a minimum not-working example below to try to indicate what I would like to do. It doesn't work, it's just for demonstration purposes.
ui = shinyUI(fluidPage(
title = "Report generator",
sidebarLayout(
sidebarPanel(textInput("numberinput","Add a number", value = 5),
actionButton("addthischart", "Add the current chart to the report")),
mainPanel(plotOutput("numberplot"),
htmlOutput("report"))
)
))
server = shinyServer(function(input, output, session){
#ensure I can plot
library(ggplot2)
#make a holder for my stored data
values = reactiveValues()
values$Report = list()
#generate the plot
myplot = reactive({
df = data.frame(x = 1:input$numberinput, y = (1:input$numberinput)^2)
p = ggplot(df, aes(x = x, y = y)) + geom_line()
return(p)
})
#display the plot
output$numberplot = renderPlot(myplot())
# when the user clicks a button, add the current plot to the report
observeEvent(input$addthischart,{
chart = isolate(myplot)
isolate(values$Report <- c(values$Report,list(chart)))
})
#make the report
myreport = eventReactive(input$addthischart,{
reporthtml = character()
if(length(values$Report)>0){
for(i in 1:length(values$Report)){
explanatorytext = tags$h3(paste(" Now please direct your attention to plot number",i,"\n"))
chart = values$Report[[i]]()
theplot = HTML(chart) # this does not work - this is the crux of my question - what should i do here?
reporthtml = c(reporthtml, explanatorytext, theplot)
# ideally, at this point, the output would be an HTML file that includes some header text, as well as a plot
# I made this example to show what I hoped would work. Clearly, it does not work. I'm asking for advice on an alternative approach.
}
}
return(reporthtml)
})
# display the report
output$report = renderUI({
myreport()
})
})
runApp(list(ui = ui, server = server))
You could capture the HTML of your page using html2canvas and then save the captured portion of the DOM as a image using this answer, this way your client can embed this in any HTML document without worrying about the origin of the page contents