script

BASH Script for Switching Between HDMI and Laptop Screen

Handy bash script I wrote, or actually adapted, for switching between your HDMI monitor and your laptop screen — you just run this when you log-in (also opens or closes gkrellm, which doesn’t fit on the tiny laptop screen) …

#!/bin/bash

# roughly based on:
# http://unix.stackexchange.com/questions/4489/a-tool-for-automatically-applying-randr-configuration-when-external-display-is-p

# laptop screen is LVDS1
# 1080p large-screen is HDMI1

# default monitor is LVDS1
MONITOR=LVDS1

# functions to switch from LVDS1 to HDMI and vice versa,
# give 5 seconds to detect modelines for HDMI monitor or fails
# as it takes a little while for modelines to be auto detected
function ActivateHDMI {
echo "Switching to 1080p monitor, HDMI1 in 5 seconds ..."
sleep 5;
xrandr --output HDMI1 --auto --output HDMI1 --primary --output LVDS1 --off
gkrellm -g -0+25 &
MONITOR=HDMI1
}
function DeactivateHDMI {
echo "Switching to laptop screen, LVDS1 now ..."
killall gkrellm
xrandr --output LVDS1 --auto --output LVDS1 --primary --output HDMI1 --off
MONITOR=LVDS1
}

# functions to check if HDMI is connected and in use
function HDMIActive {
[ $MONITOR = "HDMI1" ]
}

function HDMIConnected {
! xrandr | grep "^HDMI1" | grep disconnected
}

# every one 1 second
# poll to see if HDMI1 is connected

while true
do
if ! HDMIActive && HDMIConnected
then
ActivateHDMI
fi

if HDMIActive && ! HDMIConnected
then
DeactivateHDMI
fi

sleep 1s
done

A Script to Make Pretty Political Google Maps

A while back I wrote I script for converting and styling KML files from ERSI Shapefiles, like you might download or export form a program like Quantum GIS. It requires you have the web programming language PHP 5 installed, along with the ogr2ogr command.

‘ ?>


View Larger Map ‘ ?>

This program extensively uses the PHP/DOM model, to read and write the XML file. I am not an expert programmer — it’s a hobby, but I am very happy with the results. You might consider using the LATFOR data and Census TIGER/Line for this if your a New York State resident.


#!/usr/bin/php -q
<?php
// POLITICAL STYLING FOR KML
// Converts a Shapefile with Election Results in Percentage
// 
// Input:
//      File_Title = Title for KML Name Field (as Seen in Google Maps)
//      District_Name = Field with District Name In It
//      Percent_as_Decimal = Election Result with Percent. 
//      0.00 - 0.49 = Shade of Red
//      0.50 = White
//      0.50 - 1.00 = Blue
//      Shapefile_Name = Path to Shapefile
//
// Output:
//      Google Maps KML File, Nicely Styled

if (!isset($argv[4])) {
        echo "usage: php politicalKML.php [File_Title] [District_Name] [Percent_as_Decimal]  [Shapefile_Name]\n";
        exit;
}

// required fields
$fileTitle = $argv[1];
$nameField = $argv[2];
$percentField = $argv[3];

// filename
$filename = $argv[4];
$KMLfileName = substr($filename,0,-4).'.kml';

// convert shapefile to kml using ogr2ogr
system("ogr2ogr -f \"KML\" -sql \"SELECT * FROM ". substr($filename,0,-4)." ORDER BY $fileTitle ASC\" $KMLfileName $filename -dsco NameField=$nameField -dsco DescriptionField=$percentField");

// load our new kml file
$doc = new DOMDocument();
$doc->load($KMLfileName);

// first let's replace the name field with a nicer one
$oldnode = $doc->getElementsByTagName('name')->item(0);
$node = $doc->createElement('name', $fileTitle);
$doc->getElementsByTagName('Folder')->item(0)->replaceChild($node, $oldnode);

// delete schema field to save space
$oldnode = $doc->getElementsByTagName('Schema')->item(0);
$doc->getElementsByTagName('Folder')->item(0)->removeChild($oldnode);


// load each placemark, search for maximum — used for making color judgements
foreach ($doc->getElementsByTagName('SimpleData') as $data) {
        if( $data->getAttribute('name') == $percentField) {
                $max[] = abs(substr($data->nodeValue,0)-0.5);
        }
}

// maximum in the political race
sort($max); $max = array_pop($max);
        
// calcuate multiplier for each race
$multiple = 255/$max;

// load each placemark, then set styling and percentage description
foreach ($doc->getElementsByTagName('Placemark') as $placemark) {
        foreach ($placemark->getElementsByTagName('SimpleData') as $data) {
                if( $data->getAttribute('name') == $percentField) {
                        $value = $data->nodeValue;
                        $color = substr($value,0);
                }
        }
        
        // decide if we want to do this blue or red, and then calculate
        // the amount of color versus white
        
        // republican leaning
        if ($color <= 0.5) {
                $colorStr = sprintf('%02x', 255-floor(abs($color-0.5)*$multiple));
                $colorStr = "a0{$colorStr}{$colorStr}ff";
        }
        
        // democratic leaning
        if ($color > 0.5) {
                $colorStr = sprintf('%02x', 255-floor(abs($color-0.5)*$multiple));
                $colorStr = "a0ff{$colorStr}{$colorStr}";
        }
        
        if ($color == 0) {
                $colorStr = '00ffffff';
        }
        
        // stylize the node based on color
        $node = $doc->createElement('Style');

        $linestyle = $doc->createElement('LineStyle');
        $node->appendChild($linestyle);
        $linestyle->appendChild($doc->createElement('width', 0.1));
        $linestyle->appendChild($doc->createElement('color', 'ffffffff'));
        
        $polystyle = $doc->createElement('PolyStyle');
        $node->appendChild($polystyle);
        $polystyle->appendChild($doc->createElement('color', $colorStr));       

        $oldnode = $placemark->getElementsByTagName('Style')->item(0); 
        
        $placemark->replaceChild($node, $oldnode);
                        
        // delete extended data to save KML space
        $data = $placemark->getElementsByTagName('ExtendedData')->item(0);
        $placemark->removeChild($data);
        
        // update the description
        $oldnode = $placemark->getElementsByTagName('description')->item(0); 
        $node = $doc->createElement('description', 'Recieved '.($color*100).'% of the vote.');
        $placemark->replaceChild($node, $oldnode); 
}

// finally write to the file
$doc->save($KMLfileName);

// calculate size in MB
$filesize = filesize($KMLfileName)/1024/1024;
if ( $filesize < 10) {
        $zipCommand = "zip ".substr($KMLfileName,0,-4).".kmz $KMLfileName";
        system($zipCommand);
        
        $kmzfilesize = filesize(substr($KMLfileName,0,-4).".kmz")/1024/1024;
        echo "KMZ is " .sprintf('%01.2f', $kmzfilesize)." MB, while the KML file is ".sprintf('%01.2f',$filesize)." MB.\n"; 
}
else {
        echo "Woah Horsey! The produced file is greater then 10 MB, at a size of ".sprintf('%01.2f',$filesize)." MB uncompressed. You need to simply your polygons before proceeding, otherwise Google Maps won't be able to read it. \n";
}

>

Script I Wrote for Generating Contours

I needed an easy way to create contours to add to my topographic maps. Creating major and minor contours for each quad seemed like such a pain, as did loading individual quads into Quantum GIS, then styling them. So I wrote this script that largely automates the process, generating the minor and major (defined as 5x minor) contours from Digital Elevation Model files and combining them into one Shapefile.

I was more familiar with PHP then BASH, so I used php-cli to write this script. Writing a command line script in PHP is a bit werid, but it’s what I did. I you don’t like it, write your own script. It works well for me, but I also have PHP on my laptop for web development stuff, so your milage will vary. I store the complete set of Digital Elevation Models for NY State compressed on my laptop as BZip 2 files.

Along the Edge

Obviously you’ll have to change paths and other minor things to make it work on your machine. Be aware you will have to install the dbase module from PECL for this script to work, as it directly reads each contour shapefile’s .dbf to convert it over to feet. I could not figure out how to do this directly with ogr2ogr, and it just seemed easier to use PHP for this task.

Output for the script is two shapefiles, the major and minor contours, as two files, consisting of all requested quads merged into major and minor shapefiles.

#!/usr/bin/php -q
<?php

array_shift($argv); // remove program name

if (!$argv || !is_numeric($argv[0]) ) echo "usage: php dbupdate.php [contour_feet] [contour1] ... [contourx]\n";

$minor = array_shift($argv);
$major = $minor*5;
$minorMeters = $minor * 0.3048;
$majorMeters = $major * 0.3048;

foreach ($argv as $quad) {

        # uncompress digital elevation model
        $dem = "/home/andy/Documents/GIS.Data/digital.elevation.model/{$quad}elu.dem";
        system("bzip2 -dkv $dem.bz2");
        
        $conDir = "/home/andy/Documents/GIS.Data/dem.contours";

        if (!file_exists($dem)) {
                echo "Digital Elevation Model for $quad NOT FOUND! \n\n";
                continue;
        }
        
        $files = glob("{$conDir}/{$quad}.{$major}ft.*");
        array_map('unlink', $files);

        $files = glob("{$conDir}/{$quad}.{$minor}ft.*");
        array_map('unlink', $files);            
                
        system("gdal_contour -a elev -i {$majorMeters} {$dem} {$conDir}/{$quad}.{$major}ft.shp");
        system("gdal_contour -a elev -i {$minorMeters} {$dem} {$conDir}/{$quad}.{$minor}ft.shp");
        
        #### convert meters to feet in minor and major contour elevations
        
        foreach (array("{$conDir}/{$quad}.{$minor}ft.dbf", "{$conDir}/{$quad}.{$major}ft.dbf") as $file) {
        
                $db = dbase_open("$file", 2);

                if ($db) {
                  $record_numbers = dbase_numrecords($db);
                  for ($i = 1; $i <= $record_numbers; $i++) {

                        // gets the old row
                        $row = dbase_get_record($db, $i);

                        // Update the date field with feet instead of meters
                        $row[1] = ceil($row[1] *3.280839);
        
                        // remove the 'deleted' entry
                        // to understand this, read the dbase man page
                        unset($row['deleted']);

                        // replace record and save
                        dbase_replace_record($db, $row, $i);  
                  }
                }

                dbase_close($db);
        }
        
        // remove uncompressed dem
        unlink($dem);           
}


// put together filename of merged file
$merged = '';
foreach ($argv as $quad) { $merged .= ".$quad"; }
$merged = 'merged'.$merged;

$quads = $argv;

$files = glob("{$conDir}/{$merged}.{$major}ft.*");
array_map('unlink', $files);

$files = glob("{$conDir}/{$merged}.{$minor}ft.*");
array_map('unlink', $files);


system("ogr2ogr {$conDir}/{$merged}.{$major}ft.shp {$conDir}/{$quads[0]}.{$major}ft.shp");
system("ogr2ogr {$conDir}/{$merged}.{$minor}ft.shp {$conDir}/{$quads[0]}.{$minor}ft.shp");

$files = glob("{$conDir}/{$quads[0]}.{$major}ft.*");
array_map('unlink', $files);

$files = glob("{$conDir}/{$quads[0]}.{$minor}ft.*");
array_map('unlink', $files);

array_shift($quads);

foreach ($quads as $quad) { 
        if (!file_exists("{$conDir}/{$quad}.{$major}ft.shp")) continue;

        system("ogr2ogr -update -append {$conDir}/{$merged}.{$major}ft.shp {$conDir}/{$quad}.{$major}ft.shp");
        
        system("ogr2ogr -update -append {$conDir}/{$merged}.{$minor}ft.shp {$conDir}/{$quad}.{$minor}ft.shp");
        
        $files = glob("{$conDir}/{$quad}.{$major}ft.*");
        array_map('unlink', $files);
        
        $files = glob("{$conDir}/{$quad}.{$minor}ft.*");
        array_map('unlink', $files);
}

?>