Friday, July 31, 2009

python-twitter, why not?

Why Not?

I have recently started to experience Facebook and twitter, living the life of a truly 'connected' geek. But as you all could have guessed, being connected isn't all that interesting of an idea to me. In the end, what matters the most is the Code. How can I interact with twitter? There is a plethora of libraries available for interacting with Twitter. I heart Python and decided on hacking at python-twitter. The Scripting with Curl article linked off of Twitter was rather informative and provided me a reasonably good amount of background. If interested, most everything done in the article can be replicated with urllib2 in Python, and that's good to know. :-) I needed to install python-twitter and had the choice for installing from source or using easy_install. I'm on windows at the moment and have become use to using easy_install whenever possible, so I simply executed:
easy_install python-twitter
Post install, I got a warm fuzzy feeling executing:
import twitter
api = twitter.Api()
ooooh, ahhhh, I already feel more connected..... I used the api reference here as my introduction to the api. I usually like to toy a bit at the interactive interpreter to see what types of methods / attributes are on certain objects and see if I can figure things out on my own. First thing I noticed was there is a plethora of help available: help(twitter.Api), help(api.GetDirectMessage), etc... That was a +. I also noticed that upon executing api.GetDirectMessages() out of line, I received a good error message with a human-readible description. Yet another huge +. I like to look for things like this from the start, to see how reasonably the API is.

Getting my list of Followers

I decided to attack a simple problem: get my list of followers. I signed up to twitter around Aug 2008 but never used it or told anyone I had an account. I only started using it seriously the last week. So, if I try to do GetFollowers just to see what happens and...

>>> api.GetFollowers()
Traceback (most recent call last):
File "", line 1, in
File "build\bdist.win32\egg\twitter.py", line 1597, in GetFollowers
twitter.TwitterError: twitter.Api instance must be authenticated
Woot! Another good error message. So, let's get authenticated. Upon browsing dir(api), I found a SetCredentials method, which sounds like what I was searching for. The help provided a simple and straight forward explanation of the call:
api.SetCredentials('myusername','mypassword')
All there is to it, no hackin at headers required. Can I get my followers now?
>>> len(api.GetFollowers())
15
I only have a few followers at this point in time, perhaps you can be another? It was far too easy to do this, yes/ no? Notice above I was getting the length of the list returned by GetFollowers. This call returns a List of twitter.User objects that allows you to obtain further details on the user of interest. To get the screen names of all my followers, all that needs to be done is the following:

followers = api.Followers()
for follower in followers:
print follower.screen_name

And the listing is provided. The are several functions available in the api that simplify interacting with twitter. You can trivially:
  • get different user status
  • get your direct messages
  • get replies
  • get a friends timeline
  • post a message
  • post an update (or updates)
It's pretty slick. Yet another case of Python, along with a nice API making my life simpler.

I'll probably follow up this article at a later time with a more detailed look into it but hopefully you enjoyed the brief.

Yet Another ArcObjects API Adventure

If you develop software with ArcObjects long enough, you will come to learn that experience is what matters the most. The Developer docs that come distributed with the SDK are only the first stop to finding out the real story of what to do with an ArcObject. I've been bitten several times by different ArcObjects and today is yet another one of those times. When it comes to doing GeoProcessing, the idea behind it is simple.
  1. Create a Geoprocessor
  2. Set some properties
  3. Create a geoprocessing tool instance
  4. Set some propertites
  5. Call the Geoprocessor with the instance of the tool
  6. Done
It's cake, at least in theory. Today, I had the need to do some geoprocessing using the ExtractByPolygon operation. According to the docs, the polygon property can be set with an "object" that is a polygon:
Polygon that defines the area to be extracted. X,Y coordinates define the vertices of the polygon. (In, Required)
I proceed to do what feels like the right thing to do. Create my PolygonClass, start creating a square that represents my extents and voila!
Failed to execute (Extract by Polygon). Parameters are not valid. Invalid value type for parameter polygon
That's actually a good error message! Now, I have seen this type of thing before with using the geoprocessing library and new exactly what to do; Go to the support forums and start searching. I was bit by a different operation once, that took a string as the object parameter. If you didnt put a literal "; " at the end of the string the operation would fail (without any indication of why). So I began to adventure into the infamous forums. I dug up an old desktop help article from 9.1 here and noticed the way they were calling it in a script:
ExtractByPolygon_sa C:/data/raster1 "0 0;1 1;2 2;3 3;4 4;5 3;6 2;7 1;8 0" C:/data/final_1 OUTSIDE
I read the description on this page which states this for the polygon parameter:

Polygon that defines the area to be extracted. X,Y coordinates define the vertices of the polygon.

Yes, completely useless. I could not rely on the description, just the random example that was typed up here. Then I get to creating a string with similar content and it all just works:

string strPolygon = String.Format("{0} {1};{2} {3};{4} {5};{6} {7}", left, bottom, left, top, right, top, right, bottom);

I really wish there was a moral to this story. I can't think of a good one here besides the age old developer gripe: "Documentation sucks".

ArcObjects Get Raster Extents (Properties)

I wanted to grab a rasters extents and was trying to avoid opening a RasterDataset and going through all the workspace stuffs. Experience has taught me to always look into the DataManagementTools before banging my head. Low and behold, the GetRasterProperties class was found.
Geoprocessor geoprocessor = new Geoprocessor();

GetRasterProperties rasterProperties = new GetRasterProperties();
rasterProperties.in_raster = rasterFilename;
rasterProperties.property_type = "TOP";
geoprocessor.Execute(rasterProperties,null);
double top = rasterProperties.property;

rasterProperties.property_type = "BOTTOM";
geoprocessor.Execute(rasterProperties,null);
double bottom = rasterProperties.property;

rasterProperties.property_type = "LEFT";
geoprocessor.Execute(rasterProperties,null);
double left = rasterProperties.property;

rasterProperties.property_type = "RIGHT";
geoprocessor.Execute(rasterProperties,null);
double right = rasterProperties.property;

I really wish there was a way to return more than one property, seems kindof inefficient doing it this way. Maybe i'll go back and do it the other way, using the IRaster2 interface. Grrr...

Thursday, July 30, 2009

Embedding Images in Word (Python/C#/VB)

I wrote a utility that exports trac wiki content into static html for the purposes of dumping it into a word document (for the powers that be). The Microsoft Word selection.InsertFile method turned out to be quite a lifesaver for this. My exporter utility does some hacking up of the urls so that bookmarks can be created for the hyperlinks. This makes it easy to navigate the word doc since the user can click the URLs in the doc and it will take them to the appropriate page/ paragraph of the content. It all worked out rather nicely, about 50 lines of python for the main word-doc-generation code. When all is said and done, I handed off the document to others to read and admire. After doing this, I was informed that all the images were missing. I found that hard to believe, since I could clearly see the images on my machine. So I looked into it and found out the InsertFile method does not cause images to be embedded within the word doc. As a result, the only machine the doc worked on was mine, since I had all the images within the docs folder..... nice. I could not find any nice one-stop method for telling the word doc to "save all images into this doc for me". That's a pain. I posted up an inquiry to Microsoft Discussion Groups and waited over night for an answer but nothing good came through. After waiting another day, a Jay Freedman gave me a tip. I ended up hacking it together and using the code provided below:

for shape in doc.InlineShapes:
if not shape.LinkFormat is None:
filename = shape.LinkFormat.SourceFullName
shape.LinkFormat.SavePictureWithDocument = True
shape.LinkFormat.BreakLink()


Efficient or not, it works. With that being said, if any of you know of a cleaner way to accomplish this, please let me know!

Testing 555 timers is FUN

I had a few old 555 timers sitting around and got to wondering if they were any good. So, I had a bit of fun putting this tester together.



I think it's one of those things anyone who works with 555 timers should have around the shop... just in case. Thanks Tony Van Room!