I've been struggling to find the best way to avoid overlapping subplots. I tried autosize, where height is dependent on the number of rows but then the plotly graph overlaps with the proceeding widget (in this case a datatable) below it. The number of subplots changes based on user input.
Here's an image of what I get:
plotly:: subplot(subplots, nrows = rows,titleY = TRUE) %>%
layout(margin = list(b=200)) #,autosize=F, height=(300*rows))
Does anyone know how to render a plotly subplot that avoids these overlap issues?
The best answer I've found is to create a reactive where the plotly figure is constructed. The dynamically changing height should be based on user inputs. In my case, it was the number of processes and impact categories the user selectes to display in the figure so I came up with a relationship like height = 100*n_pro*n_imp. This height should be passed into plot_ly() (as well as the renderUI). The reactive is then called by a renderPlotly which is in turn called by a renderUI. In my case, I kept the width at 100% but that could also be updated. It would look as follows:
fig_creation = reactive({
height = (something based on user input$)
plot_ly(..., height = height)
)}
output$plotlyFig = renderPlotly({ fig_creation() })
output$figPlotly = renderUI({
height = (something based on user input$) + 100 #the 100 is a buffer
plotlyOutput("plotlyFig",width = "100%", height = paste0(height)
})
On the UI side you simply use uiOutput("figPlotly"), where you want the figure to be placed.
Related
library(flexdashboard)
library(tidycensus)
library(tidyverse)
library(mapview)
library(dplyr)
library(tigris)
library(leafsync)
library(leafpop)
library(readxl)
library(DT)
library(highcharter)
{r}
#Importing Data ****Update file path before running****
states=data.frame(read_excel('C:/Users/pmckercher/Documents/CISA Research/CISA Funding Data.xlsx',
sheet = 'Funding By State',col_names = TRUE ))
us_geo=tigris::states(cb=FALSE, resolution = '20m') #State Sahpe File Download
all_data=inner_join(us_geo,states, by=c("NAME"="State")) #Joinging the two datasets
# These are shells, replace zcol= '' with a percentage of use column (will have to
#update the python file to calculate this when we get the real data) to make the display
#show how much of each states allocation has been provided.
Map22=mapview(all_data,zcol=c('fund_22'),col.regions = RColorBrewer::brewer.pal(11, "RdYlGn"), alpha.regions = 1, popup= popupTable(all_data,zcol=c('NAME', 'fund_22','fund_23','fund_24','fund_25')), label=c('NAME'))
Map22
This produces this visualization in the viewer:
Mapview Interactive Map
But, when the Dashaboard window pops up. it produces this where the map should be:
Buffering bars
How do I get the Interactive map to show up in the Dashboard window?
I'm trying to understand Shiny apps in particular this example of the bus dashboard located at
https://github.com/rstudio/shiny-examples/tree/master/086-bus-dashboard
I'd like to modify the update rule so colors are displayed depending on whether or not locations$Bearing >= 200.
I tried modifying the locations dataframe which has Bearing but can't figure out how to chnage the color on map when the leaflet map is updated. It looks like it may have something to do with color = ~dirPal(Direction)
addTiles('http://{s}.tile.thunderforest.com/transport/{z}/{x}/{y}.png') %>%
addCircleMarkers(
~VehicleLongitude,
~VehicleLatitude,
color = ~dirPal(Direction),
opacity = 0.8,
radius = 16
)```
where dirColors is defined at beginning of script
dirColors <-c("1"="#595490", "2"="#527525", "3"="#A93F35", "4"="#BA48AA", "5" = "#BA48AA")
I'd like to basically add a color here but conditionally displayed only for buses where Bearing >= 200 in location dataframe.
routeVehicleLocations <- reactive({
if (is.null(input$routeNum))
return()
locations <- vehicleLocations()
anomalies <- locations[locations$Bearing > 200,]
if (as.numeric(input$routeNum) == 0)
return(locations)
locations[locations$Route == input$routeNum, ]
})
The rest of the app is fine but would like to overwrite the color if condition above is met (Bearing >=200). Eventually would like to replace this rule with my own model and own data sources.
I am trying to implement an interactive dashboard in Bokeh with a "play" function that loops through all value pairs for two indicators selected by widgets.
Screen cap of dashboard
While the loop works, the dashboard resets the axis values for each step of the loop. So what I need is to set axis values based on the widget.value selected. To this end, I have built a data frame "ranges" that has the name of the indicator as index and the min/max value for each indicator as columns.
The updates for controls work thusly (x_axis,etc. are the names of the widgets):
controls = [x_axis, y_axis, start_yr, end_yr, years]
for control in controls:
control.on_change('value', lambda attr, old, new: update())
The update function is supposed to update the ranges upon change in the controls like this:
def update():
p.x_range = Range1d(start = ranges.loc[x_axis.value,"Min"],
end = ranges.loc[x_axis.value,"Max"])
p.y_range = Range1d(start = ranges.loc[y_axis.value,"Min"],
end = ranges.loc[y_axis.value,"Max"])
What should happen: Whenever I change the value of the widget, the ranges should update, but other than that, they should remain constant
What does happen: The ranges are set based on the value of the widget initially set and don't change on update.
I've tried to find examples trying to achieve something similar but no luck.
This is a working example:
import numpy as np
from bokeh.plotting import figure
from bokeh.models import Range1d
from bokeh.io import curdoc
x = np.linspace(0, 100, 1000)
y = np.sin(x)
p = figure(x_range=(0, 100))
p.circle(x, y)
def cb():
# this works:
p.x_range.start += 1
p.x_range.end += 1
# this also works:
#p.x_range = Range1d(p.x_range.start+1, p.x_range.end+1)
curdoc().add_periodic_callback(cb, 200)
curdoc().add_root(p)
I'm using GetTextExtentPoint32W to get width of a text in a cell in MS Excel 2010. The cell width is fetched using ActiveCell.Width. These two widths are then compared to determine whether the text fits in the cell or extends out of the cell.
Visually, even though the text fits perfectly in the cell, the text width returned by the method is more than the cell width. Also, when I increase the font size the difference between actual text width and that returned by the method increases.
Following is a part of the source code used to achieve the result. Please help me solve this error.
hDC = ctypes.windll.user32.GetDC(self.windowHandle)
tempBMP = ctypes.windll.gdi32.CreateCompatibleBitmap(hDC, 1, 1)
hBMP = ctypes.windll.gdi32.SelectObject(hDC, tempBMP)
iFontSize = self.excelCellObject.Font.Size
deviceCaps = ctypes.windll.gdi32.GetDeviceCaps(hDC, 90)
iFontSize = int(iFontSize)
iFontSize = ctypes.c_int(iFontSize)
iFontSize = ctypes.windll.kernel32.MulDiv(iFontSize, deviceCaps, 72)
iFontSize = iFontSize * -1
iFontWeight = 700 if self.excelCellObject.Font.Bold else 400
sFontName = self.excelCellObject.Font.Name
sFontItalic = self.excelCellObject.Font.Italic
sFontUnderline = True if self.excelCellObject.Font.Underline else False
sFontStrikeThrough = self.excelCellObject.Font.Strikethrough
#Create a font object with the correct size, weight and style
hFont = ctypes.windll.gdi32.CreateFontW(iFontSize,
0, 0, 0,
iFontWeight,
sFontItalic,
sFontUnderline,
sFontStrikeThrough,
False, False, False,
False, False,
sFontName)
#Load the font into the device context, storing the original font object
hOldFont = ctypes.windll.gdi32.SelectObject(hDC, hFont)
sText = self.excelCellObject.Text
log.io("\nText \t"+sText+"\n")
textLength = len(sText)
class structText(ctypes.Structure):
_fields_ = [("width", ctypes.c_int),
("height",ctypes.c_int)]
StructText = structText()
getTextExtentPoint = ctypes.windll.gdi32.GetTextExtentPoint32W
getTextExtentPoint.argtypes = [ctypes.c_void_p,
ctypes.c_char_p,
ctypes.c_int,
ctypes.POINTER(structText)]
getTextExtentPoint.restype = ctypes.c_int
#Get the text dimensions
a = ctypes.windll.gdi32.GetTextExtentPoint32W(hDC,
sText,
textLength,
ctypes.byref(StructText))
#Delete the font object we created
a = ctypes.windll.gdi32.DeleteObject(hFont)
a = ctypes.windll.gdi32.DeleteObject(tempBMP)
#Release the device context
a = ctypes.windll.user32.ReleaseDC(self.windowHandle, hDC)
textWidth = StructText.width
cellWidth = self.excelCellObject.Width
Thanks.
I do not use Python or Excel 2010 so cannot comment on your current approach. However, I have struggled with a similar problem. I hope the following points will be helpful.
Background
If you hover over the right boundary of an Excel column and hold the left mouse button you will get a display of the format: “Width: n.nn (mm pixels)”.
The help for the ColumnWidth property says:
One unit of column width is equal to the width of one character in the
Normal style. For proportional fonts, the width of the character 0
(zero) is used.
Use the Width property to return the width of a column in points.
As far as I can tell, “Normal style” means the standard font name and size at the time the workbook was created. Changing the standard font name and size for an existing workbook does not appear to have any effect. Changing the font name and size for a worksheet has no effect.
Two example displays for a standard width column are:
For Arial 10 Width: 8.43 (64 pixels)
For Tahoma 10.5 Width: 8.38 (72 pixels)
I have created a string of zeros and attempted to measure how many are visible depending on the width of the column. I found the number of zeroes that I could see matched the value displayed reasonably well for such as subjective measure.
With VBA, the ColumnWidth property of a column or cell sets or returns the width in characters.
With VBA, The read only Width property of a column or cell returns .75 * the width in pixels.
The significance of the above information is that the width values obtained from Excel are not necessarily correct for the font being used.
My problem and the solution I discovered
The problem I had was that I was merging cells and filling them with text. Although Excel will adjust the height of a row so the text within an unmerged cell is visible, it will not do so for a merged cell. I tried many techniques including Microsoft’s .Net, text rendering routines without success. Nothing I tried would reliably emulate Excel’s system for determining the width of text.
The technique I eventually used successfully involved picking a cell to the right and below all used cells for experimental use. I adjusted the width of the experimental cell’s column to match the combined width of the merged cell and copied the formatted value from the cell whose height I wanted. Because the experimental cell was unmerged, Excel would adjust the height as appropriate. I then made sure the source row was at least this height.
The key feature of this technique was that I was not trying to emulate Excel’s system for determining the width of text; I was using Excel’s system.
You would need to try different column widths for the experimental cell. I would start with the current width of the source column. If the row height matches that for a single row, the width of the source column is already sufficient. If the row height is more than that for a single row, I would increase the column width until the row height matched that for a single row and then adjust the source column’s width to match. If you start with the widest value (in characters or Python’s text width) you will probably get the source column width correct at the first attempt which would avoid the need for later adjustments.
In my project, I have 256 tiny PushButtons in one 16x16 grid layout. (Yeah that took forever.) Editing and running my program now is very laggy. Also, for some strange reason, Qt will not let me enable any of the buttons, but other buttons to the side work just fine?
Is there any easy way to determine which square of the grid was clicked without having a bunch of buttons? (Like following the cursor over an image maybe?)
Also, when each "square" of the grid is clicked, it becomes the "selection" and it needs to be the only "square" selected. (Think about it like a huge chess board)
Here is a pic: http://gyazo.com/988cdbb59b3d1f1873c41bf91b1408fd
Later on, I will need to do this again for a 54x54 size grid (2916 buttons) and I REALLY don't want to do it button by button.
Thanks for your time, I hope you understand my question :)
You can do this easy way, I've explained almost everything in code, but if you have any questions about it feel free to ask, and please, accept this answer if it solved your problem :)
import sys
from PyQt4 import QtGui, QtCore
from PyQt4.QtGui import *
from PyQt4.QtCore import *
class DrawImage(QMainWindow):
def __init__(self, parent=None):
super(QMainWindow, self).__init__(parent)
self.setWindowTitle('Select Window')
#you can set grid size here ... 8x8, 16x16 , for bigger numbers (54x54) be sure your image is big enough, because QWidget can't be smaller then ~20 pixels
self.gridSize = 16
mainWidget = QWidget()
self.setCentralWidget(mainWidget)
self.scene = QGraphicsScene()
view = QGraphicsView(self.scene)
layout = QVBoxLayout()
layout.addWidget(view)
mainWidget.setLayout(layout)
self.image = QImage('image.JPG')# put your image name here, image (suppose to be grid) must be at the same folder or put full path
pixmapItem = QGraphicsPixmapItem(QPixmap(self.image), None, self.scene)
pixmapItem.mousePressEvent = self.pixelSelect
def pixelSelect( self, event ):
#add whatever you want to this widget,any functionality or you can add image for example, I've simply colored it
wdg = QWidget()
layout = QVBoxLayout()
palette = QPalette(wdg.palette())
palette.setBrush(QPalette.Background, QColor(200,255,255))
wdg.setPalette(palette)
wdg.setLayout(layout)
self.scene.addWidget(wdg)
#calculate size and position for added widget
imageSize = self.image.size()
width = imageSize.width()
height = imageSize.height()
#size
wgWidth = float(width)/self.gridSize
wgHeight = float(height)/self.gridSize
wdg.setFixedSize(wgWidth,wgHeight)
#position
wgXpos = int(event.pos().x()/wgWidth) * wgWidth
wgYpos = int(event.pos().y()/wgHeight) * wgHeight
wdg.move(wgXpos, wgYpos)
#which square is clicked?
print "square at row ", int(event.pos().y()/wgHeight)+1,", column ",int(event.pos().x()/wgWidth)+1, "is clicked"
def main():
app = QtGui.QApplication(sys.argv)
form = DrawImage()
form.show()
app.exec_()
if __name__ == '__main__':
main()
Also, if you want to display simple square image over your grid image, look at question/solution I had: QGraphicsPixmapItem won't show over the other QGraphicsPixmapItem
If you don't really need the appearance of buttons, I would create a QWidget subclass that implements a custom paintEvent and renders a grid of needed size (taking the widget size into account). Then, in the mouse events (up,down,move etc.) you can calculate which grid item was clicked with a simple formula. You can render cells with different colors to indicate selection or highlighting.
P.S.:I would really like to post some code from my implementations (i have done this two or three times) but the source codes are at my old company :)
You just create your own QGridLayout in order to be able to add the buttons easily.
I posted an answer to another question, showing you how to fill a custom made QGridLayout with a bunch of widgets sequentially. The buttons are added according to the maximum count of columns you specified. (Note: It's just a very rough example but enough to start from)
In your example you would create the custom grid layout with 16 columns and simply add your buttons.
To find out which button has been pressed (and to make connecting easier) you can use QSignalMapper.
For investigating the lag you could check the amount of (GDI-/User-) handles of your application (using ProcessExplorer for example). The handle count shouldn't be above 10.000.
I don't know why you can't enable the push buttons.