Monday, November 16, 2009

Update: Drivers with hemianopia do worse in driving simulator

A group of Harvard researchers published a report that persons with hemianopia performed worse in a diving simulator than normally sighted persons.

Specifically, the persons with hemianopia had difficulty detecting pedestrians on their blind side. This is often the stated concern about letting persons with hemianopia drive - they will have trouble seeing traffic and pedestrians on their blind side.

In contrast, the study published in February 2009 was a "real world" test, where persons were actually taken out on the road in a using a dual-brake vehicle and monitored by a certified driving rehabilitation specialist.

The two studies are not directly comparable, in that the methodologies are strikingly different. However, we can attempt to make reconcile the apparently conflicting results.

The new study states that drivers with hemianopia are not as good as normally-sighted drivers. The real-world study says that they are good enough.

Monday, November 02, 2009

PHP class adds SVG images to PDF files

I have modified the svg2pdf PHP class from Sylvain Briand at for incorporating SVG graphics into a PDF document. The original class is an extension of the awesome FPDF class for creating PDF documents on the fly using PHP. Because FPDF does not support SVG graphics, there is a need for this extension. Briand's class works great, but did not meet all of my needs. My modification adds the following capabilities:

1. Write text on an SVG graphic
2. Transform scale support
3. Overflow hidden support (incomplete)
4. Place multiple SVG graphics on a single page
5. Produce a multi-page PDF document


Within the SVG standard, this would correspond to using a text element, as below:

<text x="210" y="15" font-family=”times” font-weight=”bold” font-style=”italic” font-size="10" fill="red">Hello World</text>

The PDF standard defines 3 standard fonts that all readers should support (Helvetica, Times, and Courier). You can use these fonts, with their bold and italic variants, without issue. The parent FPDF class supports external font definition files, so if you want to use any other font you must import it before calling ImageSVG() [not tested, see FPDF docs for more information on importing fonts].

There is no support for manipulating orientation, baseline alignment, directionality, etc.


Within the SVG standard, this would correspond to using a transform attribute as below:

<g transform="scale(scale_x,scale_y)">

The original class only supported applying styles with the g element. The modified class adds support for scale transformations.

Other transformations (rotate, skew, etc) are not supported.


It is possible, using the drawing tool that generates my SVG graphics, for graphical elements to extend beyond the borders of the image. Therefore, I needed a way to crop these elements down to the height and width defined for the image. Within the SVG standard, this would correspond to applying the overflow attribute of the svg element as below:

<svg overflow="hidden">

Sorry, but I was only able to implement cropping for path objects. Rendered objects (circles, rectangles, etc) may still extend beyond the borders defined for the image.


It is now possible to call ImageSVG() multiple times for a single PDF document, and to add SVG graphics to multiple pages of a multi-page PDF file.

You can download the modified svg2pdf class here. I hope you find it helpful.

Tuesday, January 27, 2009

Many Persons with Hemianopic Vision Loss Can Safely Drive a Car

It's always unfortunate when you have to add insult to injury by revoking the driver's license of a person who has just lost part of their vision due to a stroke, brain tumor, or other intracranial disease.

It is not at all uncommon to have these people tell you that although they realize they have lost part of their vision, they they are safe, careful drivers and they should be allowed to continue to drive.

It has always been my belief that although these people may think they are still capable of driving, they have, in fact, lost the left or right half of their vision in each eye (known as a hemianopia) and are probably a danger to themselves and others if they were to get behind the wheel of a car.

Then comes along a research paper (in the February edition of Investigative Ophthalmology and Vision Science) that confirms what the patient has claimed all along - that they can safely drive a car.

The researchers took 30 patients with hemianopsias (22 complete, 8 partial) and 30 normal-sighted persons for a 14 mile test drive through city and highway traffic. The vehicle was student driver equipted (extra brake) and the person riding shotgun was a certified driving rehabilitation specialist. Two "back-seat" evaluators who didn't know if the driver was normally sighted of had a hemianopic vision defect independently graded driving performance using a standard scoring system.

Using this test system, 73% (16/22) of drivers with a complete hemianopic defect and 88% (7/8) of drivers with a partial hemianopic defect received safe ratings from the back-seat graders.

The researchers concluded that some drivers with hemianopia are fit to drive. These results call into question the fairness of governmental policies that categorically deny licensure to persons with hemianopia without the opportunity for on-road evaluation.

Saturday, January 24, 2009

Scientific Atlanta Explorer 2200 Settop Box

I recently rebuilt my PVR, which contains a Hauppauge PVR-150 with remote. In order for the Hauppauge remote to control my Scientific Atlanta Explorer 2200 settop box (STB), I have to connect a infra-red (IR) emitter from the Hauppauge to the STB, placing the emitter directly over the infrared sensor of the STB. Unfortunately, it was not at all clear where the sensor was located, and the information I could locate on the web was sparse and largely inaccurate.

The IR sensor can be located by shining a bright flashlight through the smoked plastic window containing the LED clock. You will see several circuit board components located on either side of the clock -- look for one that appears to be an "electric eye", round with a lens in the center of it. Place the emitter directly over it and test. If it does not work, place it over a different component and try again until you find the correct component.

Monday, January 19, 2009

SATA Drive Disappears

I recently purchased a Seagate Barracuda 7200.11 ST31500341AS 1.5TB for a PVR I was rebuilding (hopefully I will get around to blogging about this project). There are many reported problems with this drive, but since it is the only 1.5TB HDD currently on the market, and the price is so low, I figured it was worth a shot. I was wrong.

First, there are known firmware issues with this drive. There is also a high reported failure rate. So when I encountered problems with this drive, it was unclear where the fault lay.

The problem I experienced is, apparently, fairly common with SATA drives. After a period of time the hard drive simply disappears from Windows. It cannot be found in either Windows Explorer or Computer Management. It will, however, reappear after a reboot. For me, the HDD consistently disappeared while attempting to copy files onto it.

Reported solutions to this problem include defective cables and power issues. Others mention driver, BIOS, and firmware trouble. Still other "computer voodoo" solutions include switching SATA ports. However, nobody mentioned what may be a more common cause: the HDD is dying.

After spending nearly a week chasing down Seagate Tech Support to obtain a firmware update for my drive, they informed me that the firmware on my drive (CC1H) was the most current (at least for my OS - Windows XP).

After exhausting every other possible solution (including switching SATA ports), I was about ready to RMA the drive when, on a whim, I decided to load up SeaTools, the Seagate Diagnostic software. It immediately informed me that S.M.A.R.T. had been triggered on the drive in question. When I requested the "Long Test" be performed, it essentially informed me that the HDD was already known to be defective, and did I really want to subject it to the Long Test - I conceded.

So, the lesson learned from this experience is that whenever I encounter HDD issues, one of my first steps should be to download the latest version of the manufacturer's diagnostic software and confirm that the drive is not defective. At least in this case, the bad S.M.A.R.T. status was not reported during boot-up nor in the BIOS. I don't know if this is typical of SATA drives or not, but it seems that if you do not specifically check the S.M.A.R.T. status of a HDD, you cannot be assured that it is okay.

Sunday, August 24, 2008

Setup failed to install product catalog

Had a first today.

A friend of a friend suffered a hard drive crash on their old Gateway Pentium 4 computer. While installing Windows XP Pro on a brand new replacement HDD, I encountered an error message I had never seen before: "Setup failed to install product catalog." Clicking through the error dialog box I viewed the log file, where there were a couple more nasty messages about "Setup had problems registering OLE control DLL" and "Signature for Windows Professional setup invalid."

Wow... talk about trying to hurt a guy's feelings.

A little Googleing got me to this Microsoft page that points the finger of blame at bad memory or a problem deleting a directory during the installation process.

I know the memory is good because I ran MemTest86+ overnight just to be certain that I wasn't dealing with a memory or CPU problem.

So, I follow the instructions on the Microsoft page to delete the directory and continue with the install. A few minutes later the error recurred.

Now I was starting to think I might have a bad HDD, so I downloaded and ran the manufacturer's diagnostic software. This drive was a Hitachi, so I used their Drive Fitness Test, but you can find a similar utility for any brand hard drive.

It tested perfect. Now what?

Back to Google, of course. I encountered this page that reported that the OLE error could be traced back to an outdated BIOS. Hmmm... sounds like something worth trying.

Gateway has a pretty good downloads section, and I was able to locate a newer BIOS. The only problem was that the BIOS is packaged to be installed from within Windows! Stupid or what?

After creating a bootable floppy on another computer (it really is worth keeping at least one working floppy around for occasions like this), I copied the BIOS files onto it. I was able to successfully boot to this floppy and flash the BIOS. Hooray!

Problem solved. I was now able to install Windows without a glitch.

Sunday, May 11, 2008

PHP Tag Cloud

I was trying to develop a tag cloud for one of my sites, and had some difficulty finding the best way to calculate what the size of each tag should be. Since I couldn't find a good solution online, I wrote my own.

A little bit of Googling landed me at Prism-Perfect. Here we find a very basic PHP script that really doesn't cut the mustard. The problem is that she takes a strictly linear approach -- the tag proportion (percentage) is used directly to determine the font size of the tag cloud. The reason why this is a poor choice to create a tag cloud is that tag frequency tends to not to be evenly distributed. Instead a few tags will usually have a very high frequency of use, and then it drops off rapidly. A tag cloud created using a tag frequency directly to determine font size will have a few tags that are very large, many tags that are very small, and almost nothing in between.

In the comments section of the Prism-Perfect post, I found a link to Echo Chamber where they take a non-linear approach to calculating tag size. Unfortunately, their calculations are wrong -- or at least they do not accomplish what we are trying to do, which is to more evenly distribute font size within the tag cloud. The equations with the post are flawed, and the corrected equations posted in the comments attempt to fix the problem, but still do not achieve the linearized font distribution that we are looking for. (I was unsuccessful in my attempts to register on Echo Chamber to post a comment to this post, the site appears to be dead.)

Finally, I came across an article on Dr Dobbs on constructing tag clouds. I do not know exactly what language their sample scripts are in (VB?), but they do exactly what we want. I have taken the script that linearizes the Pareto distribution and converted it to PHP.

Here is how it works:

  1. I pull the tags from a database and put them into an array. The array key is the tag itself, and the value is its frequency. I pull other info needed to construct a functioning cloud at the same time and save it into other arrays.

    $query = "SELECT news_categories.category, news_categories.idx, COUNT(news_tag.news_idx) AS quantity FROM news_tag JOIN news_categories ON news_tag.category_idx = news_categories.idx GROUP BY news_tag.category_idx ORDER BY quantity DESC $limit";
    $result = mysql_query($query) or trigger_error("MySQL error nr ".mysql_errno().": ".mysql_error());
    while (list($tagname,$tagid,$quantity) = mysql_fetch_row($result))
    $tagname = trim(stripslashes($tagname));
    $tags[$tagname] = $quantity;
    $tagcount[$tagname] = $quantity;
    $category_id[$tagname] = $tagid;
    $tags = FromParetoCurve($tags, $minSize, $maxSize);

  2. I pass the array containing the tag frequencies to the Dr Dobbs function to linearize it.

    function FromParetoCurve($weights, $minSize, $maxSize)

    $logweights = array(); // array of log value of counts
    $output = array(); // output array of linearized count values

    // Convert each weight to its log value.
    foreach ($weights AS $tagname => $w)
    // take each weight from input, convert to log, put into new array called logweights
    $logweights[$tagname] = log($w);

    // MAX AND MIN OF logweights ARRAY
    $max = max(array_values($logweights));
    $min = min(array_values($logweights));

    foreach($logweights AS $lw)
    if($lw < $min) { $min = $lw; } if($lw > $max)
    $max = $lw;

    // Now calculate the slope of a straight line, from min to max.
    if($max > $min)
    $slope = ($maxSize - $minSize) / ($max - $min);

    $middle = ($minSize + $maxSize) / 2;

    foreach($logweights AS $tagname => $w)
    if($max <= $min) { //With max=min all tags have the same weight. $output[$tagname] = $middle; } else { // Calculate the distance from the minimum for this weight. $distance = $w - $min; //Calculate the position on the slope for this distance. $result = $slope * $distance + $minSize; // If the tag turned out too small, set minSize. if( $result < $minSize) { $result = $minSize; } //If the tag turned out too big, set maxSize. if( $result > $maxSize)
    $result = $maxSize;
    $output[$tagname] = $result;
    return $output;

  3. The returned array is then sorted and looped through to construct the the tag cloud.

You can download the complete scripts here. I hope this helps you in constructing your own tag cloud!