środa, 7 marca 2012

Import KML files to GoogleMaps

The nuisance of GoogleMaps is that it does not know GPX and only KML/GeoRSS files can be uploaded. Fortunately it is easy to convert GPX to KML with gpsbabel:


gpsbabel -i gpx -f file.gpx -x simplify,count=333 -o kml -F file.kml

If there are several files they have to be convert one-by-one and then upload to Google. It would be more comfortable to merge them first and upload it in one go rather than uploading each individually.

As I could not find how to merge serveral GPX files into one using gpsbabel (merge option in gpsbabel puts all track points from all tracks into a single track and sorts them by time stamp. Points with identical time stamps will be dropped) I worked out the following simple Perl script:


#!/usr/bin/perl
#
# Combine GPX files into one
# usage: gpxmerge file1 file2 file3 ....
#
use XML::DOM;
binmode(STDOUT, ":utf8");

my $parser = new XML::DOM::Parser;

for my $file2parse (@ARGV) {
my $doc = $parser->parsefile ($file2parse);

for my $w ( $doc->getElementsByTagName ("wpt") ) { $waypoints .= $w->toString() . "\n"; }
for my $r ( $doc->getElementsByTagName ("rte") ) { $routes .= $r->toString() . "\n"; }
for my $t ( $doc->getElementsByTagName ("trk") ) { $tracks .= $t->toString() . "\n"; }
}

print "<?xml version='1.0' encoding='UTF-8' ?>
<gpx version='1.1' creator='GPXmerger'
xmlns='http://www.topografix.com/GPX/1/1'
xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'
xsi:schemaLocation='http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd'>\n
<author>tomasz przechlewski </author>
<email>tprzechlewski[at]acm.org</email>
<url>http://pinkaccordions.homelinux.org/Geo/gpx/</url>";

print "$waypoints\n$routes\n$tracks\n";

print "</gpx>\n";

The resulting file structure is as follows: first all waypoints, then all routes and finally all tracks. This is perfectly legal GPX file.

Now I convert GPX to KML using gpsbabel:


gpsbabel -i gpx -f file.gpx -x simplify,count=333 -o kml -F file.kml

Since gpsbabel generates pretty verbose KML files I simplify them using XSLT stylesheet (perhaps this step is superfluous):


xsltproc -o simplified.kml kml2kml.xsl file.kml

and the stylesheet looks like:



<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:kml="http://www.opengis.net/kml/2.2" >

<xsl:output method="xml" indent='yes' />

<xsl:template match="/">

<!-- ;; http://www.jonmiles.co.uk/2007/07/using-xpaths-text-function/ ;; -->

<kml xmlns="http://www.opengis.net/kml/2.2" xmlns:gx="http://www.google.com/kml/ext/2.2">
<Document>


<Folder>
<name>Waypoints</name>

<xsl:for-each select="//kml:Folder[kml:name/text()='Waypoints']/kml:Placemark//kml:Point">
<Placemark>
<!-- <name><xsl:value-of select='../kml:name'/></name> --><!-- niepotrzebne -->
<Point>
<coordinates>
<xsl:value-of select="kml:coordinates"/>
</coordinates>
</Point>
</Placemark>
</xsl:for-each>

</Folder>


<Folder>
<name>Tracks</name>

<xsl:for-each select="//kml:Placemark//kml:LineString">

<Placemark>
<name>Path</name>

<LineString>
<tessellate>1</tessellate>
<coordinates>

<xsl:value-of select="kml:coordinates"/>

</coordinates>
</LineString>
</Placemark>

</xsl:for-each>

</Folder>

</Document>
</kml>

</xsl:template>
</xsl:stylesheet>

Now KML file is ready to be imported to Google maps via Maps → My Places → Create map.

The result of example conversion can be be found here.

Konfigurowanie TeXlive

Pliki systemu TeXLive są umieszczone nie w jednym a w kilku katalogach. Listę tych katalogów otrzymamy wykonując polecenie:

kpsewhich -expand-var '$TEXMF'

Mówiąc bardziej precyzyjnie: $TEXMFMAIN to katalog główny (korzeń główny instalacji), którego zawartość nie powinna być modyfikowana w inny sposób niż poprzez tlmgr; $TEXMFLOCAL -- tu można instalować coś prywatnego, co będzie dostępne dla wszystkich użytkowników systemu (system-wide); $TEXMFHOME -- prywatne pliki użytkownika.

kpsewhich --expand-var '$TEXMFMAIN' # korzeń główny = to co dała fabryka
kpsewhich --expand-var '$TEXMFLOCAL' # korzeń lokalnych zmian dla całej instalacji 
kpsewhich --expand-var '$TEXMFHOME' # lokalne nastawy użytkownika

Kolejność wyszukiwania plików jest taka, że najpierw jest przeszukiwane drzewo katalogów o korzeniu $TEXMFHOME a potem $TEXMFLOCAL a na końcu $TEXMFMAIN.

System TeX konfiguruje się edytując plik texmf.cnf. Plik ten można odszukać w następujący sposób:

kpsewhich texmf.cnf

/usr/local/texlive/2011/texmf.cnf

Po zainstalowaniu czegokolwiek w $TEXMFHOME należy wykonać texhash $HOME/texmf.
Po modyfikacji zawartości $TEXMFLOCAL też
należy wykonać texhash (jako root).


wtorek, 6 marca 2012

Simple application of fontspec package

The document body font is Times New Roman-like. Sans serif font is Helvetica-like. Both regular and condensed variant of sans serif is used. With fontspec package it can be obtained with:


\RequirePackage{ifxetex} %%
\ifxetex %% xetex
\RequirePackage{fontspec}
\usepackage{polyglossia} \setdefaultlanguage{polish}
\setmainfont{TeX Gyre Termes}
\setsansfont{TeX Gyre Heros}
\defaultfontfeatures{Mapping=tex-text}
\newfontfamily\PM@SansCondensed{TeX Gyre Heros Cn} %%
\usepackage{xunicode,xltxtra}
\else %% conventional TeX
\RequirePackage{tgtermes,txfonts,qtxmath} %% txfonts
\def\PM@SansCondensed{\fontfamily{qhvc}}
\fi

With the help of \ifxetex command from ifxetex package the code above works when compiled both with xetex as well as conventional pdflatex.

The example below illustrates how \PM@SectionFont can be used to switch to condensed variant of sans serif:


\renewcommand{\section}{\@startsection{section}{1}{\z@}%
{-3.5ex \@plus -1ex \@minus -.2ex}%
{2.3ex \@plus.2ex}%
{\reset@font
\PM@SectionFont
\raggedright}}

Finally, a few words how to configure system (a Linux one, BTW strictly speaking MS Windows is not a system) to work with OpenType fonts.

Providing the TeX Gyre fonts package is installed (with tlmgr in case of TeXLive for example) all .otf files are located in ~/2011/texmf-dist/fonts/opentype/public/tex-gyre (where ~ denotes the root of TeXlive distribution).

To add all TeX Gyre fonts to system resources it suffice to create /etc/fonts/local.conf with the following content:


<?xml version='1.0'?>
<!DOCTYPE fontconfig SYSTEM 'fonts.dtd'>
<!-- /etc/fonts/local.conf file for local customizations -->
<fontconfig>
<!-- Font directory list -->

<dir>/usr/local/texlive/2011/texmf-dist/fonts/opentype/public/tex-gyre</dir>

</fontconfig>

Or similar, if root of TeXlive distribution is not /usr/local/.

Now run as root


fc-cache

Check if everything is OK:


fc-list | grep -i Heros

Information on TeX Gyre Heros should be displayed on screen:


TeX Gyre Heros Cn:style=Bold
TeX Gyre Heros Cn:style=Bold Italic
TeX Gyre Heros:style=Regular
TeX Gyre Heros Cn:style=Regular
TeX Gyre Heros:style=Bold Italic
TeX Gyre Heros:style=Italic
TeX Gyre Heros Cn:style=Italic
TeX Gyre Heros:style=Bold

wtorek, 28 lutego 2012

Titlepage resets the page count

I was not aware that \titlepage command resets page counter. Have no idea why LaTeX works this way but in result \setcounter{page} is ignored no matter where one inserts it in the source code.

It somehow works if \setounter{page} is executed after \begin{titlepage}... (or \maketitle which uses titlepage) but page number for titlepage is always 1.

Worse: definitely LaTeX would be more user-friendly if it would write such brute actions as page counter resets to log file.

Simple fix is to redefine titlepage environment. For example below is a simplified titlepage environment from article.cls:


\renewenvironment{titlepage}
{%
\if@twocolumn
\@restonecoltrue\onecolumn
\else
\@restonecolfalse\newpage
\fi
\thispagestyle{empty}%
%%\setcounter{page}\z@
}%
{\if@restonecol\twocolumn \else \newpage \fi
}

The unwanted \setcounter was commented-out in the code above.

niedziela, 19 lutego 2012

Konwersja DTD na RNC: trang i nXML

Jest coś takiego jak Katalog Polskiej Muzyki Akordeonowej (KPMA), który powstaje przy wykorzystaniu cutting edge technologii: jest redagowany jako plik XML w edytorze strukturalnym.

Na początku KPMA był plikiem TeXowym, później (2002 r.) został przerobiony na XML i odtąd był redagowany w Emacsie, w trybie psgml. Struktura dokumentu była/jest opisana za pomocą stosownego DTD, które psgml potrafi interpretować.

W tzw. międzyczasie tryb psgml stał się obsolete na rzecz nXML. Można wprawdzie dalej używać psgml (działa bez problemów) i być może dałoby się skonfigurować Emacsa, w taki sposób iż dokumenty KPMA byłby redagowane w psgml a inne dokumenty XML w trybie nXML, ale koniec końców zdecydowałem się na zmianę.

Aby zmienić DTD na RNC, wystarczy posłużyć się trangiem:


trang -I dtd -O rnc lkompc.dtd lkompc.rnc

Teraz należy dodać schemat do konfiguracji nXML. Wystarczy w tym celu wczytać plik Kompozycje.xml a następnie wybrać XML→Set Schema→File. Wybrać plik lkompc.rnc. W katalogu z dokumentem XML (tj. Kompozycje.xml w tym konkretnym przypadku) zostanie zapisany plik schemas.xml, zawierający:


<?xml version="1.0"?>
<locatingRules xmlns="http://thaiopensource.com/ns/locating-rules/1.0">
<uri resource="Kompozycje.xml" uri="lkompc.rnc"/>
</locatingRules>

Od tego momentu Kompozycje.xml będzie edytowany z nastawami schematu określonymi w lkompc.rnc.

piątek, 17 lutego 2012

Perl XML:DOM

Plik XML wygląda tak:


<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE lista.kompozycji SYSTEM "lkompc.dtd" >
<lista.kompozycji>

<kompozycja typ="i.orkiestro">
<tytul>Atlantyda I na orkiestrę symfoniczną</tytul>
<xsklad>4 akordeony w orkiestrze</xsklad>
<autor>
<nazwisko>Augustyn</nazwisko>
<imie>Rafał</imie>
</autor>
<rok>1979</rok>
<sklad>4 acc</sklad>
<wydawca>manus</wydawca>
</kompozycja>

...

<kompozycja typ="solo">
<tytul>Rapsodia</tytul>
<xsklad>akordeon solo</xsklad>
<autor>
<nazwisko>Krzanowski</nazwisko>
<imie>Andrzej</imie>
</autor>
<autor>
<nazwisko>Krzanowska</nazwisko>
<imie>Grażyna</imie>
</autor>
<rok>1983</rok>
<wydawca>PWM</wydawca>
<nagranie>KM</nagranie>
</kompozycja>
...

</lista.kompozycji>

a ma wyglądać tak:


<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE lista.kompozycji SYSTEM "lkompc.dtd" >
<lista.kompozycji>

<kompozytor id='Augustyn.R'><!-- *** Augustyn:Rafał# -->

<kompozycja typ="i.orkiestro">
<tytul>Atlantyda I na orkiestrę symfoniczną</tytul>
<xsklad>4 akordeony w orkiestrze</xsklad>
<rok>1979</rok>
<sklad>4 acc</sklad>
<wydawca>manus</wydawca>

</kompozycja>
<kompozycja typ="i.orkiestro">
<tytul>Atlantyda II na wielką orkiestrę i chór</tytul>
<xsklad>4 akordeony w orkiestrze</xsklad>
<rok>1983</rok>
<sklad>4 acc</sklad>
<wydawca>manus</wydawca>
<nagranie>LP</nagranie>
</kompozycja>

</kompozytor>

...

<kompozytor id='Krzanowski.A#Krzanowska.G'><!-- *** Krzanowski:Andrzej#Krzanowska:Grażyna# -->
<kompozycja typ="solo">
<tytul>Rapsodia</tytul>
<xsklad>akordeon solo</xsklad>
<rok>1983</rok>
<wydawca>PWM</wydawca>
<nagranie>KM</nagranie>
</kompozycja>

...

</lista.kompozycji>

To znaczy, że z elementu kompozycja mają zniknąć elementy autor. Wszystkie kompozycje tego samego kompozytora mają być elementami-dziećmi elementu kompozytor. Element kompozytor ma identyfikować kompozytora za pomocą atrybutu id, którego wartość jest wyznaczana (w przypadku gdy dzieło jest ma jednego autora) jako:


nazwisko.inicjał

W przypadku gdy kompozycja jest dziełem zbiorowym, identyfikator kompozytora zbiorowego ma mieć postać:


nazwisko.inicjał#nazwisko.inicjał
nazwisko.inicjał#nazwisko.inicjał#nazwisko.inicjał ...

Powyższe realizuje taki oto skrypt:


#!/usr/bin/perl
use XML::DOM;
binmode(STDOUT, ":utf8");

my $file2parse = $ARGV[0];

my $parser = new XML::DOM::Parser;
my $doc = $parser->parsefile ($file2parse);

for my $kompozycja ( $doc->getElementsByTagName ("kompozycja") ) {
my $author_id = '';

## przeglądamy kolejne elementy autor:
for my $autor ($kompozycja->getElementsByTagName("autor")) {

$im = ($autor->getElementsByTagName("imie"))[0]->toString();
$nz = ($autor->getElementsByTagName("nazwisko"))[0]->toString();

$author_id .= "$nz:$im#"; ## autorów może być dużo stąd .= a nie =
$author_id =~ s/<[^<>]+>//g; ## usuń tagi, zostaw sam tekst

##print STDERR "$author_id\n";

## usuń element autor:
$kompozycja->removeChild($autor);
}

## Hash of Arrays, cf http://docstore.mik.ua/orelly/perl2/prog/ch09_02.htm
push @{ $Kompozycje{ $author_id }}, $kompozycja->toString ();

}

### Druk ############################################################

print "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n";
print "<!DOCTYPE lista.kompozycji SYSTEM \"lkompc.dtd\" >\n";
print "<lista.kompozycji>\n";


for $autor (sort keys %Kompozycje ) {
$autor_i = $autor;
$autor_i =~ s/:([^#:])[^#:]+#/.\1#/g; # tylko inicjały
chop($autor_i);

print "\n\n\n\n<kompozytor id='$autor_i'><!-- *** $autor -->\n\n";
for $kompozycja ( @{ $Kompozycje{ "$autor" }} ) {
print $kompozycja, "\n";
}
print "\n</kompozytor>\n";
}


print "</lista.kompozycji>\n";

## koniec ###

Jeżeli się nie doda binmode, to UTF jest malformed (Ah ten Perl.) Podpowiedź znalazłem tutaj. Nawiasem mówiąc i w innym skrypcie:


s/<imie>([^<>])([^<>]+)<\/imie>/<inicjal>\1<\/inicjal>/gm;

Też zwraca malformed UTF-8 jeżeli np. imieniem jest Łukasz. A jak zaczyna się od A-Z to jest OK.

wtorek, 14 lutego 2012

Dropbox

Zainstalowałem sobie (i Elce też) Dropboksa. Sprytny program i podoba mi się.

Po bezproblemowej instalacji w górnym panelu pojawiła się ikona Dropboksa, po kliknięciu w którą można zarządzać kontem za pomocą nautilusa. Ja po prostu kopiuję pliki z poziomu basha do katalogu ~/Dropbox/, bo tak jest szybciej.

Pliki z katalogu ~/Dropbox/Public/ są dostępny z zewnątrz. Nie jest oczywiste w pierwszej chwili pod jakim adresem, ale można to ustalić empirycznie klikając w ikonę Dropboksa, następnie prawy-klik na pliku→ Dropbox→ Copy Public Link. Wklejamy przez Paste/Wklej oczywiście. Procedura prosta, tyle że klikanie męczy...

Dla plików `epl112_2120369.jpg' oraz `How to use the Public folder.txt' wyszło odpowiednio:


http://dl.dropbox.com/u/61315145/epl112_2120369.jpg
http://dl.dropbox.com/u/61315145/How%20to%20use%20the%20Public%20folder.txt

Co by wskazywało, że URL jest tworzony według schematu: http://dl.dropbox.com/u/id_użytkownika/nazwa_pliku.

niedziela, 12 lutego 2012

Fedora 15: problem z logowaniem

Gdm się uruchamia i tyle. Działa mysz, ale z klawiatury nic się nie wpisze, więc nie da się siłą rzeczy zalogować. Problem pojawił się nagle, nic nie aktualizowałem ostatnio, itp.

Po pierwsze loguję się w trybie tekstowym (runlevel 3). Następnie:

  1. W momencie startu, kiedy system wyświetla na ekranie Boot from ... naciskam klawisz Del. Na ekranie pojawia się menu gruba, np.:


    Fedora (2.6.42.3-2.fc15.i686)
    Fedora (2.6.41.10-3.fc15.i686)
    Fedora (2.6.41.9-1.fc15.i686)
  2. Teraz wybieram wersję systemu (strzałkami góra/dół) i naciskam e. Pojawia się menu zawierające (przykładowo):

    root (hd0,0)
    kernel /boot/vmlinuz-2.6.42.3-2.fc15.i686...
    initrd /boot/initramfs-2.6.42.3-2.fc15...
  3. Strzałkami wybieram wiersz zawierajacy słowo vmlinuz, naciskam znowu e i dopisuję 3 na końcu wiersza. Naciskam Enter, a potem b (boot).

Doinstalowuję kdm:


yum install kdeutils-libs kdeutils kdm

Byłem uprzejmy przy instalacji FC15 kdma usunąć, bo jego obecność wymaga zainstalowania m.in. programu (demona) gpsd, który z kolei -- jeżeli zostanie uruchomiony -- gryzie się z -- intensywnie wykorzystywanym przeze mnie -- programem gspbabel. No więc skoro się gryzie i skoro nie jest mi do niczego nie potrzebny, to go wywaliłem, ale być może to był błąd. (Inna sprawa że zależność pomiędzy menedżerem logowania a programem do obsługi urządzeń GPS wydaje się czymś, hmmm... absurdalnym.)

Teraz reboot i wszystko działa.

Podobno plik /etc/sysconfig/desktop deklaruje menedżera logowania oraz typ środowiska graficznego. Zajrzałem do środka /etc/sysconfig/desktop:


less /etc/sysconfig/desktop
DESKTOP="KDE"
DISPLAYMANAGER="KDE"

Programy →Administracja→Narzędzie przełączania środowisk. Było KDE, ustawiłem na Xfce. Po restarcie:


less /etc/sysconfig/desktop
DESKTOP="KDE"
DISPLAYMANAGER="KDE"

Hmm..., jakby nic się nie zmieniło. Ale to co widzę na pulpicie to na oko Xfce a nie KDE.

Dokumentacja Fedory określa, że wartościami dla DESKTOP mogą być tylko GNOME lub KDE. Widocznie zmiana środowiska jest dokonywana w inny sposób a zawartość /etc/sysconfig/desktop jest (częściowo) ignorowana.

Pozostaje pytanie: czemu rozjechał się GDM?

czwartek, 9 lutego 2012

Where they came from?

Google fusion tables another excercise.

Two data sets describe football players who plays in Polish t-Mobile ekstraklasa (1st division) and Pierwsza Liga (2nd division) in 2011/2012 (autumn).

To show from where the player came a straight line is drawn from a player's birthplace to club's stadium, the player plays for.

Figure 1. 1st division.

Figure 2. 2nd division.

Players from 2nd division seems to be born closer to the clubs they play for:-)

Warning: in considerable number of cases the geocoding as performed by Google maybe wrong due to poor data quality--have no time to check/correct.

Raw data are available here: div#1 and div#2.

wtorek, 7 lutego 2012

Using ffmpeg for cutting media files

As simple as:


ffmpeg -ss start-time -t duration -i file-in file-out

Usually start-time/stop-time are given so duration have to be computed. Nothing difficult but the following bash script calculates duration for us:


#!/bin/bash
# cnt_sec function converts string `hh:mm:ss' to seconds, both
# `hh' and `mm' are optional
function cnt_sec () {
echo $1 | awk -F":" '{ if (NF>2) { sec += 60*60 * $(NF-2) } ;
if (NF>1) { sec += 60 * $(NF-1) } ;
if (NF>0) { sec += $NF } ;
print sec }'
}

STRT_TIME=`cnt_sec $1`
STOP_TIME=`cnt_sec $2`

DURATION=$((STOP_TIME-STRT_TIME))
echo $DURATION
# cut from file $3 from $1 to $2 write to $4
# both $1 and $2 are time durations in `hh:mm:ss' format
ffmpeg -ss $1 -t $DURATION -i $3 $4

poniedziałek, 6 lutego 2012

Google Fusion Tables map rendering issue?

Yet another excercise, which tests Google Fusion Tables.

The data set contains--among other things--birth place for 600+ rugby players who last year take part in Rugby World Cup in New Zealand. The raw data is available here and here.

On the following diagram (cf. Figure 1) the players are mapped by column containing birthplace coordinates

Figure 1. World's concentration of top Rugby Union players.

The map do not show which player plays for which country. To show that a straight line is drawn from each player's birthplace to the country's capital, the player plays for (cf. Figure 2).

Figure 2. The origin of top Rugby Union players by federation.

Some lines look strange and the problem is particularly evident around New-Zealand-Samoa-Tonga-Fiji. For example it seems that many Samoan players were born at high ocean (cf. Figure 3).

Figure 3. The origin of top Rugby Union Samoan players.

BTW mapping Samoans one-by-one is OK (try it). The problem is when all rows are mapped together by Visualize→Map function.

Accidentaly around 600 miles to the East of New Zealand lies antipodal meridian ie. a meridian which is diametrically opposite the Greenwich meridian (a pime one). The longitude of points lying on antipodal meridian can be referenced (at least in GoogleMaps) both as -180° or 180° (ie. -36,-180° and -36,+180° refers to the same place). Perhaps it is the cause of observed errors...