The personal website of Scott W Harden

Generate LUTs with Python

I wrote a script to generate and display LUTs with Python. There has been a lot of heated discussion in the QRSS Knights mailing list as to the use of color maps when representing QRSS data. I'll make a separate post (perhaps later?) documenting why it's so critical to use particular mathematically-generated color maps rather than empirical "looks good to me" color selections. Anyway, this is what I came up with:

For my QRSS needs, I desire a colormap which is aesthetically pleasing but can also be quickly reverted to its original (gray-scale) data. I accomplished this by choosing a channel (green in this case) and applying its intensity linearly with respect to the value it represents. Thus, any "final" image can be imported into an editor, split by RGB, and the green channel represents the original data. This allows adjustment of contrast/brightness and even the reassignment of a different colormap, all without losing any data!

ORIGINAL DATA: (that's the "flying W" and the FSK signal below it is WA5DJJ)

Note that it looks nice, shows weak signals, doesn't get blown-out by strong signals, and it fully includes the noise floor (utilizing all available data).

This is the Python script I wrote to generate the downloadable LUTs, graphs, and scale bars / keys / legends which are not posted. It requires python, matplotlib, and PIL.

import math
import pylab
from PIL import Image

####################### GENERATE RGB VALUES #######################

r,g,b=[],[],[]
name="Blin_Glin_Rlin"
for i in range(256):
    if i>128: #LOW HALF
        j=128
        k=i
    else: #HIGH HALF
        k=128
        j=i
    #b.append((math.sin(3.1415926535*j/128.0/2))*256)
    #r.append((1+math.sin(3.1415926535*(k-128*2)/128.0/2))*256)
    r.append(k*2-255)
    g.append(i)
    b.append(j*2-1)

    if r[-1]<0:r[-1]=0
    if g[-1]<0:g[-1]=0
    if b[-1]<0:b[-1]=0

    if r[-1]>255:b[-1]=255
    if g[-1]>255:g[-1]=255
    if b[-1]>255:b[-1]=255

####################### SAVE LUT FILE #######################
im = Image.new("RGB",(256*2,10*4))
pix = im.load()
for x in range(256):
    for y in range(10):
        pix[x,y] = (r[x],g[x],b[x])
        pix[x,y+10] = (r[x],0,0)
        pix[x,y+20] = (0,g[x],0)
        pix[x,y+30] = (0,0,b[x])
        a=(g[x]+g[x]+g[x])/3
        pix[256+x,y] = (a,a,a)
        pix[256+x,y+10] = (r[x],r[x],r[x])
        pix[256+x,y+20] = (g[x],g[x],g[x])
        pix[256+x,y+30] = (b[x],b[x],b[x])
#im=im.resize((256/2,40),Image.ANTIALIAS)
im.save(name+"_scale.png")

####################### PLOT IT #######################
pylab.figure(figsize=(8,4))
pylab.grid(alpha=.3)
pylab.title(name)
pylab.xlabel("Data Value")
pylab.ylabel("Color Intensity")
pylab.plot(g,'g-')
pylab.plot(r,'r-')
pylab.plot(b,'b-')
pylab.axis([-10,266,-10,266])
pylab.subplots_adjust(top=0.90, bottom=0.14, left=0.1, right=0.97)
pylab.savefig(name+"_graph.png",dpi=60)
#pylab.show()

####################### SAVE LUT FILE #######################
f=open(name+".lut",'w')
out="IndextRedtGreentBluen"
for i in range(256):
    out+=("t%dt%dt%dt%dn"%(i,r[i],g[i],b[i]))
f.write(out)
f.close()
Markdown source code last modified on January 18th, 2021
---
title: Generate LUTs with Python
date: 2010-05-10 22:31:46
tags: python, old
---

# Generate LUTs with Python

__I wrote a script to generate and display LUTs with Python.__ There has been a lot of heated discussion in the [QRSS Knights mailing list](http://cnts.be/mailman/listinfo/knightsqrss_cnts.be) as to the use of color maps when representing QRSS data. I'll make a separate post (perhaps later?) documenting why it's so critical to use particular mathematically-generated color maps rather than empirical "looks good to me" color selections. Anyway, this is what I came up with:

<div class="text-center img-border">

[![](Blin_Glin_Rlin_scale_thumb.jpg)](Blin_Glin_Rlin_scale.png)

</div>

__For my QRSS needs,__ I desire a colormap which is aesthetically pleasing but can also be quickly reverted to its original (gray-scale) data. I accomplished this by choosing a channel (green in this case) and applying its intensity linearly with respect to the value it represents. Thus, any "final" image can be imported into an editor, split by RGB, and the green channel represents the original data. This allows adjustment of contrast/brightness and even the reassignment of a different colormap, all without losing any data!

<div class="text-center img-border">

![](Blin_Glin_Rlin.jpg-green.jpg)

</div>

__ORIGINAL DATA:__
(that's the "flying W" and the FSK signal below it is WA5DJJ)

<div class="text-center img-border">

[![](Blin_Glin_Rlin_graph_thumb.jpg)](Blin_Glin_Rlin_graph.png)
![](Blin_Glin_Rlin.jpg)

</div>

Note that it looks nice, shows weak signals, doesn't get blown-out by strong signals, and it fully includes the noise floor (utilizing all available data).

<div class="text-center img-border">

![](Blin_Glin_Rlin.jpg-blue.jpg)
![](Blin_Glin_Rlin.jpg-red.jpg)
![](Blin_Glin_Rlin.jpg-green.jpg)
[![](Bsin_Glin_Rsin_graph_thumb.jpg)](Bsin_Glin_Rsin_graph.png)
![](Bsin_Glin_Rsin.jpg)

</div>

__This is the Python script__ I wrote to generate the downloadable LUTs, graphs, and scale bars / keys / legends which are not posted. It requires python, matplotlib, and PIL.

```python
import math
import pylab
from PIL import Image

####################### GENERATE RGB VALUES #######################

r,g,b=[],[],[]
name="Blin_Glin_Rlin"
for i in range(256):
    if i>128: #LOW HALF
        j=128
        k=i
    else: #HIGH HALF
        k=128
        j=i
    #b.append((math.sin(3.1415926535*j/128.0/2))*256)
    #r.append((1+math.sin(3.1415926535*(k-128*2)/128.0/2))*256)
    r.append(k*2-255)
    g.append(i)
    b.append(j*2-1)

    if r[-1]<0:r[-1]=0
    if g[-1]<0:g[-1]=0
    if b[-1]<0:b[-1]=0

    if r[-1]>255:b[-1]=255
    if g[-1]>255:g[-1]=255
    if b[-1]>255:b[-1]=255

####################### SAVE LUT FILE #######################
im = Image.new("RGB",(256*2,10*4))
pix = im.load()
for x in range(256):
    for y in range(10):
        pix[x,y] = (r[x],g[x],b[x])
        pix[x,y+10] = (r[x],0,0)
        pix[x,y+20] = (0,g[x],0)
        pix[x,y+30] = (0,0,b[x])
        a=(g[x]+g[x]+g[x])/3
        pix[256+x,y] = (a,a,a)
        pix[256+x,y+10] = (r[x],r[x],r[x])
        pix[256+x,y+20] = (g[x],g[x],g[x])
        pix[256+x,y+30] = (b[x],b[x],b[x])
#im=im.resize((256/2,40),Image.ANTIALIAS)
im.save(name+"_scale.png")

####################### PLOT IT #######################
pylab.figure(figsize=(8,4))
pylab.grid(alpha=.3)
pylab.title(name)
pylab.xlabel("Data Value")
pylab.ylabel("Color Intensity")
pylab.plot(g,'g-')
pylab.plot(r,'r-')
pylab.plot(b,'b-')
pylab.axis([-10,266,-10,266])
pylab.subplots_adjust(top=0.90, bottom=0.14, left=0.1, right=0.97)
pylab.savefig(name+"_graph.png",dpi=60)
#pylab.show()

####################### SAVE LUT FILE #######################
f=open(name+".lut",'w')
out="IndextRedtGreentBluen"
for i in range(256):
    out+=("t%dt%dt%dt%dn"%(i,r[i],g[i],b[i]))
f.write(out)
f.close()
```

April 27th, 2010

Rachmaninoff's Bookmarklets

What a hodgepodge of topics my life has become. Yeah, dental school has been rough lately (finals week was last week), but I'm hanging in there and trying to be creative nonetheless. I've been dabbling in video motion tracking last week, and am contemplating attacking a project involving a lot of video shooting/editing and possibly some 3D work. It must have been almost 10 years since I last used 3D modeling software! I think it was 3D Studio Max back in the day they required a parallel port dongle and I had to spoof the hardware interface with a script so I could use a hacked version [rolls eyes]. I don't want to give anything away, so I'll leave it at that.

I unknowingly stumbled into a new realm of web scripting when I searched for a way to skimp on my teacher evaluations. At the end of each course, many of our professors provide a point of extra credit for completing course evaluations. These things are lengthy, as you have to bubble choices (1-5) on about 30 topics per teacher, and some courses have 15+ teachers. It can take half an hour to click every bubble even for a single course, so I wrote a script to do it for me. Tom Hayward mentioned to me after-the-fact that such a script is called a Bookmarklet. It's basically some fancy JavaScript with all the line breaks removed so it's a single line, and with all spaces replaced by %20 such that it's formatted as a URL. This JavaScript can be bookmarked as a URL, and when it's clicked the script is run. While it seems to me like a blatantly obvious security risk and a terrible idea, it seems to work on most browsers on most OSes. So, in the hope that this script inspires someone else to be creative, I'll post the source:

javascript: var auto = {
    fillerup: function () {
        var all_inputs = document.getElementsByTagName('input');
        var all_selects = document.getElementsByTagName('select');
        var all_textareas = document.getElementsByTagName('textarea');

        for (var i = 0, max = all_selects.length; i < max; i++) {
            var sel = all_selects[i];
            if (sel.selectedIndex != -1 && sel.options[sel.selectedIndex].value) { continue; }
            var howmany = 1;
            if (sel.type == 'select-multiple') {
                var howmany = 1 + this.getRand(sel.options.length - 1);
            }
            for (var j = 0; j < howmany; j++) {
                var index = this.getRand(sel.options.length - 1);
                sel.options[index].selected = 'selected';
            }
        }

        for (var i = 0, max = all_inputs.length; i < max; i++) {
            var inp = all_inputs[i];
            var type = inp.getAttribute('type');
            if (!type) { type = 'text'; }
            if (type == 'radio') {
                var to_update = true;
                var name = inp.name;
                var input_array = inp.form.elements[inp.name];
                for (var j = 0; j < input_array.length; j++) {
                    if (input_array[j].checked) {
                        to_update = false; continue;
                    }
                }
                if (to_update) {
                    var index = this.getRand(input_array.length - 1);
                    input_array[index].setAttribute('checked', 'checked');
                }
            }
        }
    }
    , getRand: function (count) { return count * Math.random()); }
}; auto.fillerup()

My microchips arrived in the mail! I'm so excited. It's just in time too, I'm about to build my first [hopefully] functional non-bread-boarded single-chip transmitter (with a single-chip preamplifier) QRSS radio beacon -err, manned experimental propagation transmitter. These chips are smaller than the ATTiny2313's I'm used to working with, and will be so awesome to work with surface-mount size. I wonder if I trust myself to hand-drill a circuit board for such a SMT microchip using copper-plated PC board? Perhaps with a dental drill? ha! Finally a use for that blasted thing.

Work on my single-chip radio transmitter has stalled. On one hand I have almost all the equipment I need at my apartment (boxes of components, a dremel, a drill press, an excellent soldering station, copious amounts of work space, boxes of tools, and many different types of wire), but I have no high-quality radio to receive any transmissions my device makes at the target frequency (10.140 MHz). However, a radio shack filled with many gorgeous radios exists on the other side of town at the top of Shands hospital! Yeah, I could work on the project using a frequency I could measure with my Century 21 direct-conversion radio (14 MHz or 7 MHz), but it doesn't seem as exciting doing it this way. I fear I'll build a beautiful 7 MHz transmitter which doesn't perform at 10 MHz. Tonight I realized I left my prototype transmitter bread-boarded at the station, and here I sit with nothing to work on (hence my writing). I've been dabbling in non-productive projects over the last few weeks - I think it's time for me to wake up, shape up, and get back to working on something significant! With that, I'm outta here. Time to read some datasheets.

Markdown source code last modified on January 18th, 2021
---
title: Rachmaninoff's Bookmarklets
date: 2010-04-27 22:09:04
---

# Rachmaninoff's Bookmarklets

__What a hodgepodge of topics my life has become.__ Yeah, dental school has been rough lately (finals week was last week), but I'm hanging in there and trying to be creative nonetheless. I've been dabbling in video motion tracking last week, and am contemplating attacking a project involving a lot of video shooting/editing and possibly some 3D work. It must have been almost 10 years since I last used 3D modeling software! I think it was 3D Studio Max back in the day they required a parallel port dongle and I had to spoof the hardware interface with a script so I could use a hacked version \[rolls eyes\]. I don't want to give anything away, so I'll leave it at that.

__I unknowingly stumbled into a new realm of web scripting__ when I searched for a way to skimp on my teacher evaluations. At the end of each course, many of our professors provide a point of extra credit for completing course evaluations. These things are lengthy, as you have to bubble choices (1-5) on about 30 topics per teacher, and some courses have 15+ teachers. It can take half an hour to click every bubble even for a single course, so I wrote a script to do it for me. [Tom Hayward](http://tomh.us) mentioned to me after-the-fact that such a script is called a [Bookmarklet](http://en.wikipedia.org/wiki/Bookmarklet). It's basically some fancy JavaScript with all the line breaks removed so it's a single line, and with all spaces replaced by %20 such that it's formatted as a URL. This JavaScript can be bookmarked as a URL, and when it's clicked the script is run. While it seems to me like a blatantly obvious security risk and a terrible idea, it seems to work on most browsers on most OSes. So, in the hope that this script inspires someone else to be creative, I'll post the source:

```js
javascript: var auto = {
    fillerup: function () {
        var all_inputs = document.getElementsByTagName('input');
        var all_selects = document.getElementsByTagName('select');
        var all_textareas = document.getElementsByTagName('textarea');

        for (var i = 0, max = all_selects.length; i < max; i++) {
            var sel = all_selects[i];
            if (sel.selectedIndex != -1 && sel.options[sel.selectedIndex].value) { continue; }
            var howmany = 1;
            if (sel.type == 'select-multiple') {
                var howmany = 1 + this.getRand(sel.options.length - 1);
            }
            for (var j = 0; j < howmany; j++) {
                var index = this.getRand(sel.options.length - 1);
                sel.options[index].selected = 'selected';
            }
        }

        for (var i = 0, max = all_inputs.length; i < max; i++) {
            var inp = all_inputs[i];
            var type = inp.getAttribute('type');
            if (!type) { type = 'text'; }
            if (type == 'radio') {
                var to_update = true;
                var name = inp.name;
                var input_array = inp.form.elements[inp.name];
                for (var j = 0; j < input_array.length; j++) {
                    if (input_array[j].checked) {
                        to_update = false; continue;
                    }
                }
                if (to_update) {
                    var index = this.getRand(input_array.length - 1);
                    input_array[index].setAttribute('checked', 'checked');
                }
            }
        }
    }
    , getRand: function (count) { return count * Math.random()); }
}; auto.fillerup()
```

__My microchips arrived in the mail!__ I'm so excited. It's just in time too, I'm about to build my first \[hopefully\] functional non-bread-boarded single-chip transmitter (with a single-chip preamplifier) QRSS radio beacon -err, manned experimental propagation transmitter. These chips are smaller than the ATTiny2313's I'm used to working with, and will be so awesome to work with surface-mount size. I wonder if I trust myself to hand-drill a circuit board for such a SMT microchip using copper-plated PC board? Perhaps with a dental drill? ha! Finally a use for that blasted thing.

<div class="text-center img-small">

[![](attiny44a_thumb.jpg)](attiny44a.jpg)

</div>

__Work on my single-chip radio transmitter has stalled.__ On one hand I have almost all the equipment I need at my apartment (boxes of components, a dremel, a drill press, an excellent soldering station, copious amounts of work space, boxes of tools, and many different types of wire), but I have no high-quality radio to receive any transmissions my device makes at the target frequency (10.140 MHz). However, a radio shack filled with many gorgeous radios exists on the other side of town at the top of Shands hospital! Yeah, I could work on the project using a frequency I could measure with my Century 21 direct-conversion radio (14 MHz or 7 MHz), but it doesn't seem as exciting doing it this way. I fear I'll build a beautiful 7 MHz transmitter which doesn't perform at 10 MHz. Tonight I realized I left my prototype transmitter bread-boarded at the station, and here I sit with nothing to work on (hence my writing). I've been dabbling in non-productive projects over the last few weeks - I think it's time for me to wake up, shape up, and get back to working on something significant! With that, I'm outta here. Time to read some datasheets.

Microcontroller Clocking a Transmitter?

I shouldn't claim this idea as novel. After googling around, I found another person who's doing the same thing, and now that I read his page I remember reading his page before, which is likely where I got the idea in the first place. I want to give him credit and hope that my project can turn out successfully like his! http://clayton.isnotcrazy.com/mept_v1.

Here's my idea: The core of any transmitter is an oscillator, and in simple transmitters (like QRSS devices), it's often a crystal. Frequency adjustment is accomplished by adjusting capacitance to ground on one of the crystal legs. Simple oscillators such as the Colpitts design (based on an NPN transistor) are often used (pictured).

See how pins 4 and 5 allow for a crystal, and pin 6 has a "CKOUT" feature?" I'm still not sure exactly what the waveform of its output looks like. The datasheet is almost intentionally cryptic. About the only thing I've been able to discover from the Internet is that it's sufficient to clock another microcontroller. However, if it's an amplified sine wave output, how cool is it that it might be able to produce RF at the same frequency at which it's clocked?

However in my quest to design a minimal-case long-distance transmitter, I'm trying to think outside the box. Although it's relatively simple, that's still several parts just to make an oscillating sine wave from a crystal. The result still has to be pre-amplified before sending the signal to an antenna. I'm starting to wonder about the oscillator circuitry inside a microcontroller which has the ability to be clocked by an external crystal. For example, take the pinout diagram from an Atmel ATTiny2313 AVR:

Taking it a step further, I wonder if I could write code for the microcontroller to allow it to adjust its own clock speed / frequency output by adjusting capacitance on one of the legs of the crystal. A reverse-biased LED with variable voltage pressed against it from an output pin of the microcontroller might accomplish this. How cool would this be - a single chip transmitter and frequency-shifting keyer all in one? Just drop in a crystal of your choice and BAM, ready to go. Believe it or not I've tested this mildly and it's producing enough RF to be able to be picked up easily by a receiver in the same room, but I'm still unsure of the power output or the waveform. If the waveform is an amplified sine wave I'm going to pass out. More likely it's a weak sine wave needing a preamplifier still, or perhaps even amplified square waves in need of lowpass filtering...

My wife snapped a photo of me working! It's a funny pic - I'm in my own little world sometimes…

Markdown source code last modified on January 18th, 2021
---
title: Microcontroller Clocking a Transmitter?
date: 2010-04-03 23:19:37
tags: qrss, circuit
---

# Microcontroller Clocking a Transmitter?

__I shouldn't claim this idea as novel. __After googling around, I found another person who's doing the same thing, and now that I read his page I remember reading his page before, which is likely where I got the idea in the first place. I want to give him credit and hope that my project can turn out successfully like his! [http://clayton.isnotcrazy.com/mept\_v1](http://clayton.isnotcrazy.com/mept_v1).

__Here's my idea: __ The core of any transmitter is an oscillator, and in simple transmitters (like QRSS devices), it's often a crystal. Frequency adjustment is accomplished by adjusting capacitance to ground on one of the crystal legs. Simple oscillators such as the Colpitts design (based on an NPN transistor) are often used (pictured).

<div class="text-center">

[![](NPN_Colpitts_oscillator_collector_coil_thumb.jpg)](NPN_Colpitts_oscillator_collector_coil.png)

</div>

__See how pins 4 and 5 allow for a crystal, and pin 6 has a "CKOUT" feature?"__ I'm still not sure exactly what the waveform of its output looks like. The datasheet is almost intentionally cryptic. About the only thing I've been able to discover from the Internet is that it's sufficient to clock another microcontroller. However, if it's an amplified sine wave output, how cool is it that it might be able to produce RF at the same frequency at which it's clocked?

__However in my quest to design a minimal-case long-distance transmitter,__ I'm trying to think outside the box. Although it's relatively simple, that's still several parts just to make an oscillating sine wave from a crystal. The result still has to be pre-amplified before sending the signal to an antenna. I'm starting to wonder about the oscillator circuitry inside a microcontroller which has the ability to be clocked by an external crystal. For example, take the pinout diagram from an Atmel ATTiny2313 AVR:

<div class="text-center">

![](attiny-2313.gif)

</div>

__Taking it a step further,__ I wonder if I could write code for the microcontroller to allow it to adjust its own clock speed / frequency output by adjusting capacitance on one of the legs of the crystal. A reverse-biased LED with variable voltage pressed against it from an output pin of the microcontroller might accomplish this. How cool would this be - a single chip transmitter and frequency-shifting keyer all in one? Just drop in a crystal of your choice and BAM, ready to go. Believe it or not I've tested this mildly and it's producing enough RF to be able to be picked up easily by a receiver in the same room, but I'm still unsure of the power output or the waveform. If the waveform is an amplified sine wave I'm going to pass out. More likely it's a weak sine wave needing a preamplifier still, or perhaps even amplified square waves in need of lowpass filtering...

<div class="text-center img-border">

[![](IMG_3206_thumb.jpg)](IMG_3206.png)

</div>

My wife snapped a photo of me working! It's a funny pic - I'm in my own little world sometimes…

<div class="text-center img-border">

[![](IMG_3241_thumb.jpg)](IMG_3241.jpg)

[![](IMG_3245_thumb.jpg)](IMG_3245.jpg)

[![](IMG_3250_thumb.jpg)](IMG_3250.jpg)

[![](IMG_3257_thumb.jpg)](IMG_3257.jpg)

</div>
March 20th, 2010

Impeded Progress

Spring break is over and dental school classes have resumed. An unexpected side-effect of spending all of spring break working so hard on my QRSS VD software project is that when I resumed dental school, I actually feel more relaxed. It's like spring break was my period of intense work, and the rest of dental school is my "break". It makes me a little disappointed though - I feel like dental school isn't pushing me very hard, and I don't feel like I'm learning or growing like I could be. With the estimated cost of tuition totaling ~$200,000 for four years of dental school, I'd have expected classes to feel a little less trite. Anyhow, it is what it is, and I'll make the best of it.

I'm spending the weekend polishing-up code and reading circuit diagrams. I have a few projects on my plate (involving QRSS in some way or another) and I'm managing the transition from productivity back to dental school the best I can...

Markdown source code last modified on January 18th, 2021
---
title: Impeded Progress
date: 2010-03-20 16:53:11
---

# Impeded Progress

__Spring break is over__ and dental school classes have resumed. An unexpected side-effect of spending all of spring break working so hard on my [QRSS VD software project](https://github.com/swharden/QRSS-VD) is that when I resumed dental school, I actually feel more relaxed. It's like spring break was my period of intense work, and the rest of dental school is my "break". It makes me a little disappointed though - I feel like dental school isn't pushing me very hard, and I don't feel like I'm learning or growing like I could be. With the estimated cost of tuition totaling ~$200,000 for four years of dental school, I'd have expected classes to feel a little less trite. Anyhow, it is what it is, and I'll make the best of it.

__I'm spending the weekend polishing-up code and reading circuit diagrams.__ I have a few projects on my plate (involving QRSS in some way or another) and I'm managing the transition from productivity back to dental school the best I can...

W4DFU Gator Seen in Canada

I don't have long, but the picture speaks for itself. Sent from Florida to Canada. I used VE1VDM's "Big Ears Grabber" in Canada.

Markdown source code last modified on January 18th, 2021
---
title: W4DFU Gator Seen in Canada
date: 2010-03-16 12:29:29
tags: qrss
---

# W4DFU Gator Seen in Canada

__I don't have long,__ but the picture speaks for itself. Sent from Florida to Canada. I used [VE1VDM's "Big Ears Grabber" in Canada](http://users.eastlink.ca/~ve1vdm/argocaptures/grabber.htm).

<div class="text-center img-border">

[![](gatorLow_thumb.jpg)](gatorLow.jpg)

</div>

Pages