How to update Span (Bokeh) using ColumnDataSource? - python

I am trying to update Span using ColumnDataSource, but the information is not being passed onto the source. Span unfortunately does not have a paremeter "source", so is there a better way?
I have defined my sources, figure and line like so:
m1_source = ColumnDataSource(data=dict(x1=[], y1=[]))
m1_spans = ColumnDataSource(data=dict(x1=[]))
p = figure(x_axis_type="datetime", title="", sizing_mode="fixed", height = 500, width = 1400)
p.line(x ="x1", y="y1", color = 'blue', source=m1_source)
Then I have a for loop that should ideally plot multiple spans, each 'i' will be a separate timestamp:
for i in m1_spans.data['x1']:
p.add_layout(Span(location=i, dimension='height', line_color='red', line_dash='solid', line_width=1))
This is taken from my update() function:
m1_source.data = dict(
x1=machine_1_vals['mpTimestamp'],
y1=machine_1_vals['Value'])
m1_spans.data = dict( x1=ToolsDF.loc[ToolsDF['Value'] == float(vals['Tool_val'])]['Timestamp'])
I have checked this, and m1_spans does successfully return multiple timestamps, so the error shouldn't be here.
The reason I am confused, is because my p.line will successfully update with no issues, but it does have a source parameter, while span does not.
I would be really appreciative for any advice about how to solve this issue.
If I should have supplied more information, I apologize and can update as needed, I just tried to keep it brief for you.
Thanks.

Span objects do not currently have an ability to be "powered" by a ColumnDataSource. Each Span only draws one span, specified by its own location property.
You will need to update the location property individually on each Span object in order to update it. Alternatively, if you absolutely want to be able to drive updates through a CDS, you could look at using a multi_line, segment, or ray glyph instead. Those all have different ways to configure their coordinates, so you'd have to see which is most convenient to your use-case. But they all come with one trade-off, which is that none of them have the full "infinite extent" that a Span supports.

Related

Retrieving node locations from pydotplus (or any layered graph drawing engine)

I'm preparing a layered graph drawing using a dataframe containing node data:
type label
0 Class Insurance Product
1 Class Person
2 Class Address
3 Class Insurance Policy
And another containing relationship data:
froml tol rel fromcard tocard
0 Insurance Policy Insurance Product ConveysProduct One One
1 Person Insurance Policy hasPolicy One Many
2 Person Address ResidesAt None None
I populate a pydotplus dot graph with the content, which I can then use to generate a rendering:
pdp_graph = pydotplus.graphviz.Dot(graph_name="pdp_graph", graph_type='digraph', prog="dot")
for i,e in b_rels_df.iterrows():
edge = pydotplus.graphviz.Edge(src=e['froml'], dst=e['tol'], label=e['rel'])#, set_fromcard=e['fromcard'], set_tocard=e['tocard'])
pdp_graph.add_edge(edge)
for i,n in ents_df.iterrows():
node = pydotplus.graphviz.Node(name=n['label'], set_type=n['type'], set_label=n['label'])
pdp_graph.add_node(node)
png = pdp_graph.create_png()
display(Image(png))
So far so good - but now I want to retrieve the node positions for use in my own interactive layout (the png is a nice example/diagram, but I want to build upon it), so am attempting to retrieve the node locations calculated via:
[n.get_pos() for n in pdp_graph.get_nodes()]
But this only returns:
> [None, None, None, None]
I've tried lots of different methods, graphviz/dot are installed fine - as proven by the image of the layout - how can I extract the positions of the nodes as data from any type of dot-style layout?
There is a way I can do this via the pygraphviz library via networkx, but the installation-overhead restricts me (pygraphviz needs to be recompiled to cinch with the graphviz install) from being able to use that for the target installations where I've less control over the base environments, hence my attempt to use pydotplus, which appears less demanding in terms of install requirements.
How do I retrieve the layout data from a layered graph drawing using this setup (or one similar), such that I can use it elsewhere? I'm looking for x,y values that I can map back to the nodes that they belong to.
I know nothing about your python setup. ( As usual with python it seems awkward and restrictive )
I suggest using Graphviz directly. In particular the 'attributed DOT format' which is a plain text file containing the layout ( resulting from the layout engine ) produced when the engine is run with the command option -Tdot. The text file is easily parsed to get exactly what you need.
Here is a screenshot of the first paragraph of the relevant documentation
The graphviz.org website contains all the additional details you may need.
You are creating an output file of png format. All position data is lost in this process. Instead, create output format="dot". Then, read that back in & modify as desired.

python-docx - How do I add an image at a specific position?

I have a pre-existing document that I need to add a picture to. The picture needs to be inside a frame in the upper right corner of the document. The frame it needs to go in is already part of the document. All I need to do as far as I understand is add a run to the paragraph inside the frame (which is a v:shape element) and then add a picture to that and the position of the picture should assume the position of the surrounding element. The only issue is I can only get a paragraph, run or picture to get added to the end of the document but not to a specific element farther down the document. Also I whereas I can set a size to the image there is no option to set the position of it on the page. Is there anyway to do this? Again what I'm wanting to do is add a picture to a document at a specific x, y position on the page.
edit:
Here's my latest attempt. I don't know any other way than to drill down deep into the document to get the element I want to add a picture to:
for r in doc.paragraphs[0].runs:
for r2 in r._r.iterchildren():
if r2.tag == '{http://schemas.openxmlformats.org/wordprocessingml/2006/main}pict':
for r3 in r2.iterchildren():
if r3.tag == '{urn:schemas-microsoft-com:vml}shape':
for r4 in r3.iterchildren():
if r4.tag == '{urn:schemas-microsoft-com:vml}textbox':
for r5 in r4.iterchildren():
if r5.tag == '{http://schemas.openxmlformats.org/wordprocessingml/2006/main}txbxContent':
for r6 in r5.iterchildren():
if r6.tag == '{http://schemas.openxmlformats.org/wordprocessingml/2006/main}p':
#pic = doc.add_picture('image.jpg', width=1508760, height=1905000)
#pic_xml = pic._inline.xml
#r6.append(pic._inline)
pr = r6.add_run()
pr.add_picture('image.jpg', width=1508760, height=1905000)
I've read examples that say to add a run to a paragraph and then add a picture to that run. This is what I'm trying but all I get is an error like this: "'CT_P' object has no attribute 'add_run'"
The fact is though is that you actually can add a run to a paragraph but this is saying that the element I'm drilling down to is a different object type than a regular paragraph object. Does that make sense? Do I have to covert this element somehow?

Using pywinauto to read a value within a window and use in a function

I am building an automation script with python using pywinauto, and I am stumped on this part. So far I'm able to start the app, or connect to it. I've toggled through the windows in the interface, and now it needs to somehow read the value and compare to the contents of a .csv file and continue with more functions. The app has multiple windows and one of them uses a spreadsheet type interface. There is not a find/replace feature, or else I could just use that.
Now comes the challenge. It needs to "see" the string within a cell and I can easily do this using AccExplorer or Inspect.exe.
This is the cell structure in the app, with the selected item "CAM 2".
Cell example from the app
AccExplorer window showing results of the cell
And this is the result provided by AccExplorer. The red circle indicates the "value" I wish to find, and use for comparison. (I have found that searching for this topic on "value" results in answers that are too vague, rather than my literal need to find the value of "value" in this case.)
By using this code in my script passing in the class of the window provided by the AccExpolorer tool (red arrow for the class)
edit = wdow['WindowsForms10.Window.8.app.0.378734a']
props = edit.GetProperties()
print(props)
It does not return the "Value" field or its property in this case should be "Cam 2"
{'class_name': 'WindowsForms10.Window.8.app.0.378734a',
'friendly_class_name': 'WindowsForms10.Window.8.app.0.378734a',
'texts': [''], 'control_id': 1639674, 'rectangle': <RECT L0, T47, R1366, B746>,
'is_visible': True, 'is_enabled': True, 'control_count': 76, 'style': 1442906112,
'exstyle': 65536, 'user_data': 0, 'context_help_id': 0,
'fonts': [<LOGFONTW 'MS Shell Dlg' -11>],
'client_rects': [<RECT L0, T0, R1366, B699>],
'is_unicode': True, 'menu_items': []}
I am rather new to python (and programming in general) but I have been doing quite well at grasping all of this. I am aware of the backend, which I have not had luck with using UIA, and it seems to be working so far with the default. Also, I've tried using SWAPY and it displays a lot of class names as duplicates, and does not show this level of cell values directly.
The main question is what would I be doing wrong to get this data, or is it even possible to get it this way? I am open to any suggestions or even using other libraries. I just figured this would be the cleanest and easiest. Thanks!
For begin read getting started guide and see some examples
You choose not better way to get cell of DataGridView, try to use UIA backend for that
from pywinauto import Desktop
dlg = Desktop(backend="uia")["YourApplicationName"]
# use that function for found your DataGridView
#dlg.print_control_identifiers()
datagrid = dlg.DataGridView
# use for found some particular cell
#datagrid.print_control_identifiers()
# in my case it was DataItem
cell = dlg.DataGridView.DataItem
# way to get item value
print(cell.legacy_properties()['Value'])
You also can use indexes for choose from a lot of same cells, like "DataItem0" or get all cells using lambda:
cells = [child for child in datagrid.descendants() if child.element_info.control_type == "DataItem"]
for cell in cells:
print(cell.legacy_properties()['Value'])

Python friends network visualization

I have hundreds of lists (each list corresponds to 1 person). Each list contains 100 strings, which are the 100 friends of that person.
I want to 3D visualize this people network based on the number of common friends they have. Considering any 2 lists, the more same strings they have, the closer they should appear together in this 3D graph. I wanted to show each list as a dot on the 3D graph without nodes/connections between the dots.
For brevity, I have included only 3 people here.
person1 = ['mike', 'alex', 'arker','locke','dave','david','ross','rachel','anna','ann','darl','carl','karle']
person2 = ['mika', 'adlex', 'parker','ocke','ave','david','rosse','rachel','anna','ann','darla','carla','karle']
person3 = ['mika', 'alex', 'parker','ocke','ave','david','rosse','ross','anna','ann','darla','carla','karle', 'sasha', 'daria']
Gephi Setup steps:
Install Gephi and then start it
You probably want to upgrade all the plugins now, see the button in the lower right corner.
Now create a new project.
Make sure the current workspace is Workspace1
Enable Graph Streaming plugin
In Streaming tab that then appears configure server to use http and port 8080
start the server (it will then have a green dot underneath it instead of a red dot).
Python steps:
install gephistreamer package (pip install gephistreamer)
Copy the following python cod to something like friends.py:
from gephistreamer import graph
from gephistreamer import streamer
import random as rn
stream = streamer.Streamer(streamer.GephiWS(hostname="localhost",port=8080,workspace="workspace1"))
szfak = 100 # this scales up everything - somehow it is needed
cdfak = 3000
nodedict = {}
def addfnode(fname):
# grab the node out of the dictionary if it is there, otherwise make a newone
if (fname in nodedict):
nnode = nodedict[fname]
else:
nnode = graph.Node(fname,size=szfak,x=cdfak*rn.random(),y=cdfak*rn.random(),color="#8080ff",type="f")
nodedict[fname] = nnode # new node into the dictionary
return nnode
def addnodes(pname,fnodenamelist):
pnode = graph.Node(pname,size=szfak,x=cdfak*rn.random(),y=cdfak*rn.random(),color="#ff8080",type="p")
stream.add_node(pnode)
for fname in fnodenamelist:
print(pname+"-"+fname)
fnode = addfnode(fname)
stream.add_node(fnode)
pfedge = graph.Edge(pnode,fnode,weight=rn.random())
stream.add_edge(pfedge)
person1friends = ['mike','alex','arker','locke','dave','david','ross','rachel','anna','ann','darl','carl','karle']
person2friends = ['mika','adlex','parker','ocke','ave','david','rosse','rachel','anna','ann','darla','carla','karle']
person3friends = ['mika','alex','parker','ocke','ave','david','rosse','ross','anna','ann','darla','carla','karle','sasha','daria']
addnodes("p1",person1friends)
addnodes("p2",person2friends)
addnodes("p3",person3friends)
Run it with the command python friends.py
You should see all the nodes appear. There are then lots of ways you can lay it out to make it look better, I am using the Force Atlas layouter here and you can see the parameters I am using on the left.
Some notes:
you can get the labels to show or disappear by clicking on the T on the bottom status/control bar.
View the data in the nodes and edges by opening Window/Data Table.
It is a very rich program, there are more options than you can shake a stick at.
You can set more properties on your nodes and edges in the python code and then they will show up in the data table view and can be used to filter, etc.
You want to pay attention to that update button in the bottom right corner of Gephi, there are a lot of bugs to fix.
This will get you started (as you asked), but for your particular problem:
you will also need to calculate weights for your persons (the "p" nodes), and link them to each other with those weights
Then you need to find a layouter and paramters that positions those nodes the way you want them based on the new weights.
So you don't really need to show the type="f" nodes, you need just the "p" nodes.
The weight between to "p" nodes should be based on the intersection of the sets of the friend names.
There are also Gephi plugins that can then display this in 3D, but that is actually a completely separate issue, you probably want to get it working in 2D first.
This is running on Windows 10 using Anaconda 4.4.1 and Python 3.5.2 and Gephi 0.9.1.

Range for vertical bar chart with google chart-wrapper

I've been trying to figure out how to use google chart-wrapper with my django application but I can't seem to find hardly any documentation on how to use it. After playing around with it for awhile I got it to do most everything I want it to, but I can't seem to figure out how to get the range quite right.
For example, this url:
http://chart.apis.google.com/chart?chxt=x&chd=t:2.0,1.0,192.0,1032.0,22.0,60.0,75.0,94.0,3.0,2.0,1.0,11.0,383.0,3.0,164.0,50.0,12.0,5.0,564.0,7671.0,115.0,331.0&chm=N%2A,000000,0,-1,11&chs=1000x300&cht=bvs&chtt=Failure+Types&chxl=0:|B16|B13|B10|C11|A10|A13|D04|D03|D02|B01|C09|B05|B04|B07|C01|C03|C04|C07|A02|A01|A06|A05
has several values above 100 (in the chd section of the url), but when it gets rendered it cuts anything above 100 off.
This is the code I used to create that url:
hist = {}
d = Defect.objects.all()
for defect in d:
c = Failure.objects.filter(defect = defect).count()
if c > 0:
hist[defect.defcode] = c
m = VerticalBarStack(hist.values())
m.title("Failure Types")
m.size(1000,300)
m.marker('N*', 'black', 0, -1, 11)
m.axes('x')
m.axes.label(0, '|'.join(hist.keys()))
It seems logical that google chart-wrapper would allow me to write something along the lines of m.range(1000) or something similar to specify the range to show on the chart, but that doesn't work and I can't find any real documentation or detailed, complex enough examples to figure it out.
You should add scaling for extended encoding.
I have added the required parameters, as below:
chds=0,2000
your final URL is:
http://chart.googleapis.com/chart?chxt=x&chd=t:2.0,1.0,192.0,1032.0,22.0,60.0,75.0,94.0,3.0,2.0,1.0,11.0,383.0,3.0,164.0,50.0,12.0,5.0,564.0,7671.0,115.0,331.0&chm=N%2A,000000,0,-1,11&chs=500x500&cht=bvs&chds=0,2000&chtt=Failure+Types&chxl=0:|B16|B13|B10|C11|A10|A13|D04|D03|D02|B01|C09|B05|B04|B07|C01|C03|C04|C07|A02|A01|A06|A05

Categories