blog.humaneguitarist.org

discoveries in digital audio, music notation, and information encoding

random mallard tests

leave a comment

Yesterday, I posted this post about a method of sorting I’d been thinking about for a while. I also posted what I think is a solution in terms of an algorithm and a Python implementation.

Not having real data to play with, I thought I’d try some random tests.

So, here’s the Python code below for getting random results and the output from running the random results generator a few times. In the output, I had results from the “b” list print out with an indentation to make it easier to see that while the results are intermixed, the original ordering per the “a” and “b” sets stays intact.

Yeah,  I know nobody cares about any of this except me, but this blog is largely a self-reference library for myself.

Python:

from duck_sort import duck_sort
import random

## auto-add tuple of data and random scores to list.
def make_rand(array, array_name):
  limit = random.randrange(1,10) 
  for i in range(1,limit):
    name = str(array_name) + str(i)
    md = (name, random.randint(0,100))
    array.append(md)
  return array

## fill lists with random data, output results.
def duck_test():
  a = []
  b = []
  make_rand(a, "a")
  make_rand(b, "b")

  ## use duck_sort() on random data; print results.
  for result in duck_sort(a,b):
    tab = ""
    if result[0][0] == "b": # for reading ease.
      tab = "\t"
    print tab + str(result)

Output:

>>> duck_test()
('a1', 52)
('a2', 60)
('a3', 95)

>>> duck_test()
    ('b1', 37)
('a1', 14)

>>> duck_test()
('a1', 45)
    ('b1', 36)
    ('b2', 39)
    ('b3', 14)
    ('b4', 65)
    ('b5', 48)
    ('b6', 33)
('a2', 11)
('a3', 51)
('a4', 30)
('a5', 31)
('a6', 57)

>>> duck_test()
('a1', 90)
    ('b1', 85)
    ('b2', 34)
    ('b3', 39)
('a2', 21)
('a3', 92)
('a4', 18)
    ('b4', 2)
    ('b5', 76)
    ('b6', 57)
    ('b7', 11)
--------------

Related Content:

Written by nitin

November 26th, 2014 at 11:43 am

Posted in scripts

Tagged with , ,

Homer Simpson’s quackish approach to sorting federerated search results

leave a comment

Over two years ago I posted this post with regard to sorting results in a federated search. That’s to say I’ve been wondering how to logically sort the results from more than one search source (local database, external search API, etc.) into one set of results for some time.

The approach I outlined in that post still makes sense to me, but what I’ve always been thinking about was how to sort two or more sets where the final sort respects the original sort order of each set.

Let me explain using the same interview candidate situation I used two years ago.

“Look, I’ve asked these different sources to send me their best stuff and now I’ll have a way to rank them with my own criteria … because they’re mine now.” It’s like using your own criteria to rank job candidates after asking a few of your industry friends to each send in their five best employees for the job you’re hiring for. You’re not necessarily going to agree with how they rank their own employees but you do trust that they’ve sent you five top notch folks.

Say I’m interviewing people and have 3 candidates each from two referring employers, Hansel and Gretel.

Hansel Gretel
Hansel_1 Gretel_1
Hansel_2 Gretel_2
Hansel_3 Gretel_3

 

In the table above, Hansel and Gretel have already ranked their candidates in order of their preference, but after I’ve got their “best”, I’ll assign my own “interview score” after I talk to them, etc.

candidate interview_score referring_employer
Hansel_1 3 Hansel
Hansel_2 0 Hansel
Hansel_3 1 Hansel
Gretel_1 4 Gretel
Gretel_2 2 Gretel
Gretel_3 0 Gretel

 

In terms of search results, this score could be relevance calculated by in-memory SQLite (as I mentioned in the earlier post), edit distance between the user query versus the title of the item, or whatever. For the purpose of explanation it doesn’t matter how the score is calculated, it only matters that there is a score and that it’s assigned by me, the interviewer, and not by Hansel and Gretel.

With a spreadsheet application, I could simply rank the final candidates by my interview score (descending) as in Sort 1, below.

SORT 1

candidate interview_score referring_employer
Gretel_1 4 Gretel
Hansel_1 3 Hansel
Gretel_2 2 Gretel
Hansel_3 1 Hansel
Hansel_2 0 Hansel
Gretel_3 0 Gretel

 

That can certainly work. I’m the interviewer and I have the final say.

I can also sort by my interview score (descending) AND referring employer (ascending) if I think Gretel is a better employer than Hansel. This puts Gretel_3 above Hansel_2 even though they both have an interview score of “0”.

SORT 2

candidate interview_score referring_employer
Gretel_1 4 Gretel
Hansel_1 3 Hansel
Gretel_2 2 Gretel
Hansel_3 1 Hansel
Gretel_3 0 Gretel
Hansel_2 0 Hansel

 

Both sorts are fine in the interview example, but in terms of search results I wanted to do something similar but while still respecting the original sort order. In other words, I wanted to sort a set of all candidates without overriding Hansel and Gretel’s original sort order. That sort would be as in Sort 3, below.

SORT 3

candidate interview_score referring_employer
Gretel_1 4 Gretel
Hansel_1 3 Hansel
Gretel_2 2 Gretel
Gretel_3 0 Gretel
Hansel_2 0 Hansel
Hansel_3 1 Hansel

 

If I pull Sort 3 apart, then it’s easy to see that the original sort order per set is preserved.

candidate candidate interview_score referring_employer
Gretel_1 4 Gretel
Hansel_1 3 Hansel
Gretel_2 2 Gretel
Gretel_3 0 Gretel
Hansel_2 0 Hansel
Hansel_3 1 Hansel

 

If these were search results, that would allow results to be mixed together while preserving the original sort order returned by the Hansel and Gretel databases. So, instead of a candidate name like “Gretel_1″ that data point would not be a person’s name but rather descriptive metadata (title, description, etc.) about the most relevant item in the Gretel database for a given search.

It took me a long time to figure out an algorithm that could sort two arrays in the manner above. I’ve been thinking about it here and there since I wrote that post two years ago. I came close a couple of months ago but the code was hard to read, over-written, and buggy. It didn’t work because the algorithm didn’t work either.

It wasn’t until last week that I think I got there in terms of a working solution … or at least I’m much closer.

What changed last week was that I was reading about sorting algorithms in Discrete Mathematics And Its Applications (7th Edition). While reading about a “bubble sort” I came up with a much, much simpler solution to my problem. It seems similar to a merge sort but with the stipulation as above where I have 2 sets and need to sort the results while still respecting the original sort order of each set.

The algorithm basically works this way to sort from two ordered sets (we’ll call them X and Y):

  1. create an empty set, Output.
  2. while both the ordered sets X and Y are not empty do the following:
    1. compare the current first item in set Y with the current first item in set X.
      1. if the score of the Y item is greater than or equal to the score of the X item, append the Y item to Output and then remove the Y item from set Y.
      2. otherwise append the X item to Output and remove the X item from set X.
  3. append all remaining items in set Y to Output.
  4. append all remaining items in set X to Output.
  5. return the Output set.

Note that the “equal to” condition in step 2.1.1 favors the second set over the first. In other words, if the “equal to” condition were removed, Sort 3 would place Gretel_3 in last place because Hansel_2 still MUST be ranked higher than Hansel_3 because of Hansel’s ordering, but Gretel_3’s score of “0” is less than Hansel_3’s score of 1.

I’m suspicious that I missed something and that this has a fatal flaw, but for now here’s a Python implementation below that uses the sample table data above to output the results as I wanted in Sort 3.

ps: until I get embarrassed and learn this algorithm already exists and has a name, I’ll call this “duck sort” because the interview analogy always reminds me of this classic Tracey Ullman Show skit with Dan Castellaneta, the voice of Homer Simpson.

Part 2 of the clip is here: http://youtu.be/xsTep82EGsw.

Python function:

def duck_sort(x,y):
  output = []
  while len(y) > 0 and len(x) > 0:
    first_x = x[0]
    first_y = y[0]
    if first_y[1] >= first_x[1]:
      output.append(first_y)
      y.remove(first_y)
    else:
      output.append(first_x)
      x.remove(first_x)
  output = output + y
  output = output + x
  return output

using the function in the IDLE Python interpreter:

>>> Hansel = [("Hansel_1", 3), ("Hansel_2", 0), ("Hansel_3", 1)]
>>> Gretel = [("Gretel_1", 4), ("Gretel_2", 2), ("Gretel_3", 0)]

>>> # to preserve lists Hansel and Gretel, do:
>>> # results = duck_sort(list(Hansel), list(Gretel))

>>> results = duck_sort(Hansel, Gretel)
>>> for result in results: print result

('Gretel_1', 4)
('Hansel_1', 3)
('Gretel_2', 2)
('Gretel_3', 0)
('Hansel_2', 0)
('Hansel_3', 1)

Update: Clearly I meant the title of this post to have the phrase “federated search” instead of “federerated search”, but it must have been a Freudian slip. After all, Roger Federer did just help the Swiss win the Davis Cup!

--------------

Related Content:

Written by nitin

November 25th, 2014 at 11:45 am

Posted in scripts,technophilia

Tagged with , ,

using the Summon API with a simple PHP script

leave a comment

A couple of months ago, I posted this code that lets one talk to Serial Solution's Summon 2.0 API with a Python script. That code was a modification of something I found online for using an older version of the API.

I'd also mentioned that I'd post a PHP version when I had one. It's below.

Like the Python one, there's no character escaping/URL-encoding stuff for the query that gets passed to it. I should also mention that the function that calls the API, "summon_tools__request()", needs a function to make a cURL request, so I included that, too. Unlike the Python script, the API credentials are not passed to the function, ya' know 'cause those are static and all.

Once you set your API credentials, usage would simply look like this:

$summon_foo = summon_tools__request("kitten+videos");
print_r($summon_foo);

After you've got your XML or JSON request, it needs to be parsed as needed, of course.

This code is part of a goodbye project that I'm trying to get done for work with just a week left before my last day. Anyway, that's why the functions have silly names – they're part of  bigger project.

Anyway, given how connecting to the API in PHP with a simpler script than the official libraries seems to be something that a few people have been wanting, I might package this into a more complete, stand-alone library down the road.

If someone wants me to do that, please leave a comment below.

function url_tools__request($url, $timeout=10, $headers=array()) {
  /* Returns results of calling a given $url with a $timeout and optional $headers. */
  
  // make cURL request; return results.
  $ch = curl_init();
  curl_setopt($ch, CURLOPT_URL, $url);
  curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
  curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); //suppress output.
  curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
  $ch_exec = curl_exec($ch);
  curl_close($ch);
  return $ch_exec;
}

function summon_tools__request($query, $offset=0, $limit=10, $sort=False, $doctype="xml") {
  /* Returns response in $doctype format (xml|json) from Summon 2.0 API for a $query.
  
    - Results start at $offset for a total of $limit results.
    - Results are sorted by relevance ($sort = False) or date-descending ($sort = True).
    - Code based on Python code here: https://gist.github.com/lawlesst/1070641
    - See also: http://blog.humaneguitarist.org/2014/09/04/getting-started-with-the-summon-api-and-python/
  */
  
  // set API credentials.
  include("summon_api_credentials.php"); //import credentials from external file.
  $api_id = $SUMMON__api_id;
  $api_key = $SUMMON__api_key;
    
  // set API host and path.
  $host = "api.summon.serialssolutions.com";
  $path = "/2.0.0/search";
  
  // create query string.
  $query = "s.q=" . $query . "&s.pn=$offset&s.ps=$limit&s.ho=true";
  
  // set sort to date-descending if needed.
  if ($sort != False) {
    $query = $query . "&s.sort=PublicationDate:desc";
  }
  
  // sort and encode $query.
  $query_sorted = explode("&", $query);
  asort($query_sorted); 
  $query_sorted = implode("&", $query_sorted);
  $query_encoded = urldecode($query_sorted);
  
  // create request headers.
  $accept = "application/$doctype";
  $date = gmstrftime("%a, %d %b %Y %H:%M:%S GMT", time());
  $id_string = implode("\n", array($accept, $date, $host, $path, $query_encoded, ""));
  $digest = base64_encode(hash_hmac("sha1", utf8_encode($id_string), $api_key, True));
  $authorization = "Summon " . $api_id . ";" . $digest;
  $headers = array("Host:$host", "Accept:$accept", "x-summon-date:$date", "Authorization:$authorization");
  
  // call API; return response.
  $url = "http://$host$path?$query";
  $response = url_tools__request($url, $timeout=10, $headers=$headers);
  return $response;
}
--------------

Related Content:

Written by nitin

November 16th, 2014 at 12:25 pm

Posted in information retrieval

Tagged with

using tennis racket grip tape on dumbbell handles

leave a comment

This is a quick post just on something I find really useful.

I workout at home with dumbbells. Being a guitarist, I have to focus on finding exercises that I feel won't overly stress my wrists, for example.

That's to say while I do it for overall health and strength, I have to defer to the physical demands of the guitar. It's one reason I stopped playing tennis – it just taxed my forearms too much and I had trouble practicing guitar when my arms were so worn out.

But there's one thing from tennis that I use to this day: grip tape.

I really don't like wearing gloves while lifting weights. But without them, the handles are really uncomfortable and produce calluses.

A good solution for me, that I used to use and have now gone back to, is to just use grip tape on the handles. The "tackiness" of the grip tape also helps me get a good grip on the weights. Plus, I can always buy a different color of tape when they need replacing and that can help keep things a little fun.

For now, I've got blue tape (pic below).

tennis grip tape on dumbbells

Anyway, it's a lovely Saturday and I should be outside for a while …

--------------

Related Content:

Written by nitin

September 20th, 2014 at 9:59 am

getting started with the Summon API and Python

leave a comment

Why is it I always think clearest when I'm home sick?

That's a post for another time (workplace, structure without structure, working without having showered, etc.) …

But for now, I'm working on something at work that requires we connect to the ProQuest Summon API.

Now, the API documentation is far better than I've seen from some other vendors and they even have some code libraries but I still think that it's still far too common for people who write code and share it to kind of think that's sufficient.

I don't think it is. Because I'm lazy … in a good way, no doubt.

devil

I tend to move on when I don't see example uses of the code because I'm not sure it's really saving me time in the end … and isn't that the ultimate point of code libraries?

Anyway, I need a PHP library to connect to Summon but Googled for a Python one, thinking that if I liked it and it was easy to grasp, I could just translate it to PHP.

Luckily, I found one here: https://gist.github.com/lawlesst/1070641.

I tweaked it to my tastes and changed the Host path to be for version 2.0 of the Summon API.

Aside from renaming and rearranging some things, I added a few parameters and changed the function to run a search from start to finish. I need to test it more and think about a few more things (timeouts, etc.) but for now, I'm seeing results back so things are progressing.

The parameters I added are the API ID and Key themselves as well as offset and limit options. The "doctype" parameter let's one choose "xml" (default) or "json".

Initially, I had a "method" parameter that could be set to "search" (default") or "image" but I am getting 404's from the Summon Cover Image API, so I dropped that for now.

Here's the code below, if anyone's interested.
I'll post a PHP version when that's done.

#####
def search_summon_v2(query, api_id, api_key, offset=0, limit=10, sort=False, doctype="xml"):

  """ Returns results from Summon API.
      ... total rip-off of code found at https://gist.github.com/lawlesst/1070641.
      :-]
  """
 
  # import modules.
  import base64, hashlib, hmac, urllib2
  from datetime import datetime
  from urllib import unquote_plus
 
  # set API host and path.
  host = "api.summon.serialssolutions.com"
  path = "/2.0.0/search"
 
  # sort and encode $query.
  ##offset = offset + 1 #Summon starts at "1" not "0". # Actually, I think I was wrong about this so I commented-out the line.
  query = "s.q=" + query + ("&s.pn=%d&s.ps=%d") %(offset, limit)
  if sort != False:
    query = query + "&s.sort=PublicationDate:desc"
  query_sorted = "&".join(sorted(query.split("&")))
  query_encoded = unquote_plus(query_sorted)
 
  # create request headers.
  if doctype not in ["xml", "json"]:
    doctype = "xml"
  accept = "application/%s" %doctype
  date = datetime.utcnow().strftime("%a, %d %b %Y %H:%M:%S GMT")
  id_string = "\n".join([accept, date, host, path, query_encoded, ""])
  digest = base64.encodestring(hmac.new(api_key, unicode(id_string), hashlib.sha1).digest())
  authorization = "Summon " + api_id + ";" + digest
  headers = {"Accept":accept, "x-summon-date":date, "Host":host, "Authorization":authorization}
 
  # send search to API; return results.
  url = "http://%s%s?%s" % (host, path, query)
  request = urllib2.Request(url=url, headers=headers)
  results = urllib2.urlopen(request).read()
  return results

#########################
##### EXAMPLE USAGE #####
#########################

# get API ID and Key strings from external file (no peeking!).
import summon_credentials as smn

# send sample query and print results.
query = "kittens"
##query = "kittens&s.dym=true" #example of passing more Summon parameters via the query string.
results = search_summon_v2(query, smn.api_id, smn.api_key, limit=1, doctype="json")
print results

Update, later in the day: I just noticed that line 33 which originally read as this:

authorization = ("Summon " + api_id + ";" + digest).replace("\n", "")

was overkill because the line breaks already got Base64 encoded, so there should be none to replace.

--------------

Related Content:

Written by nitin

September 4th, 2014 at 12:51 pm

Posted in information retrieval,scripts,XML

Tagged with

Cowabunga! Teenage Mutable Default Arguments in Python

5 comments

I was writing a Python function yesterday to which I passed a list as an argument.

After manipulating the list I passed, I returned my desired value.

What was a little surprising to me was that the initial list itself got updated.

For example, consider the following:

>>> def return_new_list(old_list):
      old_list.append("new stuff")
      return old_list

>>> my_list = ["a"]
>>> print return_new_list(my_list)
['a', 'new stuff']
>>> print my_list
['a', 'new stuff']

I would have expected that the list "my_list" would still only have the original item, "a".

Instead, "my_list" itself has been altered per the function "return_new_list()".

So, after being flustered I stumbled onto this solution which uses the built-in "list()" function within the "return_new_list()" function.

>>> def return_new_list(old_list):
      old_list = list(old_list) # this seems to "fix" the "problem".
      old_list.append("new stuff")
      return old_list

>>> my_list = ["a"]
>>> print return_new_list(my_list)
['a', 'new stuff']
>>> print my_list
['a']

Of course, after searching for why this behavior is as it is, I found this page (see: "Mutable Default Arguments") which explained why Python does what it does and also presents a different way of dealing with the issue.

But, here too with the author's example code, it seems to work just fine to use the "list()" function within the function "append_to()".

>>> def append_to(element, to=[]):
      to = list(to) # I'm a new line!
      to.append(element)
      return to

>>> print append_to(12)
[12]
>>> print append_to(42)
[42]

Anyway, just thought I'd share.

I'd love to hear any opinions on why the "solution" I proposed works, isn't a good idea, or if ninja kicks the damn rabbit, etc.

--------------

Related Content:

Written by nitin

August 20th, 2014 at 5:12 pm

Posted in scripts,technophilia

Tagged with , ,

object oriented smoothies … mmm.

leave a comment

I'm at the coffee shop and it's raining like cats and dogs … which is a happy situation considering that it wasn't "supposed" to rain for another three hours or so and I like rainy Sunday mornings especially while reading or writing.

Anyway, I was talking to someone the other day about object oriented programming. Also, at work we're likely to start a project for which I'll be coding most of the backend and I've been asking myself "more OO or more functional?".

Given that I really don't write in OO (neither does anyone on staff) even though I understand the concepts, I decided the best way to decide was really to do some light OO scripting in Python to help me decide.

For the project at work, this little Python experiment – as well as the light readings I've done the last two days – has led me to decide on a more functional style. I'll be able to get the job done faster and test easier. The speed thing is very much an issue since we'll be on a very tight deadline. Moreover, the project's not the time for me to learn new things unless I have to in order to get the job done effectively.

Anyway, the hardest part of this Python experiment was to think of a situation where OO would clearly be the better choice. So I started thinking about changing states of things. That's another reason I think OO is bad for the work project – I just need to do one-time input/output operations; things won't be changing states – at least not in the backend.

As I was thinking, I was thinking about food. Because I was hungry at the time (like I am now).

I eat a lot. And yes, I do exercise and lift weights regularly so my eating is quite intentional. I have two protein smoothies a day and so … I started thinking about my blender as an object with properties.

By attributing state … and providing methods for changing that state, the object remains in control of how the outside world is allowed to use it.

source: What Is an Object? (The Java™ Tutorials > Learning the Java Language > Object-Oriented Programming Concepts. Retrieved July 27, 2014, from docs.oracle.com/javase/tutorial/java/concepts/object.html

My blend is either "on" or "off".

It consumes wattage to run, etc.

And with a digital blender, I can record "usage" and, knowing the wattage used per second, calculate how much the blender has cost me to run both over time and, if I wanted, each individual time. This "usage" can be reset, too. If one has a ballpoint pen, that is.

So "usage" and "cost" are other properties – although as I'm writing I could see how "cost", being based on a variable (cost per watt) and "usage", should perhaps not be a method but rather an external function, especially given how cost per watt is going to change over time and how the concept isn't unique to a blender. But for now, it is watt (pun!) it is.

So, I created a "blender" class which has some simple specification metadata and I created an "appliance" class which "blender" inherits.

The code is below as are the IDLE ouput results of me "using" the blender.

In the IDLE shell, I also created a "toaster" class as that, too, inherits the "appliance" class.

p.s. If you want my smoothie recipe, leave a comment.

p.p.s. If you think my programming sucks, leave a comment.

p.p.p.s: If you think smoothies suck, your comment will not get published.

cheeky

#########################
# smOOthie.py (Object Oriented smoothie).

##### appliance class.
class appliance():

  # establish the state of the appliance.
  def __init__(self):
    self.state = "off"
    self.reset()

  # toggle the power state of the appliance,
  # record the on/off times as "start"/"stop",
  # return the new state of the appliance.
  def toggle(self):

    from time import time
    now = time()

    # if toggled "on", set the "start" time.
    if self.state == "off":
      self.state = "on"
      self._start = now
      
    # if toggled "off", set the "stop" time and record "start"/"stop" times.
    else:
      self.state = "off"
      self._stop = now
      self.usage.append({"start": self._start,
                         "stop": self._stop})
    return

  # return usage cost for appliance since last reset.
  def cost(self):

    total_seconds = 0

    for use in self.usage:
      if len(use) == 2: # make sure there is a "start" and "stop" time.
        subtotal_seconds = use["stop"] - use["start"]
        total_seconds = total_seconds + subtotal_seconds

    total_watts = total_seconds * self.specifications["watts_used_per_second"]
    total_cost_in_cents = total_watts * .012 # cost per watt based on "http://www.eia.gov/electricity/monthly/update/end_use.cfm#tabs_prices-3"
    total_cost_in_cents = round(total_cost_in_cents, 2)
    
    return total_cost_in_cents
 
  # reset usage counter.
  def reset(self):
    self.usage = []

#########################
##### blender class.
class blender(appliance):
  kind = "blender"
  specifications  = {"manufacturer": "generic",
                     "model": "generic",
                     "price": "n/a",
                     "watts_used_per_second": .0834}
                     # "watts_used_per_second" based on "http://www.indoorgenerator.com/0p/Power-Consumption-Table.pdf" for a blender.

               
#########################
##### use the blender appliance - i.e. make a smoothie.
from time import sleep

myBlender = blender()

# setting specifications (especially watts used) for Acme blender.
myBlender.specifications = {"manufacturer": "Acme Corporation",
                            "model": "Illudium Q-36",
                            "price": "$1,000,000.00 (space dollars)",
                            "watts_used_per_second": 1000}
                            # this is a VERY expensive blender to buy AND use!

def useBlender(duration=5):
 
  print "\nMy blender was: " + myBlender.state

  myBlender.toggle()
  print "\nMy blender is now: " + myBlender.state

  print "\n\t... using blender for this many seconds: " + str(duration)
  sleep(duration) # making a smoothie usually takes a little longer ...

  myBlender.toggle()
  print "\nMy blender is now: " + myBlender.state

  print "\nMy blender has been used this many times: " + \
      str(len(myBlender.usage))

  print "\nMy blender has been used during the following times (UNIX):"
  for i in myBlender.usage:
    print "\t", i

  print "\nUsing my blender has cost this (cents): " + \
        str(myBlender.cost())

  print "_" * 25

useBlender()  # blend smoothie.
useBlender(2) # just a quick pulse.

# fin.

And here's the output …

Python 2.7.2 (default, Jun 12 2011, 15:08:59) [MSC v.1500 32 bit (Intel)] on win32
Type "copyright", "credits" or "license()" for more information.
>>> ================================ RESTART ================================
>>>

My blender was: off

My blender is now: on

  ... using blender for this many seconds: 5

My blender is now: off

My blender has been used this many times: 1

My blender has been used during the following times (UNIX):
  {'start': 1406470729.349, 'stop': 1406470734.357}

Using my blender has cost this (cents): 60.1
_________________________

My blender was: off

My blender is now: on

  ... using blender for this many seconds: 2

My blender is now: off

My blender has been used this many times: 2

My blender has been used during the following times (UNIX):
  {'start': 1406470729.349, 'stop': 1406470734.357}
  {'start': 1406470734.388, 'stop': 1406470736.416}

Using my blender has cost this (cents): 84.43
_________________________
>>> class toaster(appliance):
  kind = "toaster"
  specifications = {"manufacturer": "?",
                    "model": "?",
                    "price": "?",
                    "watts_used_per_second": .4167}

 
>>> myToaster = toaster()
>>> myToaster.toggle(); sleep(10), myToaster.toggle()
(None, None)
>>> myToaster.cost()
0.05
>>> myToaster.state
'off'
>>> myToaster.toggle(); sleep(10), myToaster.toggle()
(None, None)
>>> myToaster.cost()
0.1

    Written by nitin

    July 27th, 2014 at 11:19 am

    three by Rafa and the greatest quote ever

    leave a comment

    I've recently finished reading three novels by Rafael Sabatini.

    They happen to be the basis for three of my favorite films as well. That, of course, is why I read them.

    Starting with Captain Blood – Colonel, darling – I moved on to The Sea-Hawk and Scaramouche – the same order in which the 1935, 1940, and 1952 films were respectively made but not in the order of publication.

    Anyone who's read the novels and seen the films knows that the Errol Flynn iteration of The Sea Hawk has nothing to do with the book. Still, it's a great film with a great duel. Better – if memory serves – than the duel in Caption Blood though perhaps not as fine as the duel in Scaramouche with Stewart Granger. That duel – again, if memory serves – is argued by more than one, if not many, to be the finest in cinematic history.

    The justly famous eight-minute climactic duel in the theatre between Granger and Mel Ferrer (as Noel, the Marquis de Maynes) required eight weeks of training in which both stars had to memorize eighty-seven individual sword passes and perform twenty-eight stunts.

    source: Scaramouche (1952) – Articles – TCM.com. Retrieved June 28, 2014, from www.tcm.com/tcmdb/title/2053/Scaramouche/articles.html

    Naturally, both Flynn films are all the more majestic thanks to one Erich Wolfang Korngold.

    Not since I read Lloyd Alexander's Chronicles of Prydain has reading been so laden with a sense of adventure. And while the Prydain books have depth that I could only glimpse as a youth, Sabatini's work has truth and wisdom. This, despite the fact that the protagonists in this unofficial trilogy appear on the outset to be men who are lived by life, simply making the most of the unfortunate hands they've been dealt, or as Flynn's Blood muses, "Desperate men, we go to seek a desperate fortune."

    As epic as those words are, they don't match the words apparently spoken by Flynn's Flynn …

    "I intend to live the first half of my life. I don't care about the rest." – Errol Flynn.

    --------------

    Related Content:

    Written by nitin

    June 28th, 2014 at 12:34 pm

    goodbye to the Guitar Foundation of America

    leave a comment

    My GFA membership has expired and I won't be renewing.

    Despite all the "great" benefits membership entails (see below), the Soundboard has been in a steady state of decline since they long ago stopped accepting letters to the editor. Its latest incarnation – embarrassing content aside – is less a journal and more a website printed on glossy paper. As a member I'd liked to have known what the printing costs are for doing that as opposed to before – maybe it's a better deal in terms of print production, but it's just another way in which I felt, more and more, like a customer than a real member.

    This is a reminder that your Guitar Foundation of America membership has expired.  We hope you will take a moment to renew your membership for another year to ensure that you will continue to enjoy all of the great GFA benefits including Soundboard magazine, discounts at retailers such as Mel Bay Publications, Editions Doberman-Yppan, Guitar Solo Publications, Guitar Salon International, Colorado Case Company, a discount on Acoustic Guitar magazine subscription, and up to a 60% discount on instrument insurance through Clarion & Associates, Inc.

    Members are involved in their organizations growth – or at least have the opportunity to do so. The Soundboard doesn't lend itself to discussion, the website seems to have virtually no discussions, the Soundboard Scholar was supposed to be out a year ago and yet there appears to be nothing going on or at least nothing being communicated on the website, and whatever happened to the old forums that were on the old Drupal site? As a member I should be a co-owner of that discussion content. I don't really see that the organization has any digital strategy let alone a print one (well, at least not a good one in my opinion).

    It's so easy these days to do online surveys, but as a member I don't recall ever being asked my opinion on anything. Curiously though, I was asked to rewrite this post to be less "negative". I didn't. That, boys and girls, is what we call a "red flag".

    Anyway …

    I could go on but there's no point.

    The music will live and that's what matters to me. The GFA no longer does.

    a postscript: I wrote this post on April 6, 2014 and only published it today, April 29. The reason being is that after reading my words I thought it only fair to first inquire with the GFA about the status of Soundboard Scholar. So I sent an email with the subject "Soundboard Scholar" (copied below) on April 6th. It's been over three weeks with no reply and the webpage, as of this date, still says "Summer 2013" as the launch date.

    Perhaps the email address isn't even being checked any more. So like I said before … I could go on but there's no point.

    nitin arora 	 Sun, Apr 6, 2014 at 10:29 AM
    To: peerreview@guitarfoundation.org
    
    Hello,
    
    It's been a year since this was supposed to first come out.
    
    Is there any progress? Can something at least be posted here:
    
    http://www.guitarfoundation.org/?page=SBScholarly
    
    for the sake of some transparency?
    
    thanks,
    
    -- 
    Nitin Arora
    nitaro74 (at) gmail (dot) com
    "Hope always, expect never."
    
    --------------

    Related Content:

    Written by nitin

    April 29th, 2014 at 5:00 pm

    Posted in music,opinion

    Tagged with , , ,

    Four fur Marv: some new old music for solo guitar

    leave a comment

    This is a just a short post to provide a link to some new compositions for solo guitar I completed this week – after starting in September 2012.

    While I don't expect anyone but myself to take the time to learn these properly, I do know a few folks that I think would at least give them a read through.

    If I had to provide some overview of them it would be that they are written in a 19th century/Romantic style and hopefully provide enough variance in texture to provide interest from piece to piece. While these are a set, each piece is certainly independent of the other although the cadential endings of the first and last piece share some deliberate similarities – a sort of tying up of loose ends.

    I might, at some point, post a brief analysis of some of the harmonic structure of the last piece, which at times provided me with quite a headache, but ultimately I let the music go where it wanted to. I simply needed to understand how it was doing so and had, in particular, to know this is order to try and provide coherent spellings of accidentals/enharmonics, etc.

    Below are links to the PDF of the music and the textual "liner notes" as well as a ZIP archive with the PDF, liner notes, and source LilyPond files, etc.

    Oh, and by the way, the work is dedicated to a friend of mine. He happens to be a cat. If kitty-inspiration is seemingly good enough for Domenico Scarlatti, it's surely good enough for me.

    PDF: http://humaneguitarist.org/four_fur_marv.pdf

    ZIP: http://humaneguitarist.org/four_fur_marv.zip

    --------------

    Related Content:

    Written by nitin

    March 29th, 2014 at 11:20 am

    Posted in music,news

    Tagged with , , , ,