class emojiPicker: def __init__(self): self.setupVariables() self.createGui() self.loadEmojis() def setupVariables(self): self.keyboardHeight = 650 self.keyboardWidth = 1200 self.categoryClickIndex = 0 self.colWidth = 100 self.colHeight = self.keyboardHeight self.rowHeight = 120 self.rowWidth = self.keyboardWidth + 2 * self.colWidth #keyboard spacing variables self.midRowXOffset = .2 self.keyboardYOffset = .5 self.keyboardYSpacing = 1 self.keyBoardXSpacing = 1 self.TOOLTIPS = """<div>@names</div>""" self.TOOLTIPS = """<div class="btn-group"> <button>@names 🔊</button> <button>Schadenfreude 🔊</button> <button>⻄⻇ 🔊</button> </div> """ # var audio = new Audio('emojiMessenger/static/audio.mp3'); self.filename = "audio.mp3" self.playSound = CustomJS(args=dict(filename = self.filename), code = """ var audio = new Audio('emojiMessenger/static/'.concat(filename)); audio.play(); """ ) def loadEmojis(self): self.sessionId = emojiDber.getSessionId() self.friendId = emojiDber.checkForUnmatchedFriendId(self.sessionId) #main category self.mainCategoryNames = emojiDber.getMasterCategories()[1:] mainCategoryIcons = emojiDber.getSubCategoriesIcons("MASTER",self.mainCategoryNames) self.updateEmojiFigure("Main","Column",mainCategoryIcons) #pick the first main category self.activeMainCategory = self.mainCategoryNames[0] subCategories = emojiDber.getSubCategories(self.activeMainCategory) subCategoryIcons = emojiDber.getSubCategoriesIcons(self.activeMainCategory,subCategories) self.updateEmojiFigure("Sub","Column",subCategoryIcons) #pick the first subcategory self.activeSubCategory = subCategories[0] #get suggested emojis suggestedEmojis = emojiDber.getRelevantEmojis(self.activeMainCategory) self.updateEmojiFigure("Suggested","Row",suggestedEmojis) #get emojis to display on the keyboars subCategoryEmojis = emojiDber.getCategoryTopEmojis(self.activeSubCategory) #fill in the difference with main cateogry emojis numSubEmojis = len(subCategoryEmojis) mainCategoryEmojies = emojiDber.getCategoryTopEmojis(self.activeMainCategory,NUM_TO_GET = 26 - numSubEmojis) keyboardEmojisDict = {**subCategoryEmojis,**mainCategoryEmojies} self.updateKeyboardFigure(keyboardEmojisDict) def updateEmojiFigure(self,figureName,figureType,emojisDict): newData = self.createCategoryGlyphSource(emojisDict,figureType) self.gui.select_one({"name":figureName}).data = newData def updateKeyboardFigure(self,emojisDict): newNames = list(emojisDict.keys()) newEmojis = list(emojisDict.values()) numEmojis = len(newNames) if numEmojis < 26: diff = 26 - numEmojis newNames += [""] * diff newEmojis += [""] * diff keyboardSourceDict = (self.emojiKeyboard.select_one({"name":"emojis"})).data_source.data keyboardSourceDict["names"] = newNames keyboardSourceDict["text"] = newEmojis (self.emojiKeyboard.select_one({"name":"emojis"})).data_source.data = keyboardSourceDict def createCategoryGlyphSource(self,categoriesDict,figureType): categoryEmojies = list(categoriesDict.values()) categoryNames = list(categoriesDict.keys()) numCategories = len(categoriesDict.keys()) indices = range(1,1+numCategories) categoryFills = [0] * numCategories categoryXs = [0] * numCategories categoryYs = range(numCategories) if figureType == "Row": categoryXs, categoryYs = categoryYs,categoryXs else: categoryFills[-1] = 1 categoryGlyphSourceDict = dict(x=categoryXs, y=categoryYs, text=categoryEmojies,names = categoryNames,fills = categoryFills,indices=indices) return categoryGlyphSourceDict def createEmojiFigure(self,figureType,name): #creates either a row or column to display emojies in numCategories = 10 if figureType == "Column": height = self.colHeight width = self.colWidth xRange = (-.5,.5) yRange = (-.5,numCategories-.5) yOffset = 20 else: height = self.rowHeight width = self.rowWidth xRange = (-.5,numCategories-.5) yRange = (-.4,.6) yOffset = 20 categoriesFigure = figure(title = "Title", plot_height = height, plot_width = width, x_range=xRange,y_range=yRange, toolbar_location = None,tools = "") categoriesFigure.axis.visible = False categoriesFigure.grid.visible = False categorySourceDict = dict(x=[], y=[], text=[],names = [],fills = [],indices=[]) # categorySourceDict = self.createCategoryGlyphSource(categoriesDict,figureType) categorySource = ColumnDataSource(categorySourceDict,name = name) #text glyph to display emojies categoriesGlyph = Text(x="x", y="y", text="text", angle=0,y_offset=yOffset, text_color="black",text_alpha = 1, text_font_size='35pt',text_align = "center") categoriesFigure.add_glyph(categorySource, categoriesGlyph) if figureType == "Row": categoryIndexText = Text(x="x", y="y", text="indices", angle=0,y_offset=-10,x_offset= -50, text_color="black",text_alpha = 1, text_font_size='20pt',text_align = "center") categoriesFigure.add_glyph(categorySource,categoryIndexText) #hidden circle glyph used to allow hovertool to work to show tooltips categoryCircleGlyph = Circle(x="x", y="y",radius=.45,fill_alpha = 0,line_alpha = "fills") circleGlyph = categoriesFigure.add_glyph(categorySource, categoryCircleGlyph, name = "circles") #create hover tool and add it to figure categoryHoverer = HoverTool(renderers=[circleGlyph], tooltips=self.TOOLTIPS) categoriesFigure.add_tools(categoryHoverer) return categoriesFigure def mainCategorySelectCallback(self,event): self.categoryClickIndex += 1 x,y = (event.x, event.y) index = int(y) selectedCategory = self.mainCategoryNames[index] self.activeMainCategory = selectedCategory #update the selected category indicator newFills = [0] * len(self.mainCategoryNames) newFills[index] = 1 self.gui.select_one({"name":"Main"}).data["fills"] = newFills #update sub categories subCategories = emojiDber.getSubCategories(self.activeMainCategory) subCategoryIcons = emojiDber.getSubCategoriesIcons(selectedCategory,subCategories) self.updateEmojiFigure("Sub","Column",subCategoryIcons) #pick the first new subcategory self.activeSubCategory = subCategories[0] subCategoryEmojis = emojiDber.getCategoryTopEmojis(self.activeSubCategory) #fill in the difference with main cateogry emojis numSubEmojis = len(subCategoryEmojis) mainCategoryEmojies = emojiDber.getCategoryTopEmojis(self.activeMainCategory,NUM_TO_GET = 26 - numSubEmojis) keyboardEmojisDict = {**subCategoryEmojis,**mainCategoryEmojies} self.updateKeyboardFigure(keyboardEmojisDict) def subCategorySelectCallback(self,event): #keep track of how many categories clicked throiugh until an answer found self.categoryClickIndex += 1 x,y = (event.x, event.y) index = int(y) subCategoryDict = self.gui.select_one({"name":"Sub"}).data #update the selected category indicator newFills = [0] * len(subCategoryDict["fills"]) newFills[index] = 1 self.gui.select_one({"name":"Sub"}).data["fills"] = newFills #change the active categroy abd get the emojis belonging to it self.activeSubCategory = subCategoryDict["names"][index] subCategoryEmojis = emojiDber.getCategoryTopEmojis(self.activeSubCategory) numSubEmojis = len(subCategoryEmojis.keys()) mainCategoryEmojies = emojiDber.getCategoryTopEmojis(self.activeMainCategory,NUM_TO_GET = 26 - numSubEmojis) keyboardEmojisDict = {**subCategoryEmojis,**mainCategoryEmojies} self.updateKeyboardFigure(keyboardEmojisDict) def suggestedSelectCallback(self,event): x,y = (event.x, event.y) index = int(x) suggestedEmojis = self.gui.select_one({"name":"Suggested"}).data["text"] clickedEmoji = suggestedEmojis[index] self.text_input.remove_on_change("value",self.textBoxcallback) self.text_input.value += (clickedEmoji) self.text_input.on_change("value",self.textBoxcallback) self.analyzeNgram(self.text_input.value,"tapped") def xyCoordsToKeyboardKey(self,x,y): """given an (X,Y) cooridnate, returns the key pressed on a qwerty keyboard""" rowIndex = int(y/(self.keyboardYSpacing)) colIndex = (x-(rowIndex*self.midRowXOffset))/self.keyBoardXSpacing clickedLetter = self.letters[int(rowIndex)][int(colIndex)] return clickedLetter def emojiDoubleTapCallback(self,event): #called when an emoji keyboard is double tapped #updates the suggested categories, but doesn't add it to the textbox print (1) def emojiTapCallback(self,event): #called when an emoji on the keyboard window is single tapped x,y = (event.x, event.y) index = int(x) + int(y) selectedChar = self.xyCoordsToKeyboardKey(x,y) emojiSourceData = (self.emojiKeyboard.select_one({"name":"emojis"})).data_source.data letterIndex = emojiSourceData["letters"].index(selectedChar) selectedEmoji = emojiSourceData["text"][letterIndex] self.text_input.remove_on_change("value",self.textBoxcallback) self.text_input.value += (selectedEmoji) self.text_input.on_change("value",self.textBoxcallback) self.filename = "cats.wav" self.analyzeNgram(self.text_input.value,"tapped") def analyzeNgram(self,ngram,methodOfEntry): #get the current category structure heirarchy = [self.activeMainCategory,self.activeSubCategory] emojiDber.addEnteredString( ENTERED_STRING = ngram, ENTRY_METHOD = methodOfEntry, CLICK_INDEX = self.categoryClickIndex, CATEGORY_STRUCTURE = heirarchy, SESSION_ID = self.sessionId) #reset category click index self.categoryClickIndex = 0 #get new suggestions #split the currently entered string splitNgram = list(ngram) newSuggestionsDict = {} for emoji in splitNgram: suggestions = emojiDber.getRelevantEmojisFromEmoji(emoji) newSuggestionsDict = {**newSuggestionsDict,**suggestions} #get suggested emojis self.updateEmojiFigure("Suggested","Row",newSuggestionsDict) def createMainEmojiWindow(self): plot = figure(title="", plot_width=self.keyboardWidth, plot_height=self.keyboardHeight, x_range= (-.5,10-.5),y_range = (0,3*self.keyboardYSpacing), h_symmetry=False, v_symmetry=False, min_border=0, toolbar_location=None,tools = "") plot.grid.visible = False plot.axis.visible = False emojiGlyph = Text(x="x", y="y", text="text", angle=0, text_color="black",text_alpha = 1,text_font_size='65pt',text_align = "center") source = self.createKeyboardCoordinates() plot.add_glyph(source, emojiGlyph,name = "emojis") circleGlyph = Circle(x="x", y="y",radius=.5,fill_alpha = 0,line_alpha = 0) circGlypher = plot.add_glyph(source, circleGlyph) emojiLetterText = Text(x="x", y="y", text="letters", angle=0,y_offset=-80,x_offset= -40, text_color="black",text_alpha = 1, text_font_size='20pt',text_align = "center") plot.add_glyph(source,emojiLetterText) hoverer = HoverTool(renderers=[circGlypher], tooltips=self.TOOLTIPS) plot.add_tools(hoverer) plot.on_event(Tap,self.emojiTapCallback) # plot.on_event(DoubleTap,self.emojiDoubleTapCallback) return plot def englishBoxCallback(self,attr,old,new): #called when someone types something into the english box, #gets the suggested emojis and updates the list #check if the new value is drastically longer than the old one (indicating autocomplete) if (len(new) - len(old)) > 4: print ("CLICKED") clickedEmoji = new[-1] self.text_input.value += (clickedEmoji) self.englishInput.value = "" return suggestedEmojis = emojiDber.getRelevantEmojis(new) emojisList = [] for name,emoji in suggestedEmojis.items(): entry = name.replace("_"," ") + " " + emoji emojisList.append(entry) self.englishInput.completions = emojisList def textBoxcallback(self,attr,old,new): if (len(old) > len(new)): return if not new: return newChar = new[-1] if newChar == " ": return if newChar.isdigit(): newEmojiIndex = int(newChar)-1 newEmoji = (self.gui.select_one({"name":"Suggested"})).data["text"][newEmojiIndex] self.text_input.remove_on_change("value",self.textBoxcallback) self.text_input.value = new[:-1] + newEmoji self.text_input.on_change("value",self.textBoxcallback) if newChar.isalpha(): newCharStr = newChar.lower() emojiSourceData = (self.gui.select_one({"name":"emojis"})).data_source.data typedEmojiIndex = emojiSourceData["letters"].index(newCharStr) newEmoji = emojiSourceData["text"][typedEmojiIndex] self.text_input.remove_on_change("value",self.textBoxcallback) self.text_input.value = new[:-1] + newEmoji self.text_input.on_change("value",self.textBoxcallback) self.analyzeNgram(self.text_input.value,"typed") def createKeyboardCoordinates(self): #rectangle window topRowXs, topRowYs = list(range(10)),[2*self.keyboardYSpacing + self.keyboardYOffset]*10 topRowLetters = ["q","w","e","r","t","y","u","i","o","p"] midRowXs, midRowYs = list(np.linspace(self.midRowXOffset,9-self.midRowXOffset,9)), [self.keyboardYSpacing + self.keyboardYOffset]*9 midRowLetters = ["a","s","d","f","g","h","j","k","l"] lowRowXs, lowRowYs = list(np.linspace(2*self.midRowXOffset,7-3*self.midRowXOffset,7)),[self.keyboardYOffset]*7 lowRowLetters = ["z","x","c","v","b","n","m"] self.letters = [lowRowLetters,midRowLetters,topRowLetters] xCoords = topRowXs + midRowXs + lowRowXs yCoords = topRowYs + midRowYs + lowRowYs letters = topRowLetters + midRowLetters + lowRowLetters self.numCoords = len(xCoords) emojis = [""] * self.numCoords names = [""] * self.numCoords source = ColumnDataSource(dict(x=xCoords, y=yCoords, text=emojis,names = names,letters = letters)) return source ###CHAT BOX def createChatBox(self): #creates a datatable to show messages data = dict(sender=[],message=[]) source = ColumnDataSource(data) columns = [ TableColumn(field="sender", title="From"), TableColumn(field="message", title="Message"), ] chatBox = DataTable(source=source, columns=columns, width=self.keyboardWidth, height=200) return chatBox def createMessageWindow(self): messageWindow = column([],css_classes=["message-box"],width = self.keyboardWidth - 300,height = 400) return messageWindow def sendMessage(self): #posts a message to the db and clears the text box, updates the chat window currentMessage = self.text_input.value emojiDber.postEnteredMessage(MESSAGE = currentMessage,SESSION_ID = self.sessionId) self.updateChatBox("You",currentMessage) def createSentDiv(self,message): return Div(text=message,height=30,width=self.keyboardWidth-400,css_classes = ["sent-speech-bubble"]) def createReceivedDiv(self,message): return Div(text=message,height=30,width=self.keyboardWidth-400,css_classes = ["received-speech-bubble"]) def updateChatBox(self,sender,newMessage): if sender == "You": newDiv = self.createSentDiv(newMessage) else: newDiv = self.createReceivedDiv(newMessage) self.messageWindow.children.append(newDiv) # chatBoxSource = self.chatBox.source.data # chatBoxSource["sender"].append(sender) # chatBoxSource["message"].append(newMessage) # self.chatBox.source.data = chatBoxSource self.text_input.value = "" def getReceivedMessages(self): #check if there's a friend id self.friendId = emojiDber.checkForUnmatchedFriendId(self.sessionId) #if its not found, return and try again later if not self.friendId: return unreadMessages = emojiDber.getUnreadMessages(SESSION_ID = self.friendId) for message in unreadMessages: messageText = message["MESSAGE"] messageTime = message["TIMESTAMP"] self.updateChatBox("Them",messageText) emojiDber.incrementMessageRead(SESSION_ID=self.friendId,TIMESTAMP = messageTime) def createGui(self): # self.chatBox = self.createChatBox() self.messageWindow = self.createMessageWindow() headerDiv = Div(text="<link rel='stylesheet' type='text/css' href='templates/styles.css'>") self.createKeyboardCoordinates() self.englishInput = AutocompleteInput(value = "",title = "English:",completions = ["bath","bathtub"]) self.englishInput.on_change("value",self.englishBoxCallback) self.text_input = TextInput(value="", title="Message:",width = self.keyboardWidth - 300) self.text_input.on_change("value",self.textBoxcallback) sendButton = Button(label="↩",button_type = "primary") sendButton.on_click(self.sendMessage) self.suggestedCategoryRow = self.createEmojiFigure("Row","Suggested") self.suggestedCategoryRow.on_event(Tap,self.suggestedSelectCallback) self.suggestedCategoryRow.title.text = "💡" self.suggestedCategoryRow.title.text_font_size = "20pt" mainCategoryFigure = self.createEmojiFigure("Column","Main") mainCategoryFigure.title.text = "🐘📦" mainCategoryFigure.title.text_font_size = "30pt" mainCategoryFigure.on_event(Tap,self.mainCategorySelectCallback) mainCategoryFigure.js_on_event(DoubleTap,self.playSound) subCategoryFigure = self.createEmojiFigure("Column","Sub") subCategoryFigure.title.text = "🥖📦" subCategoryFigure.title.text_font_size = "30pt" subCategoryFigure.name = "sub" subCategoryFigure.on_event(Tap,self.subCategorySelectCallback) self.emojiKeyboard = self.createMainEmojiWindow() self.emojiKeyboard.title.text = "⌨" self.emojiKeyboard.title.text_font_size = "30pt" self.gui = column( headerDiv, self.messageWindow, row(self.englishInput,self.text_input,sendButton), self.suggestedCategoryRow, row(self.emojiKeyboard,subCategoryFigure,mainCategoryFigure) ) def showGui(self): curdoc().add_root(self.gui) curdoc().add_periodic_callback(self.getReceivedMessages,1000) curdoc().on_session_destroyed(self.destroySession) curdoc().title = "Emoji Messenger" show(self.gui) def destroySession(self,session_context): emojiDber.deactivateSessionId(self.sessionId,self.friendId) print ("Session closed")
# Set up data table for summary statistics datatable_columns = [ TableColumn(field="parameter", title="Parameter"), TableColumn(field="value_all", title="All Data"), TableColumn(field="value_selection", title="Selected Data"), ] data_table = DataTable(source=datatable_source, columns=datatable_columns, width=450, height=125, index_position=None) # callback for updating the plot based on a changes to inputs station_name_input.on_change('value', update_station) simulation_number_input.on_change('value', update_n_simulations) msmt_error_input.on_change('value', update_msmt_error) sample_size_input.on_change('value', update_simulation_sample_size) toggle_button.on_click(update_simulated_msmt_error) # see documentation for threading information # https://docs.bokeh.org/en/latest/docs/user_guide/server.html update() # widgets ts_plot = create_ts_plot(peak_source, peak_flagged_source) peak_source.selected.on_change('indices', update_UI)
index_select.on_change('value', update_index) index_type_select.on_change('value', update_index) dt_pckr_start.on_change('value', update_index) dt_pckr_end.on_change('value', update_index) # Add Stock Analysis stock_auto_input = AutocompleteInput(value = '601318', completions = initializer.update_code_list(), title = '股票代码') # DatePciekr stock_pckr_start = DatePicker(title='开始日期', value = date.today() - timedelta(days = 100), min_date = date(2000,1,1), max_date = date.today()) stock_pckr_end = DatePicker(title='股票日期', value = date.today(), min_date = date(2000,1,1), max_date = date.today()) stock_select_row = row(stock_auto_input, stock_pckr_start, stock_pckr_end) stock_layout = column(stock_select_row, create_stock_figure_column(stock_auto_input.value, stock_pckr_start.value, stock_pckr_end.value)) stock_auto_input.on_change('value', update_stock) stock_pckr_start.on_change('value', update_stock) stock_pckr_end.on_change('value', update_stock) # Market Data # DatePciekr market_title = Div(text="整体市场概况", width=120, height=40, margin=[25, 0, 0, 0], style={'font-size': '150%', 'color': 'blue'}) market_pckr_start = DatePicker(title='开始日期', value = date.today() - timedelta(days = 100), min_date = date(2000,1,1), max_date = date.today()) market_pckr_end = DatePicker(title='股票日期', value = date.today(), min_date = date(2000,1,1), max_date = date.today()) market_select_row = row(market_title, market_pckr_start, market_pckr_end) market_layout = column(market_select_row, create_market_figure_column(market_pckr_start.value, market_pckr_end.value)) market_pckr_start.on_change('value', update_market) market_pckr_end.on_change('value', update_market) # Capital Data
################################################### text_input = AutocompleteInput(title='Select a sentence', completions=sentences) def update_sentences(attr, old, new): sentence = text_input.value ind = [ j for j, sent in enumerate(source_sentences.data['sentence']) if sent == sentence ] source_sentences.selected.indices = ind text_input.on_change('value', update_sentences) ################################################### # ADD RESET BUTTON ################################################### reset_button = Button(label='ALL WORDS', button_type='primary') reset_button.js_on_click( CustomJS(args=dict(source=source_words_visible, words=source_words, p=p), code=""" p.reset.emit() source.data = words.data """)) ################################################### # CREATION OF THE LAYOUT
def recommender_tab_simple(recommender): # create a list of divs def make_div_list(textlist, max_lines, fmt_str="""%s""", **attribs): """create a list of divs containing text to display""" divs = [] for i in range(max_lines): if len(textlist) > i: divs.append(Div(text=fmt_str % (textlist[i]), **attribs)) else: divs.append(Div(text=fmt_str % (' '), **attribs)) return divs def make_rec_list(titles, max_lines): """create a recommendation list of games, with a thumbnail, game title, info and Amazon buy links""" global games_by_title fmt_str1 = """ <div class="rec-post-container"> <div class="rec-post-thumb"><img src="%s" /></div> <div class="rec-post-content"> <h3 class="rec-post-title">%s<br> <a href="%s" target="_blank">Info</a><span> </span> <a href="%s" target="_blank">Buy on Amazon</a> </h3> </div> </div>""" fmt_str2 = """""" divs = [] for i in range(max_lines): # there is a title available for this list slot if len(titles) > i: divs.append( Div(text=fmt_str1 % (games_by_title['pic_url'].loc[titles[i]], titles[i], 'https://boardgamegeek.com/boardgame/' + str(games_by_title['id'].loc[titles[i]]), 'https://www.amazon.com/s?k=' + titles[i].replace(' ', '+') + '&i=toys-and-games'))) # there no title available for this list slot else: divs.append(Div(text=fmt_str2)) return divs # update the 'liked games' list UI elements def update_liked_list(titlelist): global max_liked ctl_liked_games.children = make_div_list(titlelist, max_liked, fmt_str=liked_list_fmt, render_as_text=False) # update the 'recommended games' list UI elements def update_recommended_list(titlelist): global n_recommendations ctl_recommended_games.children = make_rec_list(titlelist, n_recommendations) def show_searching_message(): ctl_recommended_games.children = [ Div(text='<h1>Searching for recommendations...</h1>') ] # called when a control widget is changed def update_preflist(attr, old, new): global liked_games liked_games.append(ctl_game_entry.value) liked_games = list(filter(None, set(liked_games))) # get control values update_liked_list(liked_games) ctl_game_entry.value = '' # clear out the list of preferred games def reset_preferred_games(): global liked_games liked_games = [] update_liked_list(liked_games) # user wants some recommendations (clicked the rec button) def recommend_games(): global liked_games, recommended_games global games_all, n_recommendations, title_list global title_list_lower # display a "Searching for recommendations..." message # Note: Bokeh doesn't do redraw while inside handlers show_searching_message() # get some default filter parameters: weight = [] minrating = 6.5 categories = ['Any category'] mechanics = ['Any mechanism'] for title in liked_games: idx = (np.array(title_list_lower) == title.lower()).nonzero()[0][0] info = games_all.iloc[idx, :] weight.append(info['weight']) categories += info['categories'].split(',') mechanics += info['mechanics'].split(',') # select a range of weights around the liked game weights weightrange = [ max(1, np.min(weight) - 0.25), min(5, np.max(weight) + 0.25) ] # get game IDs for titles liked_ids = recommender.get_item_title_id(liked_games) # select games to search from based on filters: recommended_games = recommender.recommend_items_by_pref_list( liked_ids, num2rec=n_recommendations, weightrange=weightrange, minrating=minrating, categories_include=categories, categories_exclude=['Expansion for Base-game'], mechanics_include=mechanics, mechanics_exclude=[]) update_recommended_list(recommended_games) # NOTE: I'm using globals because I'm running into variable scope # problems with the bokeh handlers. Easiest to declare globals global liked_games, recommended_games, games_all global n_recommendations, max_liked, title_list, title_list_lower global games_by_title # layout params n_recommendations = 10 max_liked = 8 # Format to use for liked list. # This needs to be changed to work like rec list liked_list_fmt = """<div style="font-size : 14pt; line-height:14pt;">%s</div>""" # variables used by the tab liked_games = [] recommended_games = [] weight_range = [1, 5] games_all = recommender.item_data # use all games for search games_by_title = recommender.item_data.set_index('name') # list of all game titles title_list = games_all['name'] title_list_lower = [s.lower() for s in title_list] # preferred game entry text control ctl_game_entry = AutocompleteInput(completions=list(title_list) + list(title_list_lower), min_characters=1, title='Enter some game names you like:') ctl_game_entry.on_change('value', update_preflist) # reset liked game list button ctl_reset_prefs = Button(label='Reset game list', width_policy='min', align='end') ctl_reset_prefs.on_click(reset_preferred_games) # liked list title ctl_liked_list_title = Div( text= """<div style="font-size : 18pt; line-height:16pt;">Games you like:</div>""" ) # liked game entries ctl_liked_games = WidgetBox( children=make_div_list(liked_games, max_liked, fmt_str=liked_list_fmt)) # recommended list title ctl_recommended_list_title = Div( text= """<div style="font-size : 18pt; line-height:16pt;">Games we recommend:</div>""" ) # recommended games list widget ctl_recommended_games = WidgetBox( children=make_rec_list(recommended_games, n_recommendations)) # Recommend games button ctl_recommend = Button(label='Recommend some games!', width_policy='min') ctl_recommend.on_click(recommend_games) # controls to select preferred games pref_controls = WidgetBox(ctl_liked_list_title, ctl_liked_games, Spacer(min_height=20), ctl_game_entry, ctl_reset_prefs, Spacer(min_height=40), ctl_recommend) # recommendation results results_controls = WidgetBox(ctl_recommended_list_title, ctl_recommended_games) # Create a row layout layout = row(pref_controls, results_controls) # Make a tab with the layout tab = Panel(child=layout, title='Simple Game Recommender') return tab
def update_air_temp_units(attr, old, new): air_temperature_input.value = str( u.Quantity(air_temperature_input.value, old).to(new, equivalencies=u.temperature()).value) air_temp_unit.on_change('value', update_air_temp_units) def update_material_density(attr, old, new): # if the material is changed then update the density material_density_input.value = str(get_density(material_input.value).value) material_input.on_change('value', update_material_density) def update_detector_density(attr, old, new): # if the material is changed then update the density detector_density_input.value = str( get_density(detector_material_input.value).value) detector_material_input.on_change('value', update_detector_density) curdoc().add_root( layout( [ [plot], [checkbox_group, plot_checkbox_group],
def recommender_tab_advanced(recommender): def make_div_list(textlist, max_lines, fmt_str="""%s""", **attribs): """create a list of divs containing text to display""" divs = [] for i in range(max_lines): if len(textlist) > i: divs.append(Div(text=fmt_str % (textlist[i]), **attribs)) else: divs.append(Div(text=fmt_str % (' '), **attribs)) return divs def make_rec_list(titles, max_lines): """create a recommendation list of games, with a thumbnail, game title, info and Amazon buy links""" global games_by_title fmt_str1 = """ <div class="rec-post-container"> <div class="rec-post-thumb"><img src="%s" /></div> <div class="rec-post-content"> <h3 class="rec-post-title">%s<br> <a href="%s" target="_blank">Info</a><span> </span> <a href="%s" target="_blank">Buy on Amazon</a> </h3> </div> </div>""" fmt_str2 = """""" divs = [] for i in range(max_lines): # there is a title available for this list slot if len(titles) > i: divs.append( Div(text=fmt_str1 % (games_by_title['pic_url'].loc[titles[i]], titles[i], 'https://boardgamegeek.com/boardgame/' + str(games_by_title['id'].loc[titles[i]]), 'https://www.amazon.com/s?k=' + titles[i].replace(' ', '+') + '&i=toys-and-games'))) # no title, so fill with blank else: divs.append(Div(text=fmt_str2)) return divs # update the 'liked games' list UI elements def update_liked_list(titlelist): global max_liked ctl_liked_games.children = make_div_list(titlelist, max_liked, fmt_str=liked_list_fmt, render_as_text=False) # update the 'recommended games' list UI elements def update_recommended_list(titlelist): global n_recommendations ctl_recommended_games.children = make_rec_list(titlelist, n_recommendations) # called when a control widget is changed def update_filters(attr, old, new): global category_includes, mechanics_includes global category_excludes, mechanics_excludes category_includes = [ ctl_category_selection1.labels[i] for i in ctl_category_selection1.active ] category_includes += [ ctl_category_selection2.labels[i] for i in ctl_category_selection2.active ] mechanics_includes = [ ctl_mechanics_selection1.labels[i] for i in ctl_mechanics_selection1.active ] mechanics_includes += [ ctl_mechanics_selection2.labels[i] for i in ctl_mechanics_selection2.active ] # NOTE: this will need to be changed if I ever implement exclude selections! if ctl_include_expansions.active: category_excludes = [] else: category_excludes = ['Expansion for Base-game'] # called when a control widget is changed def update_preflist(attr, old, new): global liked_games liked_games.append(ctl_game_entry.value) liked_games = list(filter(None, set(liked_games))) # get control values update_liked_list(liked_games) ctl_game_entry.value = '' # reset preferred games list def reset_preferred_games(): global liked_games liked_games = [] update_liked_list(liked_games) # recommend some games def recommend_games(): global liked_games, recommended_games global games_all, n_recommendations, title_list global category_includes, mechanics_includes # get game IDs for titles liked_ids = recommender.get_item_title_id(liked_games) # select games to search from based on filters: recommended_games = recommender.recommend_items_by_pref_list( liked_ids, num2rec=n_recommendations, weightrange=ctl_game_weight.value, minrating=ctl_game_min_rating.value, categories_include=category_includes, categories_exclude=category_excludes, mechanics_include=mechanics_includes, mechanics_exclude=mechanics_excludes) # show the recommended games update_recommended_list(recommended_games) # NOTE: I'm using globals because I'm running into variable scope # problems with the bokeh handlers. Easiest to declare globals global liked_games, recommended_games, games_all global n_recommendations, max_liked, title_list, title_list_lower global category_includes, mechanics_includes global category_excludes, mechanics_excludes global games_by_title # layout params n_recommendations = 10 max_liked = 8 num_check_options = 20 # Format to use for liked list. # This needs to be changed to work like rec list liked_list_fmt = """<div style="font-size : 14pt; line-height:14pt;">%s</div>""" # variables used by the tab games_all = recommender.item_data # use all games for search liked_games = [] recommended_games = [] weight_range = [1, 5] category_includes = [] mechanics_includes = [] category_excludes = [] mechanics_excludes = [] # list of all game titles title_list = games_all['name'] title_list_lower = [s.lower() for s in title_list] games_by_title = recommender.item_data.set_index('name') # preferred game entry text control ctl_game_entry = AutocompleteInput(completions=list(title_list) + list(title_list_lower), min_characters=1, title='Enter some game names you like:') ctl_game_entry.on_change('value', update_preflist) # reset liked game list button ctl_reset_prefs = Button(label='Reset game list', width_policy='min', align='end') ctl_reset_prefs.on_click(reset_preferred_games) # liked list title ctl_liked_list_title = Div( text= """<div style="font-size : 18pt; line-height:16pt;">Games you like:</div>""" ) # liked game entries ctl_liked_games = WidgetBox( children=make_div_list(liked_games, max_liked, fmt_str=liked_list_fmt)) # recommended list title ctl_recommended_list_title = Div( text= """<div style="font-size : 18pt; line-height:16pt;">Games we recommend:</div>""" ) # recommended games list widget ctl_recommended_games = WidgetBox( children=make_rec_list(recommended_games, n_recommendations)) # Recommend games button ctl_recommend = Button(label='Recommend some games!', width_policy='min', align='center') ctl_recommend.on_click(recommend_games) # game weight slider ctl_game_weight = RangeSlider( start=1, end=5, value=(1, 5), step=.1, title='Game weight range', width_policy='min', ) ctl_game_weight.on_change('value', update_filters) # min game rating slider ctl_game_min_rating = Slider(start=1, end=10, value=7, step=.1, title='Minimum average rating', width_policy='min') ctl_game_min_rating.on_change('value', update_filters) # collect all category and mechanics labels from recommender data categories, mechanics = recommender.get_categories_and_mechanics() # game category selection category_list = ['Any category'] + list(categories['tag'].values) ctl_category_selection1 = CheckboxGroup( labels=category_list[:int(num_check_options / 2)], width_policy='min', active=[0]) ctl_category_selection1.on_change('active', update_filters) ctl_category_selection2 = CheckboxGroup( labels=category_list[int(num_check_options / 2):num_check_options], width_policy='min') ctl_category_selection2.on_change('active', update_filters) # game mechanism checkbox group mechanics_list = ['Any mechanism'] + list(mechanics['tag'].values) ctl_mechanics_selection1 = CheckboxGroup( labels=mechanics_list[:int(num_check_options / 2)], width_policy='min', active=[0]) ctl_mechanics_selection1.on_change('active', update_filters) ctl_mechanics_selection2 = CheckboxGroup( labels=mechanics_list[int(num_check_options / 2):num_check_options], width_policy='min') ctl_mechanics_selection2.on_change('active', update_filters) # select whether to include expansions ctl_include_expansions = CheckboxGroup(labels=['Include game expansions'], width_policy='min') ctl_include_expansions.on_change('active', update_filters) # controls to select preferred games pref_controls = WidgetBox( ctl_liked_list_title, ctl_liked_games, Spacer(min_height=20), ctl_game_entry, ctl_reset_prefs, Spacer(min_height=5), ) ctl_liked_list_title = Div( text= """<div style="font-size : 18pt; line-height:16pt;">Game Categories:</div>""" ) filter_controls = WidgetBox( row(ctl_game_weight, Spacer(min_width=50), ctl_game_min_rating), row(ctl_include_expansions), column( row( Div(text= """<div style="font-size : 18pt; line-height:16pt;">Game Categories:</div>""" ), Spacer(min_width=50), ctl_recommend), row(ctl_category_selection1, ctl_category_selection2), Spacer(min_height=5), Div(text= """<div style="font-size : 18pt; line-height:16pt;">Game Mechanics:</div>""" ), row(ctl_mechanics_selection1, ctl_mechanics_selection2), )) # recommendation results results_controls = WidgetBox( ctl_recommended_list_title, ctl_recommended_games, Spacer(min_height=10), ) # Create a row layout layout = row(column(pref_controls, filter_controls), Spacer(min_width=50), results_controls) # Make a tab with the layout tab = Panel(child=layout, title='Advanced Game Recommender') return tab
cat=dd) # select gene expression value umis = get_umi(anndat, gene) # update factor color clusters = anndat.obs[dd] cats = sorted(clusters.unique().tolist()) fcmap['transform'].factors = [str(c) for c in cats] fcmap['transform'].palette = color_palette[:len(cats)] ## update source data source.data.update(color=clusters.astype(str).tolist()) ## update violin volin_change(gene, clusters, umis, bins=1000) ### input on change symbol.on_change('value', lambda attr, old, new: gene_change()) select.on_change('value', lambda attr, old, new: factor_change()) # set up layout sb = column(symbol, select, message) series_t = row(t1, t2, sb) series_u = row(u1, u2, volin) series_p = row( p1, p2, ) layout = column( series_t, series_u, series_p,
kms.on_change('value',lambda attr,old,new:kmsfunc()) sfms=MultiSelect(title='Subfams',\ options=[x[0] for x in collections.Counter(ptree.leaf_cds.data['subfamstr']).most_common()],\ width=150,height=70) sfms.on_change('value',lambda attr,old,new:sfmsfunc()) tcb=Button(label='CalcTC',width=80,height=40) tcb.on_click(tcbfunc) #splist=list(set(ptree.leaf_cds.data['species'])) #splist.sorted(key=ptree.leaf_cds.data['species']) #acw=AutocompleteInput(title='Organism name',completions=list(set(ptree.leaf_cds.data['species'])),width=200,height=50) acw=AutocompleteInput(title='Organism name',\ completions=[x[0] for x in collections.Counter(ptree.leaf_cds.data['species']).most_common()],\ width=200,height=50) acw.on_change('value',lambda attr,old,new:acfunc()) accacw=AutocompleteInput(title='Accession',\ completions=ptree.leaf_cds.data['gbacc'][:],width=200,height=50) accacw.on_change('value',lambda attr,old,new:accacfunc()) if len(sys.argv)>3: preselfpath=os.path.join(os.environ['SCIENCEDIR'],'GHSeqs',ghfam.upper(),sys.argv[3]) with open(preselfpath,'r') as f: preselections=[x.strip() for x in f.readlines()] print(preselections) else: preselections=[] psb=Button(label='Show Presels',width=80,height=40)
:return: [{"y": ..., "x": ..., "source": ..., "color": ...}, same] """ global source defaults = {"x": "start", "source": source} y_and_color_based_on_plus_dominance = { True: {"1y": "minus", "1c": "#48AFE8", "2y": "plus", "2c": "firebrick"}, # True if plus dominates False: {"1y": "plus", "1c": "firebrick", "2y": "minus", "2c": "#48AFE8"}, # False if plus does not dominate } vmap = y_and_color_based_on_plus_dominance[temp_plus_dominates[provider]] return [{"y": "temp_{}_{}".format(provider, vmap["1y"]), "color": vmap["1c"], **defaults}, {"y": "temp_{}_{}".format(provider, vmap["2y"]), "color": vmap["2c"], **defaults}] city_picker = AutocompleteInput(value="Tartu", title="\n", completions=list(CITY_MAP)) city_picker.on_change("value", lambda attr, old, new: update()) source = ColumnDataSource( data=dict( start=[], # Python datetime objects temp_emhi=[], # All EMHI temperatures - needed for the positioning of cloud-symbols. temp_emhi_plus=[], # EMHI temperatures above 0. temp_emhi_minus=[], # EMHI temperatures below 0. precipitation_emhi=[], temp_yrno=[], temp_yrno_plus=[], temp_yrno_minus=[], precipitation_yrno=[], symbol_yrno=[], # Cloud-symbols symbol_emhi=[] )