7:33:12 pm on 5/17/12

Menu
» Home
» About Scott
» VD Labs
» QRSS VD
» Old Stuff
» Archive
» Publications
» Contact

Categories
» C/C++
» Circuitry
» DIY ECG
» General
» high altitude balloon
» Linux
» Microcontrollers
» Molecular Biology
» My Website
» PHP
» Prime Numbers
» Python
» Radio
» UCF Lab
» Everything
» RF Links

Writings
» MD Labels
» Streamrip
» AIM Thoughts
» WindowsXP?
» Partitioning
» CD/DVD Repair
» Monitor Info
» CRT Deflection
» Venomcrack
» Flash Thing
» Heart/Brain
» Diabetes
» Triops
» Biomed

Friends
» Mike
» Fred
» Kyle W
» Nick
» Louis
» Tom
» Kyle H




Archives
» August 2011
» July 2011
» June 2011
» March 2011
» February 2011
» January 2011
» December 2010
» November 2010
» September 2010
» August 2010
» July 2010
» June 2010
» May 2010
» April 2010
» March 2010
» February 2010
» January 2010
» December 2009
» September 2009
» August 2009
» July 2009
» June 2009
» May 2009
» April 2009
» March 2009
» February 2009
» January 2009
» December 2008
» November 2008
» October 2008
» September 2008
» September 2007
» December 2006
» August 2006
» January 2006
» August 2005
» July 2005
» June 2005
» May 2005
» April 2005
» March 2005
» February 2005
» January 2005
» December 2004
» November 2004
» October 2004
» September 2004
» August 2004
» July 2004
» June 2004
» May 2004
» April 2004
» March 2004
» February 2004
» January 2004
» December 2003
» November 2003
» October 2003
» September 2003
» August 2003
» July 2003
» June 2003
» May 2003
» April 2003
» March 2003
» February 2003
» January 2003
» December 2002
» November 2002
» October 2002
» September 2002
» June 2001

You are currently browsing the The Blogging Protagonist weblog archives for January, 2009.

Archive for January, 2009

« Previous Entries
Next Entries »


Losing… Energy… Fast…
Posted by
Scott January 28th, 2009 | 5,253 words | No Comments »


Scott was 23.35 years old when he wrote this!

Only a couple weeks into my self-induced crunch time (caused by the fact my thesis work is supposed to be completed in less than a month) I’m beginning to feel a little overwhelmed. I still don’t feel it’s impossible, but I do feel like I’m making things better than they actually are in my mind. In what free time I do have, I work on side projects (like my homemade ECG machine). Last night I recorded myself sleeping. In the middle of the night I woke up and the electrodes were incredibly uncomfortable, so I ripped them off my chest and arms (ouch!) and threw them on the floor and went back to sleep. I figured that I had at least several hours’ worth of data, so I’d be fine. The next morning when I woke up I examined the recordings, and apparently I had fallen asleep in under a minute, slept for 29 minutes, then woke up and (assuming it was several hours later) ripped off the electrodes. That’s it! A mere 29 minutes of recording. One day I’ll get my whole sleep cycle recorded. Just you wait.

Here’s a little visual goodie from that recording. This data was processed in a new way – no Fourier transformation! I integrated the original trace, smoothed it 3 times, identified peaks, and used the inverse peak-to-peak distance to determine heart rate. The trace itself is not beautiful (see photo and compare it with previous traces) but if I’ll I’m determining is heartrate, it works! If there’s a weird problem (missed beats, double beats, etc) it will show up as a spike on the heartrate trace and then I can use better tools to identify the trouble in the region affected.

Okay, it’s about time I go do something. I’m in the laboratory right now (go fig) but surprisingly I can’t do a whole lot. I just got some new chemicals in today and am performing a trial run which will be completed tomorrow. Until then, I just have to wait for 18 hours for a reaction to complete. Maybe I’ll browse DA or try to draw something groovy in inkscape. See ya!



Yay Python!
Posted by
Scott January 26th, 2009 | 5,253 words | 1 Comment »


Scott was 23.34 years old when he wrote this!

I’m addicted to xkcd
http://xkcd.com/530/
http://xkcd.com/528/
http://xkcd.com/518/
http://xkcd.com/512/



I’m in Love with InkScape
Posted by
Scott January 25th, 2009 | 5,253 words | No Comments »


Scott was 23.34 years old when he wrote this!

It’s 2:15 am and I can’t sleep, so what do I do? I hope on my laptop and try out new linux software! First of all, I wanted to note that I’ve been afflicted by the mysterious case of the disappearing xmms. Xmms is a linux-based audio player nearly identical to >”Winamp. Traditionally (several months ago) I could just type sudo apt-get install xmms; xmms and xmms would install and run on my Ubuntu system with a user-friendly frontend. Now it seems that xmms is gone – replaced by xmms2 which appears to be an audio server with no front end. Wha? I didn’t put much effort into trying to figure out how to get a front end to xmms2, but brief Googling suggested that xmms2 doesn’t actually have a front-end. Today I realised that you have to install a completely separate package to get a front-end, based on xmms2. It basically acts just like xmms did (pictured). The program is called audacious, and can be installed with sudo apt-get install audacious on an Ubuntu system. Yay! Back to normal.
response to inquiry: the songs in the playlist is a short collection of songs by Splashdown (an extinct late-90s indie band I fell in love with when I was ~13) – believe it or not, all of their music can be downloaded from this website – super awesome huh? I especially recommend halfworld, ironspy, running with scissors, and waterbead (in that order). A few songs in the list are actually from Universal Hall Pass which is a different band with the same lead singer (Melissa Kaplan).

I have to admit that tonight I was blown away by the awesomeness of Inkscape – a vector drawing tool (similar to Adobe Illustrator) which is going to become my next best friend. Like I said, it does pretty much what Illustrator does, but for free! (Illustrator is about $250) It does so much cool stuff and I just realised it would be so freaking awesome to design a website layout using it. I have to admit, for the first 20 minutes I was totally lost – I had a hard time figuring out how to draw a line! But after a little more time, it became really natural, and this program is – jeez – I can’t get over how useful this can be. I decided to get used to this program by drawing-out a schematic of the circuit from my DIY ECG Project (The result is posted at the bottom of this entry, and a screenshot of the creation process is pictured to the side). I know that I will have tremendous use for this software, possibly in the creation of diagrams of the autonomic nervous system for my master’s thesis or perhaps even for a publication… [ponders] Okay I have to get to bed!

Take it from me. Download InkScape (it looks like they have a Windows version, btw) and if you have Ubuntu, install audacious for your music. Scott out.



Using PHP to Create Apache-Style Access.log
Posted by
Scott January 22nd, 2009 | 5,253 words | 2 Comments »


Scott was 23.33 years old when he wrote this!


THIS CODE HAS BEEN UPDATED!
THIS CODE HAS BEEN UPDATED!
THIS CODE HAS BEEN UPDATED!

>>> CHECK OUT THE NEW CODE < <<
[Generate Apache-Style HTTP Access Logs via SQL and PHP]

OBSOLETE CODE IS BELOW…

My web server blocks access to my apache-generated visitor logs (commonly stored in “access.log”). Therefore, many great site usage stats generators (such as awstats – see this example) cannot be used to analyze web traffic to my site. (How many people go what pages? Where do they come from? What search phrases do they type into Google to find my website?) My web host does allow PHP, and access to php.ini, so I figured that I could generate my own access.log using PHP code. I succeeded, but had a hard time doing this because it’s not clearly documented elsewhere – so I’ll make it clear.

Sample line from access.log generated by my PHP script:
132.170.10.227 – - [22/Jan/2009:11:58:49 +0800] “GET /blog/2005-06-29-eva-05-attack-scotts-sanity/ HTTP/1.1″ 200 – “http://www.google.com/search?hl=en&client=firefox-a&rls=org.mozilla%3Aen-US%3Aofficial&hs=8Lk&q=swharden+eva-05&btnG=Search” “Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.0.5) Gecko/2008120122 Firefox/3.0.5″

All I had to do was insert the following line at the end of my php.ini file:

 auto_append_file = "/home/content/n/i/b/nibjb/html/logme.php"  
 

And I placed logme.php in my root folder with the following code:

 $logwriter_logformat = "combined"; // log format,combined or common  
 $logwriter_logdir = "/home/content/n/i/b/nibjb/html/logs/"; // physical path where your log file located  
 $logwriter_logfilename = "access.log"; // your log file's filename  
 $logwriter_timezone = "+0800"; // your server's time zone. +0800 means GMT+8  

 function logwriter_writelog($logstring){  

 global $logwriter_logdir,$logwriter_logfilename;  
 $fullpathfilename = $logwriter_logdir.$logwriter_logfilename;  

 if (!is_file($fullpathfilename)) {  
 print "Log file doesn't exist or file is corrupt.";  
 return;  
 }  

 if (!is_writeable($fullpathfilename)) {  
 print "Log file is not writable,please change its permission.";  
 return;  
 }  

 if($fp = @fopen($fullpathfilename, "a")) {  
 flock($fp, 2);  
 fputs($fp, $logstring);  
 fclose($fp);  
 }  
 }  

 function logwriter_handlevar($varname,$defaultvalue) {  
 $tempvar = getenv($varname);  
 if(!empty($tempvar)) {  
 return $tempvar;  
 } else {  
 return $defaultvalue;  
 }  
 }  

 if (!empty($REMOTE_HOST)) {  
 $logwriter_remote_vistor = $REMOTE_HOST;  
 }else{  
 $logwriter_remote_vistor = logwriter_handlevar("REMOTE_ADDR","-");  
 }  

 $logwriter_remote_ident = logwriter_handlevar("REMOTE_IDENT","-");  
 $logwriter_remote_user = logwriter_handlevar("REMOTE_USER","-");  
 $logwriter_date = date("d/M/Y:H:i:s");  

 $logwriter_server_port = logwriter_handlevar("SERVER_PORT","80");  
 if($logwriter_server_port!="80") {  
 $logwriter_server_port =   
 }else{  
 $logwriter_server_port = "";  
 }  

 $logwriter_request_method = logwriter_handlevar("REQUEST_METHOD","GET");  
 $logwriter_request_uri = logwriter_handlevar("REQUEST_URI","");  
 $logwriter_server_protocol = logwriter_handlevar("SERVER_PROTOCOL","HTTP/1.1");  

 if ($logwriter_logformat=="common") {  
 $logwriter_logstring = "$logwriter_remote_vistor $logwriter_remote_ident $logwriter_remote_user [$logwriter_date $logwriter_timezone] "$logwriter_request_method $logwriter_request_uri $logwriter_server_protocol" 200 - 
 ";  
 }else{  

 $logwriter_http_referer = logwriter_handlevar("HTTP_REFERER","-");  
 $logwriter_http_user_agent = logwriter_handlevar("HTTP_USER_AGENT","");  

 $logwriter_logstring = "$logwriter_remote_vistor $logwriter_remote_ident $logwriter_remote_user [$logwriter_date $logwriter_timezone] "$logwriter_request_method $logwriter_request_uri $logwriter_server_protocol" 200 - "$logwriter_http_referer" "$logwriter_http_user_agent" 
 ";  

 }  

 logwriter_writelog($logwriter_logstring);  
 

Note that the PHP code must be surrounded with < ? php ?> as demonstrated here

The result? As you can tell, my logme.php dumps data to www.swharden.com/logs/access.log – if you browse a few pages on my website, or even use Google to search for me (ie: google for ’swharden’ and ‘minidisc’) you can see yourself in the logfile – pretty cool huh? Once I have a good volume of log data I’ll demonstrate how to turn it into useful information.



Signal Filtering with Python
Posted by
Scott January 21st, 2009 | 5,253 words | 9 Comments »


Scott was 23.33 years old when he wrote this!

It’s time for a lecture. I’ve been spending a lot of time creating a DIY dlectrocardiogram and it produces fairly noisy signals. I’ve spent some time and effort researching the best ways to clean-up these signals, and the results are incredibly useful! Therefore, I’ve decided to lightly document these results in a blog entry.

Here’s an example of my magic! I take a noisy recording and turn it into a beautiful trace. See the example figure with the blue traces. How is this possible? Well I’ll explain it for you. Mostly, it boils down to eliminating excess high-frequency sine waves which are in the original recording due to electromagnetic noise. A major source of noise can be from the alternating current passing through wires traveling through the walls of your house or building. My original ECG circuit was highly susceptible to this kind of interference, but my improved ECG circuit eliminates most of this noise. However, noise is still in the trace (see the figure to the left), and it needed to be removed.

The key is the FFT (Fast Fourier Transformation) algorithm which can get pretty intimidating to research at first! I’ll simplify this process. Let’s say you have a trace with repeating sine-wave-shaped noise. The output of the FFT transformation of the signal is the breakdown of the signal by frequency. Check out this FFT trace of a noisy signal from a few posts ago (top graph). High peaks represent frequencies which are common. See the enormous peak around 60 Hz? (Hz means “per second” by the way, so 60 Hz is a sine wave that repeats 60 times a second) That’s from my AC noise. Other peaks (shown in colored bands) are other electromagnetic noise sources, such as wireless networks, TVs, telephones, and your computer processor. The heart produces changes in electricity that are very slow (the heartbeat is about 1 Hz, or 1 beat per second), so if we can eliminate all of the sine waves with frequencies higher than what we want to isolate we can get a pretty clear trace. This is called a band-stop filter (we block-out certain bands of frequencies) A band-pass filter is the opposite, where we only allow frequencies which are below (low-pass) or above (high-pass) a given frequency. By eliminating each of the peaks in the colored regions (setting each value to 0), then performing an inverse fast Fourier transformation (going backwards from frequency back to time), the result is the signal trace (seen as light gray on the bottom graph) with those high-frequency sine waves removed! (the gray trace on the bottom graph). A little touch-up smoothing makes a great trace (black trace on the bottom graph).

Here’s some Python code to get you started in cleaning-up your noisy signals! The image below is the output of the Python code at the bottom of this entry. This python file requires that test.wav (~700kb) (an actual ECG recording of my heartbeat) be saved in the same folder. Brief descriptions of each portion of the graph will follow.

(A) The original signal we want to isolate. (IE: our actual heart signal)

(B) Some electrical noise. (3 sine waves of different amplitudes and periods)

(C) Electrical noise (what happens when you add those 3 sine waves together)

(D) Static (random noise generated by a random number generator)

(E) Signal (A) plus static (D)

(F) Signal (A) plus static (D) plus electrical noise (C)

(G) Total FFT trace of (F). Note the low frequency peak due to the signal and electrical noise (near 0) and the high frequency peak due to static (near 10,000)

(H) This is a zoomed-in region of (F) showing 4 peaks (one for the original signal and 3 for high frequency noise). By blocking-out (set it to 0) everything above 10Hz (red), we isolate the peak we want (signal). This is a low-pass filter.

(I) Performing an inverse FFT (iFFT) on the low-pass iFFT, we get a nice trace which is our original signal!

(J) Comparison of our iFFT with our original signal shows that the amplitude is kinda messed up. If we normalize each of these (set minimum to 0, maximum to 1) they line up. Awesome!

(K) How close were we? Graphing the difference of iFFT and the original signal shows that usually we’re not far off. The ends are a problem though, but if our data analysis trims off these ends then our center looks great.

Here’s the code I used to make the image:

 import numpy, scipy, pylab, random  

 # This script demonstrates how to use band-pass (low-pass)  
 # filtering to eliminate electrical noise and static  
 # from signal data!  

 ##################  
 ### PROCESSING ###  
 ##################  

 xs=numpy.arange(1,100,.01) #generate Xs (0.00,0.01,0.02,0.03,...,100.0)  
 signal = sin1=numpy.sin(xs*.3) #(A)  
 sin1=numpy.sin(xs) # (B) sin1  
 sin2=numpy.sin(xs*2.33)*.333 # (B) sin2  
 sin3=numpy.sin(xs*2.77)*.777 # (B) sin3  
 noise=sin1+sin2+sin3 # (C)  
 static = (numpy.random.random_sample((len(xs)))-.5)*.2 # (D)  
 sigstat=static+signal # (E)  
 rawsignal=sigstat+noise # (F)  
 fft=scipy.fft(rawsignal) # (G) and (H)  
 bp=fft[:]  
 for i in range(len(bp)): # (H-red)  
     if i>=10:bp[i]=0  
 ibp=scipy.ifft(bp) # (I), (J), (K) and (L)  

 ################  
 ### GRAPHING ###  
 ################  

 h,w=6,2  
 pylab.figure(figsize=(12,9))  
 pylab.subplots_adjust(hspace=.7)  

 pylab.subplot(h,w,1);pylab.title("(A) Original Signal")  
 pylab.plot(xs,signal)  

 pylab.subplot(h,w,3);pylab.title("(B) Electrical Noise Sources (3 Sine Waves)")  
 pylab.plot(xs,sin1,label="sin1")  
 pylab.plot(xs,sin2,label="sin2")  
 pylab.plot(xs,sin3,label="sin3")  
 pylab.legend()  

 pylab.subplot(h,w,5);pylab.title("(C) Electrical Noise (3 sine waves added together)")  
 pylab.plot(xs,noise)  

 pylab.subplot(h,w,7);pylab.title("(D) Static (random noise)")  
 pylab.plot(xs,static)  
 pylab.axis([None,None,-1,1])  

 pylab.subplot(h,w,9);pylab.title("(E) Signal + Static")  
 pylab.plot(xs,sigstat)  

 pylab.subplot(h,w,11);pylab.title("(F) Recording (Signal + Static + Electrical Noise)")  
 pylab.plot(xs,rawsignal)  

 pylab.subplot(h,w,2);pylab.title("(G) FFT of Recording")  
 fft=scipy.fft(rawsignal)  
 pylab.plot(abs(fft))  
 pylab.text(200,3000,"signals",verticalalignment='top')  
 pylab.text(9500,3000,"static",verticalalignment='top',  
            horizontalalignment='right')  

 pylab.subplot(h,w,4);pylab.title("(H) Low-Pass FFT")  
 pylab.plot(abs(fft))  
 pylab.text(17,3000,"sin1",verticalalignment='top',horizontalalignment='left')  
 pylab.text(37,2000,"sin2",verticalalignment='top',horizontalalignment='center')  
 pylab.text(45,3000,"sin3",verticalalignment='top',horizontalalignment='left')  
 pylab.text(6,3000,"signal",verticalalignment='top',horizontalalignment='left')  
 pylab.axvspan(10,10000,fc='r',alpha='.5')  
 pylab.axis([0,60,None,None])  

 pylab.subplot(h,w,6);pylab.title("(I) Inverse FFT")  
 pylab.plot(ibp)  

 pylab.subplot(h,w,8);pylab.title("(J) Signal vs. iFFT")  
 pylab.plot(signal,'k',label="signal",alpha=.5)  
 pylab.plot(ibp,'b',label="ifft",alpha=.5)  

 pylab.subplot(h,w,10);pylab.title("(K) Normalized Signal vs. iFFT")  
 pylab.plot(signal/max(signal),'k',label="signal",alpha=.5)  
 pylab.plot(ibp/max(ibp),'b',label="ifft",alpha=.5)  

 pylab.subplot(h,w,12);pylab.title("(L) Difference / Error")  
 pylab.plot(signal/max(signal)-ibp/max(ibp),'k')  

 pylab.savefig("SIG.png",dpi=200)  
 pylab.show()  
 
« Previous EntriesNext Entries »
copyright © 2006 swharden@gmail.com