Adding Progress Bar to gdal.Warp() - python-2.7

I am trying to figure out a way to use progress bar in gdal.Warp() to show how much of a job is done. For progress bar, I am using Tqdm and gdal.Warp() is used to crop image from remote URL
def getSubArea(url):
vsicurl_url = '/vsicurl/' + url
output_file = 'someID_subarea.tif'
gdal.SetConfigOption('GDAL_HTTP_UNSAFESSL', 'YES')
gdal.Warp(output_file, vsicurl_url, dstSRS='EPSG:4326', cutlineDSName='area.geojson', cropToCutline=True)
I know there is callback argument that reports progress from 0 to 1, but its only called after gdal.warp has finished downloading cropped image.

You may add a callback function for progress through the 'kwargs' parameter in 'gdal.Warp' (documentation: https://gdal.org/python/).
Code:
def getSubArea(url):
vsicurl_url = '/vsicurl/' + url
output_file = 'someID_subarea.tif'
# Data you want to pass to your callback (goes in to unknown parameter)
es_obj = { ... }
kwargs = {
'dstSRS': 'EPSG:4326',
'cutlineDSName': 'area.geojson',
'cropToCutline': True,
'callback': progress_callback,
'callback_data': es_obj
}
gdal.SetConfigOption('GDAL_HTTP_UNSAFESSL', 'YES')
gdal.Warp(output_file, vsicurl_url, **kwargs)
def progress_callback(self, complete, message, unknown):
# Calculate percent by integer values (1, 2, ..., 100)
percent = floor(complete * 100)
# Code for saving or using percent value
...
About progress callback: https://gdal.org/api/cpl.html#_CPPv416GDALProgressFunc

See answer here around native gdal callback function.
If you wanted to report the download progress of the raster, you'd likely need to split that out as a separate step using something like requests and wrapping that with a progress bar like tqdm or progressbar2.

Related

Send Image or Document with Inline Menu

I am coding an Python Telegram Bot with python-telegram-bot. I created a custom inline menu.
I want that the User could press a button and will get an picture. The send_photo function needs an instance of bot an update.
But I don't know how to pass that on to the CallBackQuery handler.
Does anyone have an idea how to solve it?
The send photo function:
def gvu(bot, update):
bot.send_photo(update.message.chat_id, photo=open('botpic/gvu.jpg', 'rb'))
The Handler in Main Routine:
updater.dispatcher.add_handler(CallbackQueryHandler(pattern="1", callback=gvu))
return self.callback(dispatcher.bot, update, **optional_args)
The error:
TypeError: callback_handler() got an unexpected keyword argument 'chat_data'
This works for me:
buttonsMenu = [
[telegram.InlineKeyboardButton("UP", callback_data="UpVote")],
[telegram.InlineKeyboardButton("DOWN", callback_data="DownVote")],
]
keyboard_markup = telegram.InlineKeyboardMarkup(buttonsMenu)
context.bot.sendPhoto(chat_id=update.message.chat.id, photo=open('./imgpath.jpg'), 'rb'),caption='messageText', reply_markup=keyboard_markup)
This will send an image, with text and 2 butttons below the text msg.
Now for the callback query, i did this in main():
# Callbacks for the msg buttons
dp.add_handler(CallbackQueryHandler(vote, pattern="UpVote"))
dp.add_handler(CallbackQueryHandler(vote, pattern="DownVote"))
Where vote , is a def that runs the code i want for that callback.
hope it makes sense.
Read into documentation here:
https://core.telegram.org/bots/api#inlinequery
https://github.com/python-telegram-bot/python-telegram-bot/blob/master/examples/inlinekeyboard.py

How can I fix my estimator classifier code

Hi I'm new to Tensorflow and I've been practicing with the tensorflow.estimator library. Basically I ran the inbuilt tf.estimator.DNNClassifier algorithm below
import tensorflow as tf
def train_input_fn(features, labels, batch_size):
"""An input function for training"""
# Convert the inputs to a Dataset.
dataset = tf.data.Dataset.from_tensor_slices((dict(features), labels))
# Shuffle, repeat, and batch the examples.
return dataset.shuffle(1000).repeat().batch(batch_size)
# Feature columns describe how to use the input.
my_feature_columns = []
for key in landmark_features.keys():
my_feature_columns.append(tf.feature_column.numeric_column(key=key))
# Build a DNN with 2 hidden layers and 10 nodes in each hidden layer.
classifier = tf.estimator.DNNClassifier(feature_columns=my_feature_columns, hidden_units=[10, 10],n_classes=10)
dataset = train_input_fn(landmark_features, emotion_labels, batch_size = 1375 )
However I keep getting the following error:
INFO:tensorflow:Using default config.
WARNING:tensorflow:Using temporary folder as model directory: /tmp/tmpc_tag0rc
INFO:tensorflow:Using config: {'_model_dir': '/tmp/tmpc_tag0rc', '_tf_random_seed': None, '_save_summary_steps': 100, '_save_checkpoints_steps': None, '_save_checkpoints_secs': 600, '_session_config': allow_soft_placement: true
graph_options {
rewrite_options {
meta_optimizer_iterations: ONE
}
}
Any idea on what I can do to fix my code ?

Pepper robot: How to use tablet to send text input for further processing in Choregraphe?

I need to send a user text input to the robot through the integrated tablet, and catch it somehow, for further processing in Choregraphe.
After reading the Aldebaran documentation about ALTabletService API, I found few methods which might be a solution to all this. The methods are ALTabletService::showInputTextDialog and ALTabletService::onInputText, but somehow I can't get them to work: they return absolutely nothing when I input some text through the tablet.
I need access to the string created when the user inputs a piece of text. Any advice how to do it?
i realized this without ALTabletService methods showInputTextDialog or onInputText
My Approach:
I made an html page with an input field and a button to send the input.
On button press I use the forceInput method from ALDialog doc via QiMessaging Javascript library. doc
I can't test it right now but this should help as a inspiration
function forceInput(input) {
QiSession(function(session) {
session.service('ALDialog').then(function(ALDialog) {
ALDialog.forceInput(input);
});
}
}
Now you can send the input to the topic.
This could be sth like "imput_from_tablet blablabla".
And in the Dialog you catch
u:(imput_from_tablet _*) $1
Where $1 should be blablabla.
Hope that helps
best regards
You can create a webpage for the tablet and package it in your application - see the documentation here; then on that webpage you can create a text input field (be careful that the bottom half of the screen will be hidden by the keyboard when the field is selected), and then use the javascript SDK to (for example) raise an ALMemory event with the inputted text value, that you can then get from Choregraphe.
I had exactly the same problem and I found this ALTabletService::onInputText method in the signal list. You can find examples how to use signals on the same page. Based on these examples I created the following script that can get a value from the input field:
import qi
import sys
def main(app):
try:
session = app.session
tabletService = session.service("ALTabletService")
tabletService.showInputTextDialog("Example dialog", "OK", "Cancel")
signal_id = 0
def callback(button_id, input_text):
if button_id == 1:
print "'OK' button is pressed."
print "Input text: " + input_text
if button_id == 0:
print "'Cancel' button is pressed"
tabletService.onInputText.disconnect(signal_id)
app.stop()
# attach the callback function to onJSEvent signal
signal_id = tabletService.onInputText.connect(callback)
print "Signal ID: {}".format(signal_id)
app.run()
except Exception, e:
print "Error was: ", e
if __name__ == "__main__":
ip = "10.0.10.254" # the IP of the robot
port = 9559
try:
connection_url = "tcp://{}:{}".format(ip, port)
app = qi.Application(url=connection_url)
app.start()
except RuntimeError:
print("Can't connect to Naoqi.")
sys.exit(1)
main(app)

Python ReportLab - Clickable TOC with X of Y page numbering

Using ReportLab 2.7, Python 2.7:
I can create a pdf with clickable bookmarks in the table of contents (toc), or I can create a pdf with "x of y" page numbering, but the bookmarkpage(key) appears to break when I try to do both.
Example code:
class MyDocTemplate(BaseDocTemplate):
def __init__(self, filename, **kw):
self.allowSplitting = 0
BaseDocTemplate.__init__(self, filename, **kw)
template = PageTemplate('normal', [Frame(2.5*cm, 2.5*cm, 15*cm, 25*cm)]) #, id='F1'
self.addPageTemplates(template)
def afterFlowable(self, flowable):
if isinstance(flowable, Paragraph):
txt = flowable.getPlainText()
style = flowable.style.name
if style == 'Heading1':
key = 'h1-%s' % self.seq.nextf('heading1')
self.canv.bookmarkPage(key)
self.notify('TOCEntry', (0, txt, self.page))
elif style == 'Heading2':
key = 'h2-%s' % self.seq.nextf('heading2')
print key
self.canv.bookmarkPage(key)
self.notify('TOCEntry', (1, txt, self.page, key))
class NumberedCanvas(canvas.Canvas):
def __init__(self, *args, **kwargs):
canvas.Canvas.__init__(self, *args, **kwargs)
self._saved_page_states = []
def showPage(self):
self._saved_page_states.append(dict(self.__dict__))
self._startPage()
def save(self):
"""add page info to each page (page x of y)"""
num_pages = len(self._saved_page_states)
for state in self._saved_page_states:
self.__dict__.update(state)
self.draw_page_number(num_pages)
canvas.Canvas.showPage(self)
canvas.Canvas.save(self)
def draw_page_number(self, page_count):
self.setFont('Times-Bold',14)
self.drawRightString(7.6*inch,.5*inch,
"Page %d of %d" % (self._pageNumber, page_count))
h1 = PS(name = 'Heading1',
fontSize = 14,
leading = 16)
h2 = PS(name = 'Heading2',
fontSize = 12,
leading = 14,
leftIndent = 25)
#Build story.
story = []
toc = TableOfContents()
#For conciseness, using the same styles for headings and TOC entries
toc.levelStyles = [h1, h2]
story.append(toc)
story.append(PageBreak())
story.append(Paragraph('First heading', h1))
story.append(Paragraph('Text in first heading', PS('body')))
story.append(Paragraph('First sub heading', h2))
story.append(Paragraph('Text in first sub heading', PS('body')))
story.append(PageBreak())
story.append(Paragraph('Second sub heading', h2))
story.append(Paragraph('Text in second sub heading', PS('body')))
story.append(Paragraph('Last heading', h1))
doc = MyDocTemplate("mypdf.pdf")
doc.multiBuild(story, canvasmaker=NumberedCanvas)
Any comments would be greatly appreciated.
found this initially looking for a solution to no avail, however, figured something out which works for me and wish to share as follows:
With the starting point of the reportlab example as regards to creating a toc containing document -which I assume you used in the first place- proceed as follows.
Modify the template assignment in the init function by adding the options onPage and onPageEnd defining calls to functions for drawing a header and a footer onto the page as follows, guess you could do the same within one function only, however, I used two in order to separate the header/footer section in my usecase:
template = PageTemplate('normal', [Frame(2.5*cm, 2.5*cm, 15*cm, 25*cm, id='F1')],onPage=header,onPageEnd=footer)
add the named header/footer functions to your class as shown below with illustrating some options for clarification including the page number in the footer function to make sure the question is answered:
def header(canvas, doc):
canvas.saveState()
canvas.drawImage('some_image.gif', 5,780, width=None,height=None,mask=None)
canvas.setLineWidth(1)
canvas.line(5,780,120,780)
canvas.setFont('Times-Bold',16)
canvas.drawString(108, 108, 'blah')
canvas.restoreState()
def footer(canvas, doc):
canvas.saveState()
canvas.setFont('Times-Roman',9)
canvas.drawImage('py.jpg', inch,inch, width=None,height=None,mask=None)
canvas.drawString(inch, 0.75 * inch, "Page %d " % doc.page)
canvas.restoreState()
Whatever you did with the added 'numbered canvas class' and why it breaks I don't know, but since your provided code reminds me strongly of the reportlab toc example I guess you can start with that, apply my suggested changes/additions and see how it goes.
That should do the trick, hope that helps!

How to pass parameters via the selector/action?

Is there a way to pass parameters via the addTarget call as it calls another function?
I've also tried the sender method - but that seems to break as well. What's the correct way to pass the parameters without creating global variables?
#my_button = UIButton.buttonWithType(UIButtonTypeRoundedRect)
#my_button.frame = [[110,180],[100,37]]
#my_button.setTitle("Press Me", forState:UIControlStateNormal)
#my_button.setTitle("Impressive!", forState:UIControlStateHighlighted)
# events
newtext = "hello world"
#my_button.addTarget(self, action:'buttonIsPressed(newtext)', forControlEvents:UIControlEventTouchDown)
view.addSubview(#my_button)
def buttonIsPressed (passText)
message = "Button was pressed down - " + passText.to_s
NSLog(message)
end
Update:
OK, here's a method with an instance variable that worked.
#my_button = UIButton.buttonWithType(UIButtonTypeRoundedRect)
#my_button.frame = [[110,180],[100,37]]
#my_button.setTitle("Press Me", forState:UIControlStateNormal)
#my_button.setTitle("Impressive!", forState:UIControlStateHighlighted)
# events
#newtext = "hello world"
#my_button.addTarget(self, action:'buttonIsPressed', forControlEvents:UIControlEventTouchDown)
view.addSubview(#my_button)
def buttonIsPressed
message = "Button was pressed down - " + #newtext
NSLog(message)
end
The easiest way of attaching "parameters" to a rubymotion UIButton call is through the use of tags.
First set up a button with a tag attribute. This tag is the parameter you want to pass to the target function.
#button = UIButton.buttonWithType(UIButtonTypeRoundedRect)
#button.setTitle "MyButton", forState:UIControlStateNormal
#button.frame =[[0,0],[100,50]]
#button.tag = 1
#button.addTarget(self, action: "buttonClicked:", forControlEvents:UIControlEventTouchUpInside)
Now create a method that accepts sender as a parameter:
def buttonClicked(sender)
mytag = sender.tag
#Do Magical Stuff Here
end
Forewarning: As far as I know, the tag attribute only accepts integer values. You could get around this by putting your logic into the target function like this:
def buttonClicked(sender)
mytag = sender.tag
if mytag == 1
string = "Foo"
else
string = "Bar"
end
end
Initially I tried setting the action with action: :buttonClicked which worked but did not allow for using the sender method.
Yes, you usually create instance variables in your Controller class, and then just call methods on them from any method.
According to the documentation using setTitle is the general way to set a title of a UIButton instance. So you're doing it right.