Set the marking on a viz through IPython - spotfire

Similar to this question but not quite the same: Spotfire: "limit data using markings" by python script
I have a script that currently looks like this:
from Spotfire.Dxp import Data
from Spotfire.Dxp.Application.Visuals import *
#Remove the current Marking Filter
for filtering in vis.As[VisualContent]().Data.Filterings:
vis.As[VisualContent]().Data.Filterings.Remove(filtering)
#Set the new Marking Filter
vis.As[VisualContent]().Data.Filterings.Add(Document.Data.Markings["Marking (4)"])
#Set the new Marking
#Need code here
I need to set a new marking for the visualization so that I can then use that for another visualization. Specifically, I need to set this box:
UPDATE
I am able to set markings using this piece of code:
vc = vis.As[VisualContent]()
marking = vc.Data.MarkingReference
marking.SetSelection(marking.GetSelection(dataTable),dataTable)
This does mark the records I want, but because it does not change the setting in the Marking box, it will not let me drill down further (filtered to the same marking it is setting).

This script ultimately worked for me:
from Spotfire.Dxp import Data
from Spotfire.Dxp.Application.Visuals import *
if Document.Properties['KPIHierLevel'] == '<[SBA_NAME] NEST [MARKET_NAME]>':
Document.Properties['KPIHierLevel'] = '<[MARKET_NAME] NEST [BRAND]>'
for filtering in vis.As[VisualContent]().Data.Filterings:
vis.As[VisualContent]().Data.Filterings.Remove(filtering)
vis.As[VisualContent]().Data.Filterings.Add(Document.ActiveMarkingSelectionReference)
vis.As[VisualContent]().Data.MarkingReference = (Document.Data.Markings["Marking (7)"])
elif Document.Properties['KPIHierLevel'] == '<[MARKET_NAME] NEST [BRAND]>':
Document.Properties['KPIHierLevel'] = '<[BRAND] NEST [PRODUCT]>'
for filtering in vis.As[VisualContent]().Data.Filterings:
vis.As[VisualContent]().Data.Filterings.Remove(filtering)
vis.As[VisualContent]().Data.Filterings.Add(Document.ActiveMarkingSelectionReference)
vis.As[VisualContent]().Data.MarkingReference = (Document.ActiveMarkingSelectionReference)
I also created a Reset script that is similar to this but sets the marking back to something other than Marking (7).

Related

How get BQL (bLOOMBERG) query from python

I have the following query in Excel using BQL:
=BQL("MEMBERS('INEMCBI LX Equity',type=holdings)";"name";"cols=2;rows=223")
This shows a table of securities of a specific mutual fund. Like this:
enter image description here
I want to get the same information using python in Dataframe structure but I dont know any way to get it.
If you run BQNT<GO> on the terminal, you'll get access to Python BQL examples, but the examples won't work outside of BQNT. Since you mention using =BQL, I'm assuming you have access to a terminal.
Example in BQNT:
import bql
bq = bql.Service()
fund = bq.univ.members("INEMCBI LX Equity", type="HOLDINGS")
name = bq.data.name()
req = bql.Request(fund, {"Fund Holdings": name})
res = bq.execute(req)
data = res[0].df()
data
Run BQNT on your Bloomberg terminal to ensure the BQL environment is installed.
Follow the steps exactly as followed.
Open file explorer
Navigate to C:\blp\bqnt\environments\bqnt-3\Lib\site-packages and copy these folders:
bqapi
bqbreg
bql
bqlmetadata
bqrequest
bqutil
ciso8601
Paste them to your python installation folder %userprofile%\Anaconda3\envs{mypythonenv}\lib\site-packages\
Then you can test this code in your code editor. I use Vscode.
import seaborn as sb
import pandas as pd
import matplotlib.pyplot as plt
import bql
bq = bql.Service()
query = """get(px_last)for('AAPL US EQUITY')with(dates=range(-1y,0d),fill='prev')"""
data = bql.combined_df(bq.execute(query)).reset_index()
fig = plt.figure(figsize=(12,8))
sb.lineplot(data=data, x='DATE',y='px_last')
plt.show()

Problem: Can only check multiple checkbuttons together?

I would like to generate checkbuttons for multiple items. Due to the repetition, I used a loop to initialize the widget and the default state, saving the BooleanVar() and widgets in separate lists. But by doing so, I can only check either check or uncheck all of them together.
I already tried to set different value to the BooleanVar in the list from within the loop, but to no avail.
ckbtnVarList = [tk.BooleanVar()]*len(ckbtnDict["Tag"])
ckbtnWdtList = [None]*len(ckbtnDict["Tag"])
for idx in range(len(ckbtnDict["Tag"])):
ckbtnVarList[idx].set(1)
ckbtnWdtList[idx]=ttk.Checkbutton(mainfrm, text=ckbtnDict["Text"][idx], variable=ckbtnVarList[idx]).pack()
As specified in the comments above, you need to create your list of BooleanVar's with a list comprehension or a list. The below code shows how to do this.
Since you didn't provide a complete code example, I've had to make some assumptions about your input data.
import tkinter as tk
ckbtnDict = {}
ckbtnDict['Tag'] = ["Tag1","Tag2","Tag3"]
ckbtnDict["Text"] = ["Txt1","Txt2","Txt3"]
mainfrm = tk.Tk()
ckbtnVarList = [tk.BooleanVar() for i in range(len(ckbtnDict["Tag"]))]
ckbtnWdtList = [None for i in range(len(ckbtnDict["Tag"]))]
for idx in range(len(ckbtnDict["Tag"])):
ckbtnVarList[idx].set(1)
ckbtnWdtList[idx]=tk.Checkbutton(mainfrm, text=ckbtnDict["Text"][idx], variable=ckbtnVarList[idx])
ckbrnWdtList[idx].pack()
mainfrm.mainloop()

Adding GraphicsObject to two ViewBoxes or QGraphicsViews

Ultimately I want pyqtgraph to display a single GraphicsObject simultaneously in several ViewBoxes, sharing a single scene.
At the same time I want to have some other GraphicsObjects in a single ViewBox only.
Something like this:
vb0 = ViewBox()
vb1 = ViewBox()
# shown only in first ViewBox vb0
local_item = GraphicsObject()
# shown in all ViewBoxes
global_item = GraphicsObject()
vb0.addItem(local_item)
assert vb0.scene() is vb1.scene()
# the magic function i am looking for
vb0.scene().addItemGlobally(global_item)
So very naively I looked into the ViewBox sourcecode and reproduced the steps for addItem() like here:
import pyqtgraph as pg
from pyqtgraph.Qt import QtCore as qc, QtGui as qg, QtWidgets as qw
class Polygon(pg.GraphicsObject):
"""Just a Triangle..."""
app = qw.QApplication([])
viewer = pg.GraphicsWindow()
vb0 = viewer.addViewBox(0, 0)
vb1 = viewer.addViewBox(0, 1)
viewer.show()
poly_yellow = Polygon((125, 125, 0, 255))
scene = vb0.scene()
added_items = vb1.addedItems = vb0.addedItems
child_group = vb1.childGroup = vb0.childGroup
child_group.setParent(scene)
child_group.itemsChangedListeners.append(vb1)
# here reproducing steps found in addItem()
if scene is not poly_yellow.scene():
scene.addItem(poly_yellow)
poly_yellow.setParentItem(child_group)
added_items.append(poly_yellow)
vb0.updateAutoRange()
# vb1.updateAutoRange()
# checking if ViewBoxes share relevant attributes
assert vb0.scene() is vb1.scene()
assert vb0.scene() is poly_yellow.scene()
assert vb0.addedItems is vb1.addedItems
assert vb0.childGroup is vb1.childGroup
app.exec_()
Running this gives me two ViewBoxes, but only vb0 showing the triangle. Also this approach would give me global only Items. Is there any way to get something like local/global items without re-implementing ViewBoxes completely?
EDIT: I think it is impossible to achieve what I want with pyqtgraph ViewBoxes. A transform of the global items must happen just before the painting.
I found it is not easily doable using ViewBox. However, it is possible to us pyqtgraphs GraphicsView, implementing a lot of functionality found in the ViewBox class already.
My approach now is to generate as many GraphicsView as I need, and set them all to one scene via GraphicsView.setScene()
The scene contains the 'global' items, displayed in every View. The Viewspecific, local Items are drawn using the GraphicsView.drawBackground() function.
I haven't tested it to much, but it seems quite good working, for the case, were several thousend items are added to the scene, but only few items are drawn to the background.

How do I interactively update a markdown cell in jupyter notebook by an IPython widget?

I am using Jupyter notebook with Python 3 kernel. I have a computation which bases on user input by an IPython widget.
The result of the computation needs to be shown in a markdown cell. For this I use the Python Markdown nbextension. The Question now is: How do I update the markdown cell on user interaction?
I tried to run the markdown cell from python using a Javascript call.
As a minimal example, the following two cells may serve. (First normal python cell, second markdown cell)
from IPython.display import Javascript
import ipywidgets
def update_md_cell(slider_value):
Javascript("Jupyter.notebook.execute_cells([1])")
t_slider = ipywidgets.IntSlider(min = 0, max = 10, value = 10)
ipywidgets.interactive(update_md_cell, slider_value = t_slider)
... The value of number is {{t_slider.value}}. ...
But this seems to work only outside of functions.
Javascript("Jupyter.notebook.execute_cells ([1])")
reloads the markdown cell.
def update_md_cell():
Javascript("Jupyter.notebook.execute_cells ([1])")
update_md_cell()
does nothing.
Is there another way to connect the inputs (through the IPython widget) to the output (in the Markdown cell)?
Update: Like mentioned in the comment to Suraj Potnuru's answer, my basic problem is the gotcha from here:
A big gotcha: something somewhere needs to return Javascript as its output, otherwise it doesn’t get executed in the notebook.
But it's even worse, a return in the via ipywidgets.interactive() binded function is not enough to fix the gotcha, e.g.:
def update_md_cell():
return Javascript("Jupyter.notebook.execute_cells ([1])")
update_md_cell()
works.
from IPython.core.display import Javascript
from IPython.display import display
import ipywidgets
def update_md_cell(slider_value):
return Javascript("Jupyter.notebook.execute_cells ([1])")
t_slider = ipywidgets.IntSlider(min = 0, max = 10, value = 10)
ipywidgets.interactive(update_md_cell, slider_value = t_slider)
doesn't work.
How do I get the second to work?
Update your foo() function to the below code
def foo():
slider_value = t_slider.value
display(Javascript("var markdown_cell = IPython.notebook.get_cell(1);markdown_cell.set_text('The value of the number is "+ str(slider_value) +"');IPython.notebook.execute_cell(1)"))
The above code snippet fetches the value of the slider object and uses get_cell() function to fetch the first cell which is your markdown cell. The cells numbering starts from 0, hence 0th cell is your python code cell, 1st cell is your markdown cell.
It uses the set_text() function to update the markdown inside your cell with the latest slider value.
Call foo() function whenever your slider is updated to update the markdown also.

Ever expanding amount of Entries with TKinter

What I'm trying to do is to make a GUI where when you start typing in an entry-box another shows up just beneath the one you are typing in. Then when you start typing in the one that popped up, another pops up. Is this possible with TKinter and Python?
Edit:
So what I currently have is this:
entry1 = StringVar()
numberLabel3 = Label(window, text = "3. External meeting attendees")
r+=1
numberLabel3.grid(column = 0, row = r, sticky = W)
externalAtendeesLabel = Label(window, text = "input name of external meeting atendee: ")
r+=1
externalAtendeesLabel.grid(column = 1, row = r, sticky = E)
externalAtendeesEntry = Entry(window, textvariable = entry1)
externalAtendeesEntry.grid(column = 2, row = r)
#Note to self: Find a smart way of dynamically expanding this "list" of entries
(There is more code above and below this, but this is the relevant code for my question)
where r is a variable I made to make it easier to insert stuff into the middle of my rather long code.
The imports I'm using are:
from tkinter import *
from PIL import ImageTk
from PIL import Image
import os
I use the image modules and OS to insert an image further up in my GUI.
What I was thinking was to make a function that I could somehow setup to check the newest Entry-box, but I've run into the problem that for this to be potentially infinite I would have to dynamically create new variables, so that I can access the information that the user inputs. These variables would save the info just like my entry1 variable does it for the externalAtendeesEntry.
I would also have to dynamically make variables for more entries.
How do I dynamically create a potentially infinite amount of variables?
I know that this is kind of a re-post, but the other ones I've found all say that you should use dictionaries, but in that case it can't be infinite. It can only be finite to the point where my dictionary is no longer.
For one, you don't need to use StringVar. It only complicates your code without providing any real value. The other part of the answer is to store the entries in a list.
For example, create a function called addEntry that creates an entry and adds it to a list:
entries = []
...
def addEntry():
entry = tk.Entry(...)
entry.pack(...)
entries.append(entry)
To get the values at a later date, just iterate over the list:
for entry in entries:
print(entry.get())
With that, you can add entries whenever you want. You could, for example, bind to <Any-KeyRelease> to create a new entry as the user types (being sure to only do it if there isn't already a blank entry). Or, bind to <Return> or <FocusOut>, or on the click of a "new person" button, or however else you decide.

Resources