Archive

Archive for the ‘Education’ Category

Flex Thermal Colormap

January 23rd, 2009 No comments

As a user of Matlab, I have never had to generate a “heat” colormap, since I always use the built in one. It just so happens that among other ongoing projects I have not listed on this website, I will attempt to write some computational examples in Flex/Actionscript 3.0. In order to visualize the data, of course one needs to have some type of plotting features.

I believe I figured out how the “heat” colormap that is generally used for thermal visualization (I’m a Mechanical engineering student) works. It’s actually just HSV. Now depending on how you define HSV, the conversion seems to require people to do strange things (aka the implementation on Wikipedia, that uses HSV and HSL or whatever interchangeably).

However, using GIMP, I found out that the heat colormap is easy to generate from HSV. If you load up the color wheel in any graphical editor that supports choosing colors in HSV, you will notice that it’s generally a wheel, or that the values go from 0 to 360 (obviously a circle). Now the heat map color range we want is usually from [0:240]. We also want to have the higher values map to Red (Hue=0) and the colder or lower values to Blue (Hue=240). The mapping on the color wheel makes it fairly clear what the other algorithms are trying to do.

The mapping algorithm from HSV to RGB is as follows (assuming a S and V=1.0 – a.k.a. heat map colors).

From H=0-59 R=255 G=0-255 B=0

From H=60-119  R=255-0 G=255 B=0

From H=120-179 R=0 G=255 B=0-255

From H=180-239 R=0 G=255-0 B=255

From H=240-299 R=0-255 G=0 B=255

From H=300-359 R=255 G=0 B=255-0

As you can see, it’s a fairly simple linear mapping if you go by HUE. The permutations go according to ROYGBIV along the circle. S, V are selected to be 1.0 simply because that’s what the thermal color map is.

Anyways, the following is just a bit of flex code that displays the value of a 2D function on a domain of [0,1]x[0,1]. It’s my first application with flex and so I’m a little unfamiliar with the data types. So if anyone needs an easy to understand heat/thermal colormap, here’s a “crippled” version of HSV to RGB specifically made for thermal maps.

< ?xml version="1.0"?>
<mx :Application xmlns:mx="http://www.adobe.com/2006/mxml" 
  backgroundColor="#123456"
  creationComplete="init();" width="600" height="600" verticalAlign="middle" backgroundGradientAlphas="[1.0, 1.0]" backgroundGradientColors="[#FFFFFF, #AAAAAA]">
 
  </mx><mx :Script>
  < ![CDATA[
 
 
	var plot:Shape = new Shape();
	var domain_width:Number = 1.0;
	var domain_height:Number = 1.0;
	var domain_xelem:uint = 100;
	var domain_yelem:uint = 100;
	var color_value_max:Number = 1.0;
	var color_value_min:Number = -1.0;
 
    public function init():void 
    {
 
 
    }
 
    public function heatmap(value:Number):Array
    {  	
 
 
    	var RGB:Array;
 
    	// Remap hot color to red and cold color to blue
    	// 240 is the angle range [0:240] for red to blue in HSV
    	var h:uint=(1-(value-color_value_min)/(color_value_max-color_value_min))*240;
 
    	var g:Number=(h%60)/60;
    	var inc:Number=255;
    	var up:uint=int(g*inc);
    	var down:uint=255-up;
 
    	switch(int(h/60))
    	{
    		case 0: return new Array(255,up,0);
    		case 1: return new Array(down,255,0);
    		case 2: return new Array(0,255,up);
    		case 3: return new Array(0,down,255);
    		case 4: return new Array(up,0,255);
    		case 5: return new Array(255,0,down);
    	}
 
		return new Array(255,255,255);
    }
 
    public function RGB(RGBArray:Array):uint
    {
    	return RGBArray[0]*65536+RGBArray[1]*256+RGBArray[2];
    }
 
    public function showMap():void
    {
    			// Define height parameters
		var dx:Number=domain_width/domain_xelem;
		var dy:Number=domain_height/domain_yelem;
 
		// Define color gradient
		var RED:Number = 0xFF0000;
		var BLUE:Number = 0x0000FF;
 
		var scrn_width:Number = myCanvas.width;
		var scrn_height:Number = myCanvas.height;
 
		for(var i:uint=0;i<domain_xelem;i++)
		{
			for (var j:uint=0;j<domain_yelem;j++)
			{
				var x:Number = i*dx+dx/2;
 
				var y:Number = j*dy+dy/2;
				plot.graphics.beginFill(RGB(heatmap(Math.cos(2*Math.PI*x)*Math.cos(2*Math.PI*y))));
				plot.graphics.drawRect(((x-dx/2)*scrn_width),((y-dy/2)*scrn_height),(dx*scrn_width),(dy*scrn_height));
				plot.graphics.endFill();
			}
		}
 
      myCanvas.rawChildren.addChild(plot);
    }
 
  ]]>
  </mx>		
  <mx :Canvas width="400" height="400" id="myCanvas" backgroundColor="#903636">
  </mx>
  <mx :Button label="Generate Color map" id="btnColorMap" enabled="true" click="showMap()"/>
Categories: Education Tags: , , , , ,

GWT XML Indenter/Formatter

December 31st, 2008 5 comments

So while I was working on one of my outreach projects as a graduate student, I wanted to write a simple XML indenter to make my GWT generated xml more aesthetically appealing using stock GWT. The xml document is assumed to be as lean as possible (There are no empty #text nodes that are usually in xml because of the indentation.)

I should also mention that I’m posting this because I didn’t really see any stock simple GWT indenters after a quick google. The following is not meant to be a complete indenter, just something quick and simple to organize xml.

Here’s a basic indenter.

	public String formatXML(Node node,String tab_str)
	{
		String formatted="";
 
		if (node.getNodeType()==Node.ELEMENT_NODE)
		{
			String attributes="";
			for (int k=0;k < node.getAttributes().getLength();k++)
				attributes+=" "+node.getAttributes().item(k).getNodeName()+"=\""+node.getAttributes().item(k).getNodeValue()+"\"";
 
			formatted=tab_str+"<"+node.getNodeName()+attributes+">\n";
 
			for (int i=0;i< node.getChildNodes().getLength();i++)
			{
				formatted=formatted+formatXML(node.getChildNodes().item(i),tab_str+"    ");
			}
			formatted=formatted+tab_str+"</"+node.getNodeName()+">\n";
		}
		else
		{
			if (node.toString().trim().length()>0)
				formatted=tab_str+node.toString()+"\n";
		}
 
		return formatted;
	}
Categories: Education Tags: , , , ,

Pbox2avi for windows

December 17th, 2008 No comments

It appears that windows is incompatible with some of the shelling parts of my python script, so I have uploaded a windows specific version to take care of these issues.

Issues are:

  • piping
  • commands.getstatusoutput (doesn’t work on windows)

Download: pbox2avi_win.py

Pbox2avi update!

December 15th, 2008 No comments

Thanks to Phil’s advice on how to use exiftool more effectively, I’ve decided to update the script so it’s a little shorter.

Download:pbox2avi.py

# python script to extract lecture slides and mp3's from UCSF lecture files for conversion
 
#requires swfextract
 
import commands,sys,re
 
def parse(filename):
    #check filename for .swf extension
    if not filename.find('.swf'): # not a comprehensive check
        return
 
    #open file
    status, output = commands.getstatusoutput("swfextract %s" % (filename,))
 
    print output
 
    #find "JPEGs: ID(s)"
    slide_identifier = "JPEGs: ID(s)"
    start=output.find(slide_identifier)
    slide_extract=[]
    if start:
        start += len(slide_identifier)+1
        slide_end = output.find("[-s]",start)
        print start,slide_end
        slide_extract=output[start:slide_end-2].replace(" ","")
 
    #find "Sounds: ID(s)"
    sound_identifier = "Sounds: ID(s)"
    start=output.find(sound_identifier)
    sound_extract=[]
    if start:
        start += len(sound_identifier)+1
        sound_end = output.find("[-f]",start)
        sound_extract=output[start:sound_end-2].replace(" ","")
 
    # now extract all the data
    print "swfextract %s -P -j %s -s %s" % (filename,slide_extract,sound_extract)
 
    status, output = commands.getstatusoutput("swfextract %s -P -j %s -s %s" % (filename,slide_extract,sound_extract))
 
    return slide_extract,sound_extract
 
def create(slide_extract,sound_extract,outputfile):
    #first throw out every other picture because second picture is always a thumbnail
    slides=slide_extract.replace(","," ").split(" ");
    slides=[slides[i] for i in range(len(slides)) if i%2 ==0]
 
    sounds=sound_extract.replace(","," ").split(" ");
 
    print "Number of slides: %s, number of mp3's: %s" % (len(slides),len(sounds))
    for i in range(len(sounds)):
 
        vidcmd="jpeg2yuv -n %d -I p -f 2 -j %s | yuv2lav -o temp.avi" % (int(round(2*10*(duration("sound%s.mp3" % (sounds[i],))))/10),"pic%s.jpg" % (slides[i],))
        # print vidcmd
        status,output=commands.getstatusoutput(vidcmd)
 
        sndcmd="mencoder temp.avi -o slide%d.avi -ovc lavc -lavcopts vcodec=msmpeg4 -oac copy -audiofile sound%s.mp3" %(i,sounds[i])
 
        # print sndcmd
        commands.getstatusoutput(sndcmd)
        print "Finished processing slide %d" % (i,)
 
    print "Cleaning up..."
    # remove unnecessary data
    commands.getstatusoutput("rm *.jpg *.mp3 temp.avi")
 
    slidevids=["slide%s.avi" % (i,) for i in range(len(slides))]
 
    slidevids=" ".join(slidevids)
 
    print "Combining slides..."
    # combine all of them
    commands.getstatusoutput("mencoder -oac copy -ovc copy %s -o %s" % (slidevids,outputfile))
 
    print "Cleaning up..."
    commands.getstatusoutput("rm slide*.avi")
 
def duration(mp3):
    # find duration of mp3 using exiftool
    cmd="exiftool %s -Duration -n -S -s" % (mp3,)
    status,output = commands.getstatusoutput(cmd)
    return float(output)
 
if __name__=="__main__":
    slides,sounds=parse(sys.argv[1])
    if len(sys.argv)==2:
        create(slides,sounds,"output.avi")
    elif len(sys.argv)==3:
        create(slides,sounds,sys.argv[2])
Categories: Education, Releases, Useful Apps Tags: