pyqtgraph, how track log/linear axes transformation changes between linked axes - pyqtgraph

I have 3 linked views, linked by X axis. This works great. However, when I switch one plot to log X mode, the others do not switch to log x mode, but they pop in to zoom way in to the log version of the x axis.
How do it make it so the log X transformation applies to all plots?
So far, I simply use the code
diViewWidget.setXLink(frViewWidget)
noiseViewWidget.setXLink(diViewWidget)
The data should look like this:
but actually look like this:
Basically, to reproduce you can go to any 2 linked views, right click and set the transformation to log x.
The workaround I found is to go to each plot individually and set the transformation individually, but I'd like it to happen programatically.
Thanks,
-Caleb

#learning qt i just found a better linkLogXChecks version
from itertools import permutations
def linkLogXChecks(plotitems):
for a, b in permutations(plotitems, 2):
a.ctrl.logXCheck.toggled.connect(b.ctrl.logXCheck.setChecked)

https://groups.google.com/forum/#!msg/pyqtgraph/3686qqVHgpI/bmBAQ_sDKJIJ
https://forum.qt.io/topic/39241/how-to-set-logarithmic-scale-on-a-qgraphicsview/2
I couldn't apply that fix across separate PlotItems, so tried broadcasting the changed checkbox signal and it seems to work
import pyqtgraph as pg
data = pg.np.random.normal(size=100)
app = pg.QtGui.QApplication([])
win = pg.GraphicsWindow()
p1 = win.addPlot(y=data)
win.nextRow()
p2 = win.addPlot(y=data)
p2.setXLink(p1)
win.nextRow()
p3 = win.addPlot(y=data)
p3.setXLink(p1)
def linkLogXChecks(plotitems):
def broadcast(state):
for p in plotitems:
p.ctrl.logXCheck.setChecked(state)
for p in plotitems:
p.ctrl.logXCheck.toggled.connect(broadcast)
linkLogXChecks([p1, p2, p3])
pg.QtGui.QApplication.instance().exec_()

Related

How to control Ipyvuetify ProgressCircular

I want to use an ipyvuetify widget called ProgressCircular to show the loading process. Therefore, I was trying to figure out how to show and hide the widget in my code.
progress=v.ProgressCircular(width=3,
color='red',
indeterminate=True,
)
Although I was able to see all the attributes with dir(), I still couldn't find the right one to use. How do people figure out how to use classes or functions in a package that lacks samples.
dir(v.ProgressCircular)
You can use display(progress) within an ipywidgets Output widget.
import ipyvuetify as v
import ipywidgets as ipyw
import time
progress=v.ProgressCircular(width=3,
color='red',
indeterminate=True,
)
output = ipyw.Output()
display(output)
with output:
display(progress)
time.sleep(2)
output.clear_output()
I will assume that you are working in a Jupyter environment :
after declaring your widget place it on the last line of your cell or use display as suggested by #ac24:
progress = v.ProgressCircular(
width = 3,
color = 'red',
indeterminate = True
)
progress
# alternatively
# display(progress)
once it's done you can play with it using some very basic html attributes
progress.class_ = 'd-none' # disapear
progress.class_ = None # shown
As you were complaining about the documentation, see here for the usage of HTML attributes https://ipyvuetify.readthedocs.io/en/latest/usage.html#setting-attributes, more examples would be useless as the possible combinations of html attributes are virtually infinite. Lucky for us vuetify.js is providing a very complete one that can be used in combination with the ipyvuetify one :
https://vuetifyjs.com/en/styles/display/
No need to use Output or styles for this, just make a container widget and change its children:
import ipyvuetify as v
import time
progress=v.ProgressCircular(width=3,
color='red',
indeterminate=True,)
container = v.Html(tag='div', children=[progress])
display(container)
time.sleep(2)
container.children=[v.Chip(children=['Done'])]

Is there a way to expand groups with the XDSM diagram creation in OpenMDAO?

Most of my test files involve the creation of an IndepVarComp that gets connected to a group. When I go to create an XDSM from the test file, it only shows the IndepVarComp Box and the Group Box. Is there a way to get it to expand the group and show what's inside?
This would also be useful when dealing with a top level model that contains many levels of groups where I want to expand one or two levels and leave the rest closed.
There is a recurse option, which controls if groups are expanded or not. Here is a small example with the Sellar problem to explore this option. The disciplines d1 and d2 are part of a Group called cycle.
import numpy as np
import openmdao.api as om
from openmdao.test_suite.components.sellar import SellarNoDerivatives
from omxdsm import write_xdsm
prob = om.Problem()
prob.model = model = SellarNoDerivatives()
model.add_design_var('z', lower=np.array([-10.0, 0.0]),
upper=np.array([10.0, 10.0]), indices=np.arange(2, dtype=int))
model.add_design_var('x', lower=0.0, upper=10.0)
model.add_objective('obj')
model.add_constraint('con1', equals=np.zeros(1))
model.add_constraint('con2', upper=0.0)
prob.setup()
prob.final_setup()
# Write output. PDF will only be created, if pdflatex is installed
write_xdsm(prob, filename='sellar_pyxdsm', out_format='pdf', show_browser=True,
quiet=False, output_side='left', recurse=True)
The same code with recurse=False (d1 and d2 are not shown, instead their Group cycle):
To enable the recursion from the command line, use the --recurse flag:
openmdao xdsm sellar_pyxdsm.py -f pdf --recurse
With the function it is turned on by default, in the command line you have to include the flag. If this does not work as expected for you, please provide an example.
You can find a lot of examples with different options in the tests of the XDSM plugin. Some of the options, like recurse, include_indepvarcomps, include_solver and model_path control what is included in the XDSM.

Multiple altair charts generated by the same cell

I have a list of pandas dataframes I named entries, which I want to visualize after running code from the same cell. Below is the code I used :
alt.data_transformers.disable_max_rows()
for entry in entries :
entry['ds'] = entry.index
entry['y'] = entry['count']
entry['floor'] = 0
serie = alt.Chart(entry).mark_line(size=2, opacity=0.7, color = 'Black').encode(
x=alt.X('ds:T', title ='date'),
y='y'
).interactive().properties(
title='Evolution of '+entry.event.iloc[0]+' events over time'
)
alt.layer(serie)\
.properties(width=870, height=450)\
.configure_title(fontSize=20)
When i run the same code out of the 'for' loop, I get to see the one chart that corresponds to one dataframe, but once I run the code above, I don't get any graphs at all.
Does anyone know why It's not working or how to solve this issue?
TLDR: use chart.display()
Unless a chart appears at the end of the cell, you must manually display it.
By analogy, if you run
x + 1
by itself, Python will display the result. However, if you run
for x in range(10):
x + 1
Python will not display anything, because the last statement in the cell (in this case the for loop) has no return value to display. Instead you have to write
for x in range(10):
print(x + 1)
For altair, the mechanism is similar: if the chart is defined in the last statement in the cell, it will be automatically displayed. Otherwise, you have to manually trigger the display, which you can do using the display method:
for i in range(10:
chart = alt.Chart(...)
chart.display()
For more information on display troubleshooting in Altair, see https://altair-viz.github.io/user_guide/troubleshooting.html

How to feed data properly in tensorflow

I have been learning Tensorflow and understanding feed_dict has been a challenge. Take for example the following piece of code i am working on
p=0
self.sequence_length=25
with tf.Session() as sess:
init.run()
char_to_ix={ch:ix for ix,ch in enumerate(self.words)}
ix_to_char={ix:ch for ix,ch in enumerate(self.words)}
words_in_input=self.data[p:p+self.sequence_length]
inputs=[char_to_ix[ix] for ix in words_in_input]
words_in_target=self.data[p+1:p+self.sequence_length+1]
targets=[char_to_ix[ix] for ix in words_in_target]
onex=sess.run([selected_next_letter],feed_dict={self.X:inputs,self.y:targets})
p=p+1
This gives the error: Shapes of all inputs must match: values[0].shape = [25] != values[1].shape = []
However, when I edit the code to
with tf.Session() as sess:
init.run()
char_to_ix={ch:ix for ix,ch in enumerate(self.words)}
ix_to_char={ix:ch for ix,ch in enumerate(self.words)}
words_in_input=self.data[p:p+self.sequence_length]
inputs=[char_to_ix[ix] for ix in words_in_input]
words_in_target=self.data[p+1:p+self.sequence_length+1]
targets=[char_to_ix[ix] for ix in words_in_target]
for x,y in zip(inputs,targets):
onex=sess.run([selected_next_letter],feed_dict={self.X:x,self.y:y})
It executes.
My questions is: Is it possible to feed the whole list such as inputs and targets in the feed_dict or must I input it through a loop one by one. I ask this because the tutorials I have been reading, I see a whole list being passed in a feed_dict such as
loss_val = sess.run([train_op, loss_mean], feed_dict={
images_batch:images_batch_val,
labels_batch:labels_batch_val
})
Usually the reason for that error is because your input array(x) isn’t the same size as your labels array(y). As the error states it looks like your labels array is empty. Before doing anything tensorflowy make sure both x and y arrays have values in them and that they are of the same size.
To answer your question, yes you can use lists when training and is the preferred way of using tensorflow.

Get Geometry of widgets with variable size

Situation
I have a pop_up widget (say a textbox), which I can place arbitrarily on the screen by setting the properties x and y accordingly.
On the other hand I use the prompt, which is located in the default wibar.
I would like to place the pop_up widget directly below the prompt
Problem
I was not yet able to gather any useful information about the geometry of the prompt. With geometry I mean its x and y values together with its height and width. I solved the y-positioning by using the height of the wibar itself.
But I am stuck with x-positioning.
Is there a way to get the width of the widgets within the toolbar?
Notice
I read something about forced_width, but in this situation it sounds like a hack to me. So I would prefer to avoid forcing any widths.
I'm currently running awesome WM 4.2 on Fedora 26
Part of a problem is that "a" widget does not have a position and size since awesome allows widgets to be shown in multiple places at once. However, if we just ignore this problem, something like the following could work (to be honest: I did not test this):
function find_widget_in_wibox(wb, widget)
local function find_widget_in_hierarchy(h, widget)
if h:get_widget() == widget then
return h
end
local result
for _, ch in ipairs(h:get_children()) do
result = result or find_widget_in_hierarchy(ch, widget)
end
return result
end
local h = wb._drawable._widget_hierarchy
return h and find_widget_in_hierarchy(h, widget)
end
However, I have to warn you that the above could break in newer versions of awesome since it access non-public API (the part with wb._drawable._widget_hierarchy). There is a way to work with just the public API using :find_widgets(), but I am too lazy for that for now.
The above function gets the wibox.hierarchy instance representing a widget which allows to get the geometry of the prompt via something like the following (in the default config of awesome 4.2):
local s = screen.primary -- Pick a screen to work with
local h = find_widget_in_wibox(s.mywibox, s.mypromptbox)
local x, y, width, height = h:get_matrix_to_device()
:transform_rectangle(0, 0, h:get_size())
local geo = s.mywibox:geometry()
x, y = x + geo.x, y + geo.y
print(string.format("The widget is inside of the rectangle (%d, %d, %d, %d) on the screen", x, y, width, height)
Finally, note that the widget hierarchy is only updated during repaints. So, during startup the code above will fail to find the widget at all and right after something changed (e.g. you entered another character into the promptbox), the above will still "figure out" the old geometry.

Resources