2012-12-05

RGB and HSV Colour Selector Demo in Python

The use of red-green-blue (RGB) tuples along with hue-saturation-value (HSV) tuples is quite common in many software, such as in the colour selection feature of GIMP. Alvy Ray Smith describes the  conversion between the two colour spaces in an article Color Gamut Transform Pairs” in the August 1978 issue of SIGGRAPH 78 Conference Proceedings.

Based on the algorithms in Smith's article, I've implemented a Python colour selector demo (downloadable at http://downloads.mikequentel.com/rgbhsv.py.tar.gz) to show how a colour can be set using either RGB or HSV settings.  The code listing of the demo shows even the same variable naming conventions as the pseudocode in Smith's article, to make it easier to compare to the algorithm.

Here is a screenshot of the demo in action:


The demo uses a Tkinter GUI and the standard, out-of-the box library functionality that comes with Python 2.7. The colour swatch (rectangle) is simply the background of a Canvas object. This is meant to be a very simple, easy-to-understand demo of how to convert between RGB and HSV. The code is not meant to be an optimised example of how to generate GUI widgets; no special design patterns that generalise the creation of widgets are used.

As the demo has about 300 lines of code, I will only show here snippets of the functions that convert between RGB and HSV.

def rgb2hsv(R, G, B):
  print "Start of rgb2hsv()"
 
  if R == G == B == 0.0:
    return {'h':0, 's':0, 'v':0}
 
  # DETERMINES MAXIMUM RGB VALUE "V" WHICH IS A MEASURE OF THE DEPARTURE
  # FROM BLACK.
  V = max(R, G, B)
 
  # DETERMINES MININUM RGB VALUE "X".
  X = min(R, G, B)
 
  # DETERMINES SATURATION "S".
  S = (V - X)/V
 
  # DETERMINES ADJUSTED RED, GREEN, BLUE VALUES "r", "g", "b".
  r = (V - R)/(V - X)
  g = (V - G)/(V - X)
  b = (V - B)/(V - X)
 
  # DETERMINES HUE "H"
  H = 0
  if R == V:
    H = G == X and 5 + b or 1 - g
  if G == V:
    H = B == X and 1 + r or 3 -b
  else:
    H = R == X and 3 + g or 5 - r
  H /= 6.0
 
  hue = toDegrees(H)
  saturation = toRoundedPercentage(S)
  value = toRoundedPercentage(V)

  return {'h':hue, 's':saturation, 'v':value}

def hsv2rgb(H, S, V):
  print "Start of hsv2rgb()"
 
  if H == S == V == 0.0:
    return {'r':0, 'g':0, 'b':0}
 
  H *= 6
  I = math.floor(H)
  F = H - I
  M = V * (1 - S)
  N = V * (1 - S * F)
  K = V * (1 - S * (1 - F))
 
  R = G = B = 0.0
  if I == 0:
    R = V
    G = K
    B = M
  elif I == 1:
    R = N
    G = V
    B = M
  elif I == 2:
    R = M
    G = V
    B = K
  elif I == 3:
    R = M
    G = N
    B = V
  elif I == 4:
    R = K
    G = M
    B = V
  else:
    R = V
    G = M
    B = N

  red = to8bit(R)
  green = to8bit(G)
  blue = to8bit(B)
 
  return {'r':red, 'g':green, 'b':blue}


The functions closely match the algorithm pseudocodes in Smith's article, and even have the same variable names.

This demo was a good learning experience in understanding the algorithms that transform between the colour models of RGB and HSV.

2012-10-06

Example of Trigonometric Functions in Matplotlib

The matplotlib library offers excellent functionality for quick and simple graphing capabilities in python.

Excellent tutorials exist about how to use matplotlib for common graphing tasks. The matplotlib documentation of scipy by Mike Müller and the  Matplotlib Tutorial by Nicolas P. Rougier offer excellent code snippets that illustrate simple graphing in matplotlib.

I especially like Rougier's "Devil is in the Details" example, which I've modelled the following example on, to show the graphs of sine, cosecant, cosine, secant, tangent, and cotangent.

Here is my spin on this, code and results below.

#!/usr/bin/python
from pylab import *

# rendering area
figure(figsize=(8,5), dpi=80)

# display area to use; can be modified to accomodate more graphs
subplot(111)

# range
x = np.linspace(0, (2 * np.pi), 256,endpoint=True)

# formulas to graph
sine = np.sin(x)
cosine = np.cos(x)
tangent = np.tan(x)
cotangent = 1/np.tan(x)
cosecant = 1/np.sin(x)
secant = 1/np.cos(x)

# line styles and labels
plot(x, sine, color="red", linewidth=2.5, linestyle="-", label="sin")
plot(x, cosine, color="blue", linewidth=2.5, linestyle="-", label="cos")
plot(x, tangent, color="orange", linewidth=2.5, linestyle="-", label="tan")
plot(x, cotangent, color="purple", linewidth=2.5, linestyle="-", label="cot")
plot(x, cosecant, color="green", linewidth=2.5, linestyle="-", label="csc")
plot(x, secant, color="yellow", linewidth=2.5, linestyle="-", label="sec")

# tick spines
ax = gca()
ax.spines['right'].set_color('none')
ax.spines['top'].set_color('none')
ax.xaxis.set_ticks_position('bottom')
ax.spines['bottom'].set_position(('data',0))
ax.yaxis.set_ticks_position('left')
ax.spines['left'].set_position(('data',0))

# x tick limits and labels
xlim(x.min()*1.1, x.max()*1.1)
xticks([(-2 * np.pi), (-3 * np.pi/2), -np.pi, -np.pi/2, 0, np.pi/2, np.pi, (3 * np.pi/2), (2 * np.pi)], [r'$-2\pi$', r'$-3/2\pi$', r'$-\pi$', r'$-\pi/2$', r'$0$', r'$+\pi/2$', r'$+\pi$', r'$3/2\pi$', r'$2\pi$'])

# y tick limits and labels
ylim(-4, 4)
yticks([-4, -3, -2, -1, +1, +2, +3, +4], [r'$-4$', r'$-3$', r'$-2$', r'$-1$', r'$+1$', r'$+2$', r'$+3$', r'$+4$'])

# legend
legend(loc='upper left')

for label in ax.get_xticklabels() + ax.get_yticklabels():
  label.set_fontsize(16)
  label.set_bbox(dict(facecolor='white', edgecolor='None', alpha=0.65 ))

# display
show()




2012-09-14

How to Use Python to Upload a Document to Google Docs or Google Drive


I've been using Google Docs for several years, and recently participated in a kind of unexpected migration to Google Drive. I like the overall ease of use of the "Docs" part of Google Drive, and will hereforwards refer to this simply as "Google Docs".

I have been wanting to know for some time how to go about uploading a document to Google Docs via some kind of API. The Google Documents List API provides this functionality, and there are some useful examples on how to employ the Python version to upload files, as shown by Google here, and as seen in various postings on sites such as Stack Overflow, such as an example seen here.

Here is my version of how to upload a file to Google Docs, based on examples I mentioned above. In order to use this script, Google Documents List API version 3.0 is required, but this can be downloaded as the Google APIs Client Library for Python.

#!/usr/bin/python

import sys
import argparse
import os
import gdata.data
import gdata.docs.client
import gdata.docs.data
import gdata.docs.service
import gdata.sample_util

class SampleConfig(object):
  APP_NAME = 'GDataDocumentsListAPISample-v1.0'
  DEBUG = False

def create_client():
  client = gdata.docs.client.DocsClient(source=SampleConfig.APP_NAME)
  try:
    gdata.sample_util.authorize_client(
       client,
       1,
       service=client.auth_service,
       source=client.source,
       scopes=client.auth_scopes
    )
  except gdata.client.BadAuthentication:
    exit('Invalid user credentials given.')
  except gdata.client.Error:
    exit('Login Error')
  return client

def upload_file(path, title, type, do_convert):
  client = create_client()
  doc = gdata.docs.data.Resource(type=type, title=title)
  media = gdata.data.MediaSource()
  media.SetFileHandle(path, type)
  create_uri = gdata.docs.client.RESOURCE_UPLOAD_URI + '?convert=' + do_convert
  doc = client.CreateResource(doc, create_uri=create_uri, media=media)
  print 'Uploaded:', doc.title.text, doc.resource_id.text

def main():
  parser = argparse.ArgumentParser(description='Upload file to Google Drive (previously known as \'Google Docs\').')
  parser.add_argument('file', help='file to upload.')
  parser.add_argument('title', help='title for the uploaded document.')
  parser.add_argument('type', nargs='?', default='text/plain', help='type of file to upload, default is text/plain.')
  parser.add_argument('do_convert', nargs='?', default='true', help='true or false: convert the document to Google Docs format? Default is true')
  args = parser.parse_args()
  path = args.file
  title = args.title
  type = args.type
  do_convert = args.do_convert
  upload_file(path, title, type, do_convert)
  os._exit(0)

# Specifies name of main function.
if __name__ == "__main__":
  sys.exit(main())

2012-06-26

Using Rule of Sarrus, Cramer's Rule, and Python to Solve a System of Three Linear Equations

Lately I've been studying how to solve a system of linear equations; in particular, three linear equations. Not satisfied with the "Elimination of Variables" method for solving this sort of problem, I researched other ways of solving for x, y, and z values. I found that the Rule of Sarrus and Cramer's Rule are ideal for my purposes, and put these concepts into a Python script that would illustrate the rules.

I must mention that the code below is a fresh prototype, and lacks error-trapping at this time (for example, nothing traps for division by zero). Reason for this rough implementation is to keep the code readable as an example of using the rules of Sarrus and Cramer, rather than an actual implementation that would be used in a real system.
# System of three linear equations
# ax + by + cz = j
# dx + ey + fz = k
# gx + hy + iz = l

# System of three linear equations in matrix notation
#  -         -   - -       - -
# | a   b   c | | x |     | j |
# |           | |   |     |   |
# | d   e   f | | y |  =  | k |
# |           | |   |     |   |
# | g   h   i | | z |     | l |
#  -         -   - -       - -

# Matrix of Coefficients
# a b c
# d e f
# g h i

# Matrix of Variables
# x
# y
# z

# Matrix of Resulting Values
# j
# k
# l

# Rule of Sarrus
# a b c|a b
# d e f|d e
# g h i|g h

# Rule of Sarrus Index Values
# 0 1 2|0 1
# 3 4 5|3 4
# 6 7 8|6 7

# Determinant
# det(M) = aei + bfg + cdh - gec - hfa - idb

# Cramer's Rule
# | j b c |   | a j c |   | a b j |
# | k e f |   | d k f |   | d e k |
# | l h i |   | g l i |   | g h l |
# ---------,  ---------,  ---------
# | a b c |   | a b c |   | a b c |
# | d e f |   | d e f |   | d e f | 
# | g h i |   | g h i |   | g h i |
import sys

def main():
    
    inputs_dict = {'a':int(raw_input("a:")), 'b':int(raw_input("b:")), 'c':int(raw_input("c:")), 'j':int(raw_input("j:")), 
                   'd':int(raw_input("d:")), 'e':int(raw_input("e:")), 'f':int(raw_input("f:")), 'k':int(raw_input("k:")), 
                   'g':int(raw_input("g:")), 'h':int(raw_input("h:")), 'i':int(raw_input("i:")), 'l':int(raw_input("l:"))}

    coeffs_matrix = {'a':inputs_dict['a'], 'b':inputs_dict['b'], 'c':inputs_dict['c'], 
                     'd':inputs_dict['d'], 'e':inputs_dict['e'], 'f':inputs_dict['f'], 
                     'g':inputs_dict['g'], 'h':inputs_dict['h'], 'i':inputs_dict['i']}
    x_numerator_matrix = {'j':inputs_dict['j'], 'b':inputs_dict['b'], 'c':inputs_dict['c'], 
                          'k':inputs_dict['k'], 'e':inputs_dict['e'], 'f':inputs_dict['f'], 
                          'l':inputs_dict['l'], 'h':inputs_dict['h'], 'i':inputs_dict['i']}
    y_numerator_matrix = {'a':inputs_dict['a'], 'j':inputs_dict['j'], 'c':inputs_dict['c'], 
                          'd':inputs_dict['d'], 'k':inputs_dict['k'], 'f':inputs_dict['f'], 
                          'g':inputs_dict['g'], 'l':inputs_dict['l'], 'i':inputs_dict['i']}
    z_numerator_matrix = {'a':inputs_dict['a'], 'b':inputs_dict['b'], 'j':inputs_dict['j'], 
                          'd':inputs_dict['d'], 'e':inputs_dict['e'], 'k':inputs_dict['k'], 
                          'g':inputs_dict['g'], 'h':inputs_dict['h'], 'l':inputs_dict['l']}
    
    # Rule of Sarrus for det_coeffs_matrix
    # a b c|a b
    # d e f|d e
    # g h i|g h
    #
    det_coeffs_matrix = (coeffs_matrix['a'] * coeffs_matrix['e'] * coeffs_matrix['i'] +
                         coeffs_matrix['b'] * coeffs_matrix['f'] * coeffs_matrix['g'] +
                         coeffs_matrix['c'] * coeffs_matrix['d'] * coeffs_matrix['h'] -
                         coeffs_matrix['g'] * coeffs_matrix['e'] * coeffs_matrix['c'] -
                         coeffs_matrix['h'] * coeffs_matrix['f'] * coeffs_matrix['a'] -
                         coeffs_matrix['i'] * coeffs_matrix['d'] * coeffs_matrix['b'])
    
    # Rule of Sarrus for det_x_numerator_matrix
    # j b c|j b
    # k e f|k e
    # l h i|l h
    #
    det_x_numerator_matrix = (x_numerator_matrix['j'] * x_numerator_matrix['e'] * x_numerator_matrix['i'] +
                              x_numerator_matrix['b'] * x_numerator_matrix['f'] * x_numerator_matrix['l'] + 
                              x_numerator_matrix['c'] * x_numerator_matrix['k'] * x_numerator_matrix['h'] -
                              x_numerator_matrix['l'] * x_numerator_matrix['e'] * x_numerator_matrix['c'] -
                              x_numerator_matrix['h'] * x_numerator_matrix['f'] * x_numerator_matrix['j'] -
                              x_numerator_matrix['i'] * x_numerator_matrix['k'] * x_numerator_matrix['b'] )
    
    # Rule of Sarrus for det_y_numerator_matrix
    # a j c|a j
    # d k f|d k
    # g l i|g l
    #
    det_y_numerator_matrix = (y_numerator_matrix['a'] * y_numerator_matrix['k'] * y_numerator_matrix['i'] +
                              y_numerator_matrix['j'] * y_numerator_matrix['f'] * y_numerator_matrix['g'] +
                              y_numerator_matrix['c'] * y_numerator_matrix['d'] * y_numerator_matrix['l'] -
                              y_numerator_matrix['g'] * y_numerator_matrix['k'] * y_numerator_matrix['c'] -
                              y_numerator_matrix['l'] * y_numerator_matrix['f'] * y_numerator_matrix['a'] -
                              y_numerator_matrix['i'] * y_numerator_matrix['d'] * y_numerator_matrix['j'])
    
    # Rule of Sarrus for det_z_numerator_matrix
    # a b j|a b
    # d e k|d e
    # g h l|g h
    #
    det_z_numerator_matrix = (z_numerator_matrix['a'] * z_numerator_matrix['e'] * z_numerator_matrix['l'] +
                              z_numerator_matrix['b'] * z_numerator_matrix['k'] * z_numerator_matrix['g'] +
                              z_numerator_matrix['j'] * z_numerator_matrix['d'] * z_numerator_matrix['h'] -
                              z_numerator_matrix['g'] * z_numerator_matrix['e'] * z_numerator_matrix['j'] -
                              z_numerator_matrix['h'] * z_numerator_matrix['k'] * z_numerator_matrix['a'] -
                              z_numerator_matrix['l'] * z_numerator_matrix['d'] * z_numerator_matrix['b'])
    
    x = det_x_numerator_matrix/det_coeffs_matrix
    y = det_y_numerator_matrix/det_coeffs_matrix
    z = det_z_numerator_matrix/det_coeffs_matrix

    print
    print "results: "
    print "x = " + str(x)
    print "y = " + str(y)
    print "z = " + str(z)
    
    
# Specifies name of main function.
if __name__ == "__main__":
    sys.exit(main())

2010-11-14

How to Create a Text File List of RGB Values in C

Here is a very simple C program for generating RGB values listed in a text file:


#include <stdio.h>

int main() {

  FILE *fp;
  fp = fopen("true_colour.txt", "w");

  int r = 255;
  int g = 255;
  int b = 255;

  for (r = 255; r >= 0; r--) {
    for (g = 255; g >= 0; g--) {
      for (b = 255; b >= 0; b--) {
        fprintf(fp, "%d", r);
        fprintf(fp, ",");
        fprintf(fp, "%d", g);
        fprintf(fp, ",");
        fprintf(fp, "%d", b);
        fprintf(fp, "\n");
      }
    }
  }

  fclose(fp);
  return 0;

}

2010-09-29

Moving Sharepoint (MOSS) from One Server to Another

Moving Sharepoint (MOSS) from One Server to Another

Lots of information exists on the internet concerning how to backup, restore, and move Microsoft Office Sharepoint Server (MOSS). Here, I will refer to this simply as "Sharepoint". Many developers (including myself) have wondered, "what is the easiest way to fully backup and restore, and even in the process, move, Sharepoint?"...so here an easy way to do a full backup of one Sharepoint server, then restore to another Sharepoint server...

Sharepoint backup from original (source) server:

C:\Program Files\Common Files\Microsoft Shared\web server extensions\12\BIN>stsadm -o backup -url http://mysourceserver:80/ -filename C:\sharepoint_backups\myoriginalsharepointinstance.bak


Sharepoint restore to another (destination) server:

C:\Program Files\Common Files\Microsoft Shared\web server extensions\12\BIN>stsadm -o restore -url http://mydestinationserver/ -overwrite -filename C:\sharepoint_backups\myoriginalsharepointinstance.bak

2010-09-11

Using Ant to Automate Version Control Operations and Software Metrics

Using Ant to Automate Version Control Operations and Software Metrics


Like many developers, I use Ant to build and deploy software. Through the years, I have grown an inordinate fondness for Ant, and I have enjoyed finding ways to automate all sorts of processes in the software development life cycle.

Here, I would like to show some examples of using Ant to interact with a version control system, and to also collect software metrics.

For version control, many of us use Subversion to maintain our software repositories, and essentially, manage our intellectual property. One of the challenges in concurrently developing a system, on a team, is keeping in sync with the latest (or some particular) revision of the software. Ant can help in this endeavour.

Here, I show how Ant can be used to do an svn update on the local copy of code. I use this Ant target to ensure that I have the latest updates to the code I am working with; this target acts as a kind of continuous integration tool on Agile projects. So, introducing the Ant svnupdate target...

In the build.properties, add


# SVN Client Home -- where svn client can be found.
# eg: svnclient.home=C:/cygwin/bin/svn.exe
# or
# svnclient.home=/usr/bin/svn
svnclient.home=C:/cygwin/bin/svn.exe


Then, in the build.xml, include


<!-- Svnupdate Target -->
<target name="svnupdate" description="Updates code source to HEAD.">
<exec executable="${svnclient.home}">
<arg line='"update"'/>
</exec>
</target>


To do an svn update on your local copy, then simply use the svnupdate target, like this:


ant svnupdate


I typically combine it with the whole build, so that it is called just before the other targets.

Also, you can use Ant to create a README file based on information in the repository. To do this, add this target to the build.xml file:


<!-- Svninfo Target -->
<target name="svninfo"
description="Gets Subversion data about this local copy.">
<exec executable="${svnclient.home}" output="README">
<arg line='"info"'/>
</exec>
</target>


This would be run as:


ant svninfo


It outputs a README file that can also, using Ant, be inserted into the final deployment (eg: a WAR file or JAR file).

Ant can also call software that performs metrics. One such software, StatSVN, does an excellent job of generating statistics and charts representing the metrics of a build. Here is an example of using Ant to call StatSVN...

In build.properties:


# StatSVN parameters.
# See http://www.statsvn.org/
lib.statsvn=statsvn.jar
svn.log=svn.log
statsvn.outputdir=statsvn


In build.xml:


<!-- Statsvn Target -->
<target name="statsvn" description="Runs statsvn.jar on the local copy.">
<mkdir dir="${statsvn.outputdir}"/>
<exec executable="${svnclient.home}" output="${svn.log}">
<arg line='"log"'/>
<arg line='"--xml"'/>
<arg line='"-v"'/>
</exec>
<java jar="${lib.statsvn}" fork="true" failonerror="true" classpath=".;${lib.statsvn}">
<arg line="${svn.log}"/>
<arg line="."/>
<arg line="-output-dir"/>
<arg line="${statsvn.outputdir}"/>
</java>
</target>


This would be run as:


ant statsvn