Update displayed value everytime ipywidgets are updated - python

In my notebook i have 7 FloatSlider widgets. I want to have the product of these 7 widgets displayed at all times in a way that, as the user moves the sliders, the value displayed is updated. Currently i am trying to display the product of the SliderWidgets in a Widgets.Text (n), but i am not sure if it is the best solution.
import ipywidgets as widgets
caption = widgets.Label(value='Play around with the variables to see how N changes!')
r = widgets.FloatSlider(value=1,
min=1.0,
max=3.0,
step=0.1,
description="R*")
fp = widgets.FloatSlider(value=1,
min=0.35,
max=1.0,
step=0.05,
description="fp")
ne = widgets.FloatSlider(value=1
min=0.2,
max=3.0,
step=0.1,
description="ne")
fl = widgets.FloatSlider(value=1,
min=1.0,
max=1.3,
step=0.05,
description="fl")
fi = widgets.FloatSlider(value=1,
min=0.5,
max=1.5,
step=0.05,
description="fi")
fc = widgets.FloatSlider(value=0.20,
min=0.10,
max=0.30,
step=0.05,
description="fi",)
l = widgets.FloatSlider(value=60000000.0,
min=5000000.0,
max=1000000000.0,
step=5000000,
description="fi")
n = widgets.Text(
value= str(int(r.value * fp.value * ne.value * fl.value * fi.value * fc.value * l.value)) + " civilizations" ,
description='Estimated N:',
disabled=True)
left_box = VBox([r, fp, ne,fl])
right_box = VBox([ fi,fc,l,n])
HBox([left_box, right_box])
This code that i used displays the widgets, but does not update the widget n automatically. What is the best way for me to do it, that does not involve printing a new value everytime?

You can use an observe and a callback function on value change for each slider
def on_value_change(change):
n.value = str(int(r.value * fp.value * ne.value * fl.value * fi.value * fc.value * l.value)) + " civilizations"
r.observe(on_value_change)
fp.observe(on_value_change)
# ...

Related

Dropdown Menu - Float Values

I am trying to create a dropdown with ipywidgets, it needs to return a variable value, this variable value may change depending on other slider input values. When I try to return the variable I get the error: NameError: 'adjustment_one' Not Defined.
calculated_area = input_slider / numstorey_input_slider * 0.7
revised_area = input_slider - calculated_area
adjustment_one = revised_area / input_slider
location = ipywidgets.Dropdown(
options=[('Internal', 1), ('Roof', adjustment_one), ('External', 2) ],
value=1,
description='Plant Space Location: ',
)
The above method is solved and was an indenting error however I have now found that I can't pass a float value using the ipywidget dropdown. Below is the code - based on what is selected in the drop down this will be mapped to a dataframe as a multiplier. However when I open the excel document it only every returns the value '0'. This value should actually be 0.87 when Roof is selected, and will change depending on slider input values.
calculated_roof_area = gia_input_slider / numstoreys_input_slider * 0.7
revised_gia_roofinput = gia_input_slider - calculated_roof_area
gia_adjustment_rooftop = revised_gia_roofinput / gia_input_slider
plantspace = ipywidgets.Dropdown(
options=[('Internal', 1), ('Roof', gia_adjustment_rooftop), ('External', 2) ],
value=1,
description='Plant Space Location: ',
)
print(plantspace)
df = pd.read_excel(r'dataframe_final.xlsx', sheet_name='sheet1')
# below recalculates the adjusted qty when the slider position changes
multipliers = {
'Building Footprint Factor': bldg_footprint_factor,
'CAT A Fitout Yes / No': fitout_cat_dropdown,
'GIA Factor': gia_factor,
'GIA Adjustment - Rooftop': plantspace_dropdown
}
df['QP1 Multiplier'] = df['QP1'].map(multipliers)
df['QP2 Multiplier'] = df['QP2'].map(multipliers)
df['QP3 Multiplier'] = df['QP3'].map(multipliers)
df['QP4 Multiplier'] = df['QP4'].map(multipliers)
df['QP5 Multiplier'] = df['QP5'].map(multipliers)
df['QP6 Multiplier'] = df['QP6'].map(multipliers)
df['QP7 Multiplier'] = df['QP7'].map(multipliers)
df['QP8 Multiplier'] = df['QP8'].map(multipliers)
df['QP9 Multiplier'] = df['QP9'].map(multipliers)
Can anybody help?

I need help Building a python app for windows

Windows10/Python3
So i have the beep.pyw file located in startup:shell, it beeps every 30 minutes automatically when you open the pc.
And i'm using Tkinter to make a GUI widget "widget.py" which contains 4 advices to do in the breaks like (breathing stretching, hydrating etc...) = Done
Problem is :
How to open the widget every time the pc beeps.
Should i put both files in one file or how can i add the statement to open the "widget.py" in the "beep.pyw" ?
This is the beep.pyw :
import time
import winsound
beep_time = 30*60
def beep_every60():
while True :
winsound.Beep(2000, 1000)
winsound.Beep(2000, 1000)
time.sleep(beep_time)
beep_every60()
import time
import winsound
from tkinter import *
class WindowsBeep(Tk):
def __init__(self):
super().__init__()
self.title_ = "Windows Beep"
self.title(self.title_)
self.bg = "#222222"
self.fg = "#cccccc"
self["bg"] = self.bg
self.__largura_tela__ = self.winfo_screenwidth()
self.__altura_tela__ = self.winfo_screenheight()
self.porcentagem_largura = 0.50
self.porcentagem_altura = 0.75
self.__largura_app__ = int(self.__largura_tela__ * self.porcentagem_largura)
self.__altura_app__ = int(self.__altura_tela__ * self.porcentagem_altura)
self.centro_l_janela = int((self.__largura_tela__ // 2) - (self.__largura_app__ // 2) + 2)
self.centro_a_janela = int((self.__altura_tela__ * (1 - self.porcentagem_altura)) // 2)
self.__center__ = f"{self.__largura_app__}x{self.__altura_app__}+{self.centro_l_janela}+{self.centro_a_janela}"
self.geometry(self.__center__)
beep_time = 30*60
def beep_every60():
while True :
winsound.Beep(2000, 1000)
winsound.Beep(2000, 1000)
WindowsBeep().mainloop()
time.sleep(beep_time)
beep_every60()

Maya Python updating attributes

I have 3 attributes, 2 of which will be used together to determine the value of the 3rd.
Trig Function - The user selects which trig function they want to use. Right now it's just sin and cos
Radians - User enters the radians value for the trig function.
output - This value will be connected to an attribute on a noise texture.
My problem is how do I set this up so that when I change the values of "Trig Function" & "Radians" the output value gets updated?
Example code:
import maya.cmds as cmds
import math
cmds.window(title="Simple UI in Maya", width=300 )
theMasterLayout = cmds.columnLayout()
groupName = "testGrp"
cmds.group(empty=True, name=groupName)
cmds.addAttr(ln="WaveType", at='enum', en="sin:cos")
cmds.addAttr(ln="radians", at='double', min=0, max=10, dv=0.2, k=True)
cmds.addAttr(ln='WaveValue', at='double', dv=0)
if cmds.getAttr(groupName + ".WaveType") == "sin":
wave = math.sin(cmds.getAttr(groupName + ".radians"))
else:
wave = math.cos(cmds.getAttr(groupName + ".radians"))
cmds.setAttr(groupName + ".WaveValue", wave)
# Display the window
cmds.showWindow()
I was able to find a solution to this issue. Basically it's just using expressions. But if anyone knows of an alternative method I would still love to hear it.
import maya.cmds as cmds
groupName = "testGrp"
cmds.group(empty=True, name=groupName)
cmds.addAttr(ln="WaveType", at='enum', en="sin:cos")
cmds.addAttr(ln="radians", at='double', min=0, max=10, dv=0.2, k=True)
cmds.addAttr(ln='WaveValue', at='double', dv=0)
expString = 'if ('+ groupName + '.WaveType == 0){\n'
expString += groupName + '.WaveValue = sin(' + groupName + '.radians);\n}'
expString += '\nelse {\n' + groupName + '.WaveValue = cos(' + groupName + '.radians);\n}'
cmds.expression( s=expString,
o=groupName,
n="WaveResult",
ae=1,
uc=all )

Select and zoom features of a layer using PyQgis

I want to select features and to zoom on them and do all these steps using PyQgis.
And I'm able to do both of them separatly but it doesn't seems to work when I try to mix the two of them.
Both of the codes I use for them are from the internet. Here's what I use to select features of a layer :
from qgis.core import *
import qgis.utils
lyrMap = QgsVectorLayer('C:/someplace', 'MapName', 'ogr')
QgsMapLayerRegistry.instance().addMapLayer(lyrMap)
expr = QgsExpression("'Attribute' IS NOT NULL")
it = lyrMap.getFeatures(QgsFeatureRequest(expr))
ids = [i.id() for i in it] #select only the features for which the expression is true
lyrMap.setSelectedFeatures(ids)
And it seems to do the trick as features appear selected on QGis.
In order to zoom the code is much more simple, it's just :
canvas = qgis.utils.iface.mapCanvas()
canvas.zoomToSelected(lyrMap)
But it seems that canvas doesn't consider that there's a selection on lyrMap and simply do nothing. I've tried to do the selection manually in QGis, and then zoom using zoomToSelected, and it worked.
But my objective is to do it without needing to do the selection manually...
Note : I don't think that's the issue, but the attribute I'm doing the selection on is from a join between lyrMap and another layer (I didn't put the code here because I don't think it's linked).
Thanks in advances for answers, clues or anything really :) !
This is working for my plugin. I am using python 2.7 and QGIS 1.8 and 2.0.1.You can use this code after including using vector file and adding it to the registry.
self.rubberBand = None
#create vertex marker for point..older versons..
self.vMarker = None
#add rubberbands
self.crossRb = QgsRubberBand(iface.mapCanvas(),QGis.Line)
self.crossRb.setColor(Qt.black)
def pan(self):
print "pan button clicked!"
x = self.dlg.ui.mTxtX.text()
y = self.dlg.ui.mTxtY.text()
if not x:
return
if not y:
return
print x + "," + y
canvas = self.canvas
currExt = canvas.extent()
canvasCenter = currExt.center()
dx = float(x) - canvasCenter.x()
dy = float(y) - canvasCenter.y()
xMin = currExt.xMinimum() + dx
xMax = currExt.xMaximum() + dx
yMin = currExt.yMinimum() + dy
yMax = currExt.yMaximum() + dy
newRect = QgsRectangle(xMin,yMin,xMax,yMax)
canvas.setExtent(newRect)
pt = QgsPoint(float(x),float(y))
self.zoom(pt)
canvas.refresh()
def zoom(self,point):
canvas = self.canvas
currExt = canvas.extent()
leftPt = QgsPoint(currExt.xMinimum(),point.y())
rightPt = QgsPoint(currExt.xMaximum(),point.y())
topPt = QgsPoint(point.x(),currExt.yMaximum())
bottomPt = QgsPoint(point.x(),currExt.yMinimum())
horizLine = QgsGeometry.fromPolyline( [ leftPt , rightPt ] )
vertLine = QgsGeometry.fromPolyline( [ topPt , bottomPt ] )
self.crossRb.reset(QGis.Line)
self.crossRb.addGeometry(horizLine,None)
self.crossRb.addGeometry(vertLine,None)
if QGis.QGIS_VERSION_INT >= 10900:
rb = self.rubberBand
rb.reset(QGis.Point)
rb.addPoint(point)
else:
self.vMarker = QgsVertexMarker(self.canvas)
self.vMarker.setIconSize(10)
self.vMarker.setCenter(point)
self.vMarker.show()
# wait .5 seconds to simulate a flashing effect
QTimer.singleShot(500,self.resetRubberbands)
def resetRubberbands(self):
print "resetting rubberbands.."
canvas = self.canvas
if QGis.QGIS_VERSION_INT >= 10900:
self.rubberBand.reset()
else:
self.vMarker.hide()
canvas.scene().removeItem(self.vMarker)
self.crossRb.reset()
print "completed resetting.."

Position the number below the barcode, using pyBarcode

I'm using pyBarcode to generate PNGs and the number below the barcode is getting cut off on the right. How do I nudge it left a few pixels?
According to the documentation I need to do something like this:
barcode.writer.BaseWriter(paint_text=my_callback)
And define a callback like this:
my_callback(xpos, ypos)
and:
use self.text as text
How exactly do I apply all of that to my Django view (below)?
def barcode(request):
import barcode
from barcode.writer import ImageWriter
from cStringIO import StringIO
def mm2px(mm, dpi=300):
return (mm * dpi) / 25.4
class MyImageWriter(ImageWriter):
def calculate_size(self, modules_per_line, number_of_lines, dpi=300):
width = 2 * self.quiet_zone + modules_per_line * self.module_width
height = 1.0 + self.module_height * number_of_lines
if self.text:
height += (self.font_size + self.text_distance) / 3
return int(mm2px(width, dpi)), int(mm2px(height, dpi))
f = BarcodeForm(request.GET)
if f.is_valid():
try:
i = StringIO()
bc_factory = barcode.get_barcode_class(f.PYBARCODE_TYPE[f.cleaned_data['barcode_type']])
bc_factory.default_writer_options['quiet_zone'] = 1.0
bc_factory.default_writer_options['text_distance'] = 1.0
bc_factory.default_writer_options['module_height'] = 15.0
bc_factory.default_writer_options['module_width'] = 0.3
bc_factory.default_writer_options['font_size'] = 46
bc = bc_factory(f.cleaned_data['text'], writer=MyImageWriter())
bc.write(i)
return HttpResponse(i.getvalue(), mimetype='image/png')
except Exception, e:
return HttpResponseBadRequest(str(e))
else:
return HttpResponseBadRequest('Missing text or unsupported barcode type: %s' % f.errors)
Edit: After answering I noticed you've got a factory that's setting the quiet_zone to 1.0. Change that back to 6.5 and I'd imagine it will look fine.
Edit2: I misunderstood the exact problem you were experiencing.
For whatever reason the author of pyBarcode is putting the text centered in the middle of the bar code. When the render method calls _paint_text() it passes in xpos/2, which sets it in the middle of the barcode. I guess this is okay with the default font he's using, but when you increased the font, it no longer fits.
Instead I was able to place it on the left side, by overriding the _paint_text() method. In the last line below, the variable pos is just a tuple containing an (x,y) coordinate that tells PIL where to draw the text on the bar code. So I've made sure x is lined up with the bar code. If you need it right aligned, you could play around with the xpos variable to get it where you need.
Give this a shot:
class MyImageWriter(ImageWriter):
def calculate_size(self, modules_per_line, number_of_lines, dpi=300):
width = 2 * self.quiet_zone + modules_per_line * self.module_width
height = 1.0 + self.module_height * number_of_lines
if self.text:
height += (self.font_size + self.text_distance) / 3
return int(mm2px(width, dpi)), int(mm2px(height, dpi))
def _paint_text(self, xpos, ypos):
# this should align your font to the left side of the bar code:
xpos = self.quiet_zone
pos = (mm2px(xpos, self.dpi), mm2px(ypos, self.dpi))
font = ImageFont.truetype(FONT, self.font_size)
self._draw.text(pos, self.text, font=font, fill=self.foreground)

Categories