Upgrading bios when running Linux…

February 18th, 2010

I would like to upgrade the bios of a HP pavillion of mine that PC is running Linux. The download was an exe-file, where the data parts were so well hidden that no decompression program I have was able to find it. I tried to run it on another PC I have with XP, but then the program claimed it was going to upgrade the bios on that PC… I did not think putting the bios image from an old desktop HP on a new portable Dell. But then, wine to the rescue.

Install wine on the PC in question (or any other linux PC) and run the bios updater there, just let it try to upgrade the bios, then it will crash, but before that, it has unpacked what was needed. I found all the files in ~/.wine/c_drive/windows/temp/pft1a08.tmp (guess the last directory will be different, but with a newly installed wine the temp dir was pretty empty.)

Inside that directory resided

347.rom CopyDisk.exe install.exe sp26713.img sp26713.iso sp26713.rtf WBDED44I.DLL wilx44i.dll WinFlash.exe WINFLASH.HLP WinFlash.sys

I guess 347.rom is the update image, which I might be possible to us through flashrom or something similiar, but I just burned the sp26713.iso-file to a cdrom, booted from that and had the bios upgraded 3 minutes later. If I had had some floppy disks around, I could have tried the img-file. Felt as a bit of waste to burn 1 MB on a CD for a one-off use…

But the PC was neither able to boot from USB after the upgrade … :-p

Convert vmap0 layers into shapefiles

February 17th, 2010

The vmap0 dataset is a slightly dated, but anyhow often usable dataset of maps of all of the world in scale 1:1 000 000. It can be downloaded at e.g. mapability.com. The problem shows up as soon as one tries to use the dataset as it is in a quite unique format. Luckily, the format is known by ogr, so the data can be converted to something usable. When downloaded and unzipped, the dataset contains a lot of layers with various types of information. To get an overview, use ogrinfo:

ogrinfo -ro -summary gltp:/vrf/osgeo4w/share/maps/v0eur_5/vmaplv0/eurnasia

gltp is the protocol, vrf is the format. I unzipped my dataset (v0eur.tar.gz) into c:\osgeo4w\share\maps and the catalog structure below that point was made. The ogrinfo should list approximately 60 data sets. Each of those may be converted using ogr2ogr like

ogr2ogr landicea.shp gltp:/vrf/osgeo4w/share/maps/v0eur_5/vmaplv0/eurnasia landicea@phys(*)_area landicea

To repeat this 60 times is a bit tedious, so let’s use the information from ogrinfo which makes a line like

33: landicea@phys(*)_area (Polygon)

for each dataset.

running this through the regexp

/[0-9]*\: \(\(.*\)@\(.*\)(.*\) (.*)/

gives out the the two strings we needs for ogr2ogr. (The regexp throws away any number of numbers followed by a colon and space then captures the following string, the part of that string which is before an @-sign and the part of the string between the 2 and the next opening paranthesis then throws away a space and something inside a pair of parantesies). if we use sed to run this, the command

sed 's![0-9]*\: \(\(.*\)@\(.*\)(.*\) (.*)!ogr2ogr v0\2\3.shp gltp:/vrf/osgeo4w/share/maps/v0eur_5/vmaplv0/eurnasia \1 \2!' < vmap0layers

will return the ogr2ogr command lines needed to do the conversion to shape files.

So let's put it all together:

set uri=gltp:/vrf/osgeo4w/share/maps/v0eur_5/vmaplv0/eurnasia
ogrinfo -ro -summary %uri% > vmap0layers
sed 's![0-9]*\: \(\(.*\)@\(.*\)(.*\) (.*)!ogr2ogr v0\2\3.shp %uri% \1 \2!' < vmap0layers  > converts.bat

(I was using ! to mark the regexp to avoid problems with the slashes in the directory) The script above was tested in cmd and 4nt on windows xp. a slightly changed version should work in /bin/sh or compatibles;

export uri=gltp:/vrf/osgeo4w/share/maps/v0eur_5/vmaplv0/eurnasia
ogrinfo -ro -summary $uri > vmap0layers
sed 's![0-9]*\: \(\(.*\)@\(.*\)(.*\) (.*)!ogr2ogr v0\2\3.shp  $uri \1 \2!' < vmap0layers  > converts.bat

Just remember to adjust the uri variable to whereever your maps are stored.

Thanks to grymoire for some reminders on sed and to blacksworld.net for explanation to extract the layers one by one.

Hiding the map= parameter from a map server application

February 11th, 2010

In the mapserver documentation, one is told to use a cgi-wrapper script to hide the map= parameter. Then there is shown a script to use on ‘any system having a /bin/sh’ I tried to rewrite that as a php-script to use under windows, but that did not work, so apaches mod_rewrite to the rescue in three small steps:

1) Comment out the mod_rewrite line in httpd.conf

2) Enable mod_rewrite for the actual document root. I am using virtual servers and added the following lines in the actual <VirtualHost > section:

<Directory “c:\documents and settings\vserver\radioecology”>
Options FollowSymLinks
AllowOverride All
</Directory>

2.5 Restart apache

3 make a .htaccess file in the actual directory:

RewriteEngine on
RewriteRule ^wmsmap?(.*) /cgi-bin/mapserv.exe?map=/documents+and+settings/vserver/radioecology/mobilweb/mobilwms.map&$1

The rewriteRule says: given a webpage starting with wmsmap, pick out the query parameters, make a new page request starting with /cgi-bin/mapserv.exe?map=(…)? and add on whatever was the query parameter in the original page request. Quite simple when one just knows how to do it.

How to make a bar graph with a split Y axis in R

February 8th, 2010

There is a function, gap.barplot for doing that in the plotrix package, but I was not happy with the way the result looked, so I made it my own way using subplot in the TeachingDemos library.

data=data.frame(R=c(120,11),U=c(32,1),C=c(12,3),G=c(4,0),J=c(6,0),I=c(3,2),N=c(4,0))
# I want to plot the lower values up to 55, then a split to 95 for the last top. This
# should make it clear which is the highest, without drowning out the other data.
# Setting up an outer wireframe for the plots. I want the split to be approx 5% of the scale,
# I am to plot the ranges 0 - 55 and 95 - 140, in total 10 decades, I multiply that with
# 2 and add 5 and get 21 units on the outer Y axis:
plot(c(0,1),c(0,21),type='n',axes=FALSE,ylab="Number of something",xlab='')
# Plotting the lower range in the lower 11/21 of the plot. xpd=FALSE to clip the bars
subplot(barplot(as.matrix(data),col=heat.colors(2),ylim=c(0,55),xpd=FALSE,las=3),x=c(0,1),y=c(0,11))
# Plotting the upper range in the upper 9/21 of the plot, 1/21 left to the split. Again
# xpd=FALSE, names.arg is set up to avoid having the names plotted here, must be
# some easier way to do this but this works
subplot(barplot(as.matrix(data),col=heat.colors(2),ylim=c(95,140),xpd=FALSE,
    names.arg=c('','','','','','','')), x=c(0,1),y=c(12,21))
# Legend. An annoiance is that the colors comes in the opposite order than in the plot.
legend("topright",c('Group 1','Group 2'),fill=heat.colors(2))
# so far so good. (Just run the upper part to see the result so far
# Just want to make the ends of the axes a bit nicer.
# All the following plots are in units of the outer coordinate system

lowertop=11.1     # Where to end the lower axis
breakheight=0.5   # Height of the break
upperbot=lowertop+breakheight # Where to start the upper axes
markerheight=0.4 # Heightdifference for the break markers
markerwidth=.04  # With of the break markers
# Draw the break markers:
lines(c(0,0),c(1,lowertop))
lines(c(markerwidth/-2,markerwidth/2),c(lowertop-markerheight/2,lowertop+markerheight/2))
lines(c(0,0),c(upperbot,14))
lines(c(markerwidth/-2,markerwidth/2),c(upperbot-markerheight/2,upperbot+markerheight/2))

Bar plot with break

R is a free software environment for statistical computing and graphics. For more information and download, see http://www.r-project.org/

TODO: rewrite to use par(fig) to be able to do without any external libraries.

Hva en direktør tør

February 6th, 2010

Noen av oss vet at vi ikke kan få alt vi ønsker oss. Noen av oss vet at det er ekstremt patetisk å skylde på andre for feil vi helt klart er skyld i selv. Noen av oss har en liten ide om at det kan være gunstig å ikke makse ut alle kreditter i gode tider. Men, dette er tydeligvis ikke noen kunnskap man trenger for å være direktør. Konsekvensene om man skal ta ham alvorlig er jo egentlig enda værre. Han mener i så fall at han kan være direktør med 100000 kr i måneden i lønn på et tidspunkt han hadde så dårlig styring på egen økonomi at alle andre enn ham selv burde forstått at han ikke burde få et lån på 1.9 millioner. Eventuelt skulle jeg gjerne likt å hørt levenet han hadde satt i gang om dnbnor hadde nektet ham lånet i 2008 før finanskrisen slo inn.

Setting up a mysql database for spatial data

January 29th, 2010

I would prefer to use postgis, but have to resign to mysql. I want to create a table with spatial information and be able to access it from mapserver. As I am going to store a lot of datapoints, they may be stored just as two columns with x and y values, but as the dataset grows, that starts to be a bit slow.

I started of with a table with more than 20 columns holding point measurements and a lot of metadata related to those measurements. No, it is not practical to split that table up. I tried to add a point column to that table

alter table mobile_rawdata add column coord point

and then I copied the coordinates into that column

update rawdata set coord=point(lon,lat) where not lat is null;

again fine and dandy, but when I tried to put a spatial index on that column, I was told that that was not possible for a column with null values.

So I made a new table

create table mobile_spatial(
OGR_FID serial primary key,
SHAPE geometry not null,
rawdataid integer not null,
addtime timestamp default current_timestamp);

note that the shape column is to be of type geometry, if it is set to another spatial type, ogr will not recognice it. The column names OGR_FID and SHAPE are used as those are default values for ogr. Rawdataid pointing to the id of the old mobile_rawdata table.

Then I tested it with

ogrinfo -so MySQL:radioecology_9,user=user,password=pass mobile_spatial

but ogrinfo still did not understand that this was supposed to be a table with geometry. Reading up a bit more, I found that I needed two more tables in the database: SPATIAL_REF_SYS to store the, well, spatial reference systems and geometry_columns to store information on what kind of geometry the tables had.

I didn’t manage to find a description for those tables but according to gdal.org they will be created when a shape file is imported using ogr2ogr. Trying to import a shape file, I had them created:

CREATE TABLE geometry_columns (
`F_TABLE_CATALOG` varchar(256) DEFAULT NULL,
`F_TABLE_SCHEMA` varchar(256) DEFAULT NULL,
`F_TABLE_NAME` varchar(256) NOT NULL,
`F_GEOMETRY_COLUMN` varchar(256) NOT NULL,
`COORD_DIMENSION` int(11) DEFAULT NULL,
`SRID` int(11) DEFAULT NULL,
`TYPE` varchar(256) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

and

CREATE TABLE spatial_ref_sys (
`SRID` int(11) NOT NULL,
`AUTH_NAME` varchar(256) DEFAULT NULL,
`AUTH_SRID` int(11) DEFAULT NULL,
`SRTEXT` varchar(2048) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

the important column in the latter is the SRTEXT, eg for standard WGS84 lat lon, that is

GEOGCS["WGS 84", DATUM["WGS_1984",SPHEROID["WGS 84", 6378137, 298.257223563, AUTHORITY["EPSG","7030"]], AUTHORITY["EPSG","6326"]], PRIMEM["Greenwich",0,AUTHORITY["EPSG","8901"]], UNIT["degree", 0.01745329251994328,
AUTHORITY["EPSG","9122"]], AUTHORITY["EPSG","4326"]]

the SRID field is to be pointed to by the SRID in the geometry_column table.

The geometry_column table has to have the following values:
F_TABLE_NAME : Name of table
F_GEOMETRY_COLUMN: Column in table that holds the geometrical information
COORD_DIMENTION: Dimentionallity of dataset, usually 2
SRID : pointer to the spatial_ref_sys table
TYPE: Type of geometry in the geometry colum, e.g. POINT or POLYGON
the last to columns may be blank.

Query a layer in mapscript php

January 28th, 2010

When learning to use mapserver and mapscript, the first steps have been to display, zoom and pan. Zooming and panning is quite easy, it is just a line like

$map->zoompoint($zoomfactor,$clickpoint,$map->width,$map->height,$mapextent);
where $map is a mapboject, $zoomfactor is a number telling how many times to zoom in or out, positive for zoom in, negative for zoom out, $clickpoint is a pointobject of the location of the click in image coordinates.

Then enter the urge to do a query as well – but not much luck. I reused the same $clickpoint and tried
$map->queryByPoint($clickpoint, MS_SINGLE, 1);
(after doing some adjustments in the map file) but to no luck. Digging into the kmap source code, I understood after a while that the coordinates needed to be in map coordinates and not image coordinates. That is just a simple linear transformation, just with the little snag that the y-coordinates go the opposite direction in the image than in the map. Kmap called the transformation function twice, once for each koordinate, I preferred to make one function for the two-dimentional transformation:

function pix2geo($mapx,$mapy,$minx,$miny,$maxx,$maxy,$sizex,$sizey)

// $mapx and $mapy: image coordinates of point of interest
// $minx, $maxx,$miny, $maxy map extent in map coordinates
// $sizex and $sizey, width and height of image
{
	list($miny,$maxy)=array($maxy,$miny);
	// swaps miny and max y since the coordinates acsends upwards in the map, downwards in the picture
	$geopoint=array();
	foreach( array('x','y') as $dim){
		$p=array();
		foreach(array('map','min','max','size') as $par){
			$name="$par$dim";
			$p[$par]=$$name;
		}
		$geowidth=$p['max']-$p['min'];
		$geopoint[$dim]=$p['map']/$p['size']*$geowidth+$p['min'];
	}
	return(array($geopoint['x'],$geopoint['y']));
}

This can be used like:

list($geoX,$geoY)=pix2geo($_GET['MAP_x']*1,$_GET['MAP_y']*1,$minx,$miny,$maxx,$maxy,$map->width,$map->height);
$geopoint=ms_newpointObj();
$geopoint->setXY( $geoX,$geoY);
$map->queryByPoint($geopoint, MS_SINGLE, 1);

followed by getNumResults for each layer, getResult, getShape and finally getting the relevant values out of the shape.

I have to admit, I simplified things a bit at the beginning. The point needs to be in the projection of the queried data set. As I have the queried dataset in geographical projection and want to have the map in utm, I still have a problem there..

Selection from a mysql/ogr layer in php mapscript

January 27th, 2010

A little phpsnippet for filtering out items from a layer. I have a layer “mobil” which may be on or off. This layer consists of a number of dataset collected at various times. There is one field ‘visible’ that is used to indicate if the dataset is of general interest (eg testing and calibration datasets are set with visible to false) The datasets do also belong to a project, indicated with a projectid in the table. There are also going to be some more items to filter on. Since I don’t know a priori how many items there will be filtered on, I am putting the filter expressions in an array and combining them with ‘and’ before I set the filter on the layer.

if($_GET['mobil']=='ON'){ // no reason to do this if the layer is not visible
	if(!($_GET['invisible']=='ON')){$filters[]="visible = 1";}
	if($_GET['project']*1){$filters[]="projectid = ".$_GET['project']*1;}
	if(count($filters)){ // if there are any items to filter on
		$qLayer = $map->getlayerbyname('mobil');
		$filter="where ".implode(" and ",$filters);
		$qLayer->setfilter($filter);
	}
}

This works for sql-based layers and maybe some others, for some types of layers, one needs to set filter and filteritem.

svn copy problem

January 11th, 2010

Being a bit to eager when cleaning up a repository, I managed to remove a file too many from revision control. I still had the file sitting around, so I just readded it – but then the revision history had gone… I found a quite promising post at Markphip’s blog, but when I tried to follow that description,

svn copy -r498 -m “Restore history” file
:///home/users/radioecology/svn/AMAPds/branches/mobilweb/WaterfallApplet.java
file:///home/users/radioecology/svn/AMAPds/branches/mobilweb

(revision 499 was the one with the unfortunate remove) svn told me that “svn: Unable to find repository location for ‘file:///home/users/radioecology/svn
/AMAPds/branches/mobilweb/WaterfallApplet.java’ in revision 498″

No idea why, it definiately was there..

I am using Syntevos SmartSVN foundation as a front end on windows, tried to do a Modify -> copy within repository – that did not work either. At last I came across the mention of peg revisions and one
” svn cp file:///home/users/radioecology/svn/AMAPds/branches/mobilweb/WaterfallApplet.java@498 file:///home/users/radioecology/svn/AMAPds/branches/mobilweb/ -m “Restore”
” later and the file and history was back.No idea why the others did not work. Seems like a bit of black magic within svn – or maybe someone can explain exactly what happened.

Clas Olssons kortleser

December 25th, 2009

Advarsel! Ikke kjøp Clas Olssons 3,5″ interne minnekortleser om du har en PC du må få montert den i. Den er tilsynelatende et par mm både høyere og bredere enn hva en 3,5″ enhet skal være, trenger skohorn for montering. dvs så langt har jeg bare prøvd to forskjellige maskiner, den går ikke inn i noen av dem, så det kan jo være at det finnes en odde maskin der ute et sted med litt for stor 3,5″ holder, evt at de to maskinene jeg har prøvd har krympet. Jeg har montert både 3,5″ harddisker, floppydisker og en tape stasjon eller to i mitt liv, men har så langt ikke opplevd noen som fysisk ikke passer.

Edit: På tredje forsøk fikk jeg stappet leseren inn, riktignok fikk jeg bare festet den med en skrue på hver side og så viste det seg at den maskinen jeg hadde funnet ikke hadde noen intern USB-head :-P

edit igjen: Det fikk jeg stappet den på plass i et chieftec kabinett. Det mente også at en 3.5″ skulle være litt smalere og var ikke enig i hvor skruehullene for en frontmontert enhet skulle være, men nå henger den da på plass der på et vis…