sobota, 13 grudnia 2008

The Solvency Crisis

Czyli problem wypłacalności:

Until last summer, serious people were marveling that credit was cheap because the world, oddly enough, enjoyed a ``savings glut,'' as Fed Chairman Ben Bernanke put it. Despite the huge demand for credit from China, India, private industry, American consumers and the U.S. government, unlimited credit was somehow on offer at low interest rates.

But now we know what really occurred. Banks were increasingly moving loans off their books by creating exotic bonds. By selling off those bonds, they could use the proceeds to make more loans.

In effect, the private financial system was printing money, operating beyond regulatory constraints (which limit the ratio of loans to bank capital.) Because these loans were sold, they were unlimited. But the newly minted ``money'' was only as good as its collateral.

Once investors began examining that collateral -- a murky stew of sub-prime mortgages, high-risk credit card debt, used car loans, and other exotic securities created to insure these dubious bonds -- they saw a financial house of cards. As confidence collapsed with falling housing prices, so did the credit system.

Czyli klasyczna piramida finansowa: kręci się dopóki mało kto się połapał jak działa. Powyższy fragment jest przedrukiem z tekstu Roberta Kuttnera. Zwracam uwagę na datę publikacji: grudzień 2007. Teraz skoro to jest problem wypłacalności (a nie płynności czy braku zaufania banków do siebie, jak niektórzy ``eksperci'' usiłują to przedstawić publiczności), to kuracja pn. obniżanie stóp procentowych banków centralnych nie leczy choroby tylko odracza zgon o czas jakiś... Proste jak metr sznurka.

środa, 26 listopada 2008

Uwaga: będą unowocześniać polskie bibiloteki

,,Gazeta Wyborcza'' pod bombastycznym tytułem Bill Gates unowocześni polskie biblioteki sprzedaje takie oto przesłanie: rząd Tuska ze współzałożycielem Microsoftu Billem Gatesem chcą zmienić umierające biblioteki w centra kultury na miarę XXI wieku. No brawo można by powiedzieć... [Uwaga na boku: jak czytam, że Rząd Tuska z Gatesem, to przypomina mi się stary żydowski dowcip: -- rozmawiałem z gubernatorem, -- i co, i co ci powiedział?, -- paszoł won jewrej; tu jest inna wersja). Koniec uwagi].

Wracając ad rem. Primo co niby ma oznaczać centra kultury na miarę XXI wieku? Tyle, że kupią i wstawią komputery z niesławną Vistą? Po drugie zaś primo fundacja Mr. Gatesa stawia sprawę jasno: We're funding pilot programs and grants to purchase hardware. Our partner, Microsoft, donates software if the country requests it. (cytat ze strony fundacji dot. programów bibliotecznych)

Tekst z GW, który napisała niejaka Renata Grochal (dziennikarz na miarę XXI w. z gazety na miarę XXI w.?) został oczywiście powielony za gazeta.pl na różnych onetach, wirtualnych-polskach itp. ,,serwisach''. BTW kiedyś żeby ,kłamstwo powtarzane wielokrotnie stało się prawdą'' potrzeba było ministerstwa propagandy i ,,trzymania za twarz'' mediów (żeby powtarzały). Dziś każda bzdura pojawia się wszędzie powielona miliony razy. Reichsminister byłby zachwycony możliwościami Internetu-:(

Kończąc mam nadzieję, że omawiana propozycja rządowa skończy podobnie jak poprzednie, tj. wybory przez Internet, rozliczenia podatków osobistych przez Internet czy rozdawanie dzieciom laptopów.

wtorek, 25 listopada 2008

Super/subskrypt w CSS

Poniższe nastawy powodują złożenie fragmentu tekstu odpowiednio w superskrypcie i subskrypcie.


.superscript{font-size:xx-small; vertical-align:top;}
.subscript{font-size:xx-small; vertical-align:bottom;}

Nowe odnośniki do innych blogów, umieszczone po lewej stronie (w wersji ,,statycznej'' bloga umieszczone są w pliku index.html), zawarte wewnątrz <span>, np:


<span class='new_blog_entry'><a href="http://norman.walsh.name/">N. Walsh</a></span> |

mają być wyświetlane krojem pochyłym (kursywą) oraz po linku ma być umieszczany w superskrypcie napis [new] (tak to sobie wymyśliłem). Do osiągnięcia powyższego służy następujący fragment arkusza CSS:


.new_blog_entry { font-style: italic }
.new_blog_entry:after { content : "[new]" ; font-size:xx-small; vertical-align:top; }

Dopisane 26 listopada 2008: Nie jest chyba specjalnym zaskoczeniem, że w przeglądarce IE f-m MS (wersja 7) powyższe nie działa. Żałosne...

poniedziałek, 24 listopada 2008

Poprawianie plików PDF w edytorze Emacs

Opisany wcześniej skrypt uruchamiam ,,spod'' Emacsa działającego w trybie BibTeX. Konkretniej poniższa funkcja bibtex-adjust-pdf-filename pobiera wartości pól author, title, year oraz tp:keywords, a następnie przekazuje te wartości w postaci argumentów ww. skryptu uruchamianego jako polecenie systemowe. Mam nadzieję dzięki temu mieć większy porządek w przechowywanych dokumentach pobranych z różnych archiwów elektronicznych.


(defun bibtex-adjust-pdf-filename (file)
"Dla bieżącego rekordu bibtexa modyfikuje plik zawierający relewantny dokument PDF
(dodaje co trzeba do słownika Info oraz modyfikuje nazwę). Oryginalna nazwa pliku
PDF jest podana z minibufora. Modyfikacja jest dokonywana przez zewnętrzny skrypt.
Cała ta procedura jest po to żeby można łatwiej później odszukać plik na dysku...."
(interactive "fNazwa pliku: ")
(save-excursion
(bibtex-beginning-of-entry)
(let* ( (author (bibtex-text-in-field "author"))
(year (bibtex-text-in-field "year"))
(keywords (bibtex-text-in-field "tp:keywords"))
(title (bibtex-text-in-field "title"))
(command (format "%s -rename -f \"%s\" -t \"%s\" -a \"%s\" -k \"%s\" -y \"%s\""
(executable-find "pdf_set_info.pl") ;; script name
(expand-file-name file) title author keywords year)) )
(progn (shell-command command)
(previous-line)
(beginning-of-line)
(insert (concat "%% patched with pdf_set_info.pl %%" ))))))

Przy okazji namiar na bloga anonimowego użytkownika Emacsa zawierającego parę ciekawych rzeczy.

niedziela, 23 listopada 2008

Pdftk

PdfTk nie ma w zasobach fc8. W nowszych dystrybucjach też nie ma z uwagi na restrykcyjną licencję (znalazłem -- podobno działajacy -- rpm dla fc9 na stronie Gregory R. Kriehna, ale ja używam ciągle fc8). Nie idzie też tego skompilować: błąd zgłaszany przez gcj. Z opisu wynika, że sprawa jest trudna, bo pdftk jest źle zakodowany (I think all of us were amazed that it ever worked. That it did was by accident.:-)

Głupia sprawa... bo to przydatna aplikacja. Potrzebowałem akurat narzędzia do zmiany wpisów w słowniku Info plików PDF (pola Title, Author itp.). Znalazłem inne rozwiązanie wykorzystujące perlowy pakiet PDF::API2.

Najpierw instalacja (był dostępny w repozytoriach yuma):


yum install yum install perl-PDF-API2

Skrypt jest banalny:


#!/usr/bin/perl
use PDF::API2;
use Getopt::Long;

my $USAGE = "*** pdf_set_info -t title -k keywords -a author -f file ***\n";

GetOptions( 't=s' => \$title, 'a=s' => \$author, 'k=s' => \$keywords,
'f=s' => \$file, );

unless ($file) { print STDERR $USAGE; exit }

$pdf = PDF::API2->new;
$pdf = PDF::API2->open($file) || die "*** Problems opening $file ****";

%H = $pdf->info;
if ( $H{'Title'} ) {
print STDERR "**** Original title: $H{'Title'} ****\n";
if ($title) { $title .= " ($H{'Title'})" ; }
}

## Modyfikacja:
if ($title) { $H{'Title'} = $title }
if ($author) { $H{'Author'} = $author }
if ($keywords) { $H{'Keywords'} = $keywords }

unless ($title || $author || $keywords) { print STDERR $USAGE; exit }
%H = $pdf->info( %H );
$pdf->update;

Uruchomienie:


./pdf_set_info.pl -t tytuł -a autor -f słowa-kluczowe -f plik.pdf

Tytuł jest dodawany do tego co już jest w pliku PDF. Nie jest nadpisywany. Autor/Słowa kluczowe są nadpisywane. Uwaga: pakiet PDF::API2 nie jest mi bliżej znany, zatem trzeba uważać czy po zmianie Info plik PDF dalej da się oglądać.

piątek, 21 listopada 2008

Nowy rower MTB

Kupiłem rower MTB mając w tym temacie niewielkie doświadczenie, bo dotąd jeździłem wyłącznie rowerami szosowymi. Dzięki uprzejmości kol. kol. Bogusia L. i Daniela M. mogłem popróbować jazdy i przymierzyć się do roweru MTB. Jeden rower miał 21 calową ramę, był dość wiekowy i miał sztywny widelec. Drugi model jest nowszy -- ma amortyzator ale bez blokady skoku. Po kilku jazdach stwierdzam, że amortyzator mi niepotrzebny--wręcz przeszkadza.

Kupiłem rower 30 października w sklepie M. Szerszyńskiego w Sopocie. Zdecydowałem się na Authora Traction; zamiast amortyzatora miał być widelec sztywny. Nie chciałem ojca uczyć dzieci robić, więc nie uzgadniałem dalej co-i-jak. Rezultat nie był najlepszy: rower został wyposażony w zwykły widelec Cro-Mo, niedopasowany zupełnie do ramy.

Istnieje mianowicie coś takiego jak skok amortyzatora (ang. travel fork). Jak rozumiem jest to odległość pomiędzy amortyzatorem maksymalnie dociśniętym, a pozycją normalną. Skoki w rowerach MTB zaczynają się od 80mm. Z tego powodu koło przednie w rowerze MTB z amortyzatorem jest znacznie niżej, tj. odległość między górną krawędzią widelca a kołem jest większa niż w typowym rowerze z widelcem sztywnym. Jest większa bo się zmienia -- w maksymalnym docisku pewnie jest taka sama.

Oryginalnie Traction ma amortyzator ze skokiem 100mm i kształt ramy jest do tego dopasowany. Wstawienie zwykłego widelca o krótkich widełkach (ang. blades) dało wynik hmmm... dziwny. Rower ,,opadł'' do przodu, co zostało skompensowane monstrualną liczbą podkładek pod kierownicę. Rower wyglądał jak na pierwszym zdjęciu obok. Po pierwszej jeździe wróciłem jakbym skończył Paryż-Roubaix.

Teraz sprawy potoczyły się szybko. Wykonałem kwerendę w google, allegro i ebay na okoliczność widelcy sztywnych MTB ze szczególnym uwzględnieniem karbonowych (A co!). Widelcy metalowych o jasno podanej specyfikacji określającej długość widełek jakoś nie znalazłem. Natomiast karbonowe jak najbardziej. Klasycznie wyglądające są drogie, często tylko dla hamulców dyskowych (disc only) i także często mniejsze. Np. znalazłem na Allegro widelec Token o długości od dolnej krawędzi korony do środka piasty 415mm. Fakt, że lekki 465 g. Inny znaleziony to na Allegro f-my Boplight: długość widelca 42cm (do końca nie wiadomo co to oznacza), waga 960 g, cena 600 PLN. Mógłby ew. się nadać...

Są też widelce wyglądające jak amortyzatory: tj. duża korona i widełki przypominające golenie. Z karbonu są tylko golenie. W sklepie sugerowano taki widelec Accenta o długości 445 mm, ale ponieważ miał gołe te golenie, to do hamulców V-break należało dokupić odpowiednie adaptery. Całość 750 PLN...

Znalazłem na ebay tego typu widelce firmy eXotic. Ponieważ to jest widelec więc lepiej nie kupować byle czego ale są na blogach relacje usatysfakcjonowanych klientów (np. tu albo tutaj), na flickr.com też są zdjęcia od ludzi, którzy na tym jeżdżą. Można wybrać długość widelca w zależności od geometrii ramy -- dla ram z amortyzatorem o skoku 100mm sugerowany jest widelec o długości 445 mm (od od dolnej krawędzi korony do środka piasty). Kupiłem taki 445 mm za około 400 PLN, z dostawą z UK zapłaciłem nieco poniżej 500 PLN.

Kupiłem w środę wieczorem 5 listopada, paczka przyszła 12-tego. Pewnie byłoby jeszcze szybciej ale 11 było święto a 10 wigilia-święta-po-niedzieli więc kto by w ten dzień pracował. Kolejne zdjęcie obok pokazuje różnicę pomiędzy widelcem ,,zwykłym'' a widelcem eXotic 44,5. W piątek z pomocą kol. Rysia wymieniliśmy widelce a rower z nowym widelcem widać na trzecim zdjęciu obok. Od razu lepiej--nie ma tego frajerskiego komina podkładek pod kierownicą... (A poniżej jeszcze parę fotek dotyczących tematu.)

Po zamianie widelca rower waży 12,2 kg (z błotnikiem). Według specyfikacji Traction dla ramy 19" (ja mam 21") ma ważyć 13,2 kg. Author Modus kol. Pawła, też według specyfikacji ma ważyć 11,8 kg. Trzeba będzie przy okazji sprawdzić.

Aha, zamierzam jeszcze zmienić kierownicę na lekko giętą, ale to już bez pośpiechu.

Author Traction with stiff carbon fork
Poprawiony Traction -- widok z boku

Author Traction with stiff carbon fork
Poprawiony Traction -- widok z przodu

Dopisane 26 listopada 2008: Kierownica do tego roweru ma średnicę 25,4 mm a sztyca 31,6 mm. Trzon widelca 28,6 mm. To tak pro memoria, na wypadek gdybym chciał zmieniać a nie mógł znaleźć suwmiarki (dziś mi się to udało po dłuższych poszukiwaniach).

Dopisane 20 grudnia 2008: Tak jak zamierzałem, kierownicę wymieniłem na lekko (20mm) giętą Ritchey WCS Rizer (120 PLN z wysyłką) i mostek na Easton EA50 110mm (używany z Allegro, 43,50 PLN). Kierownica, która oryginalnie miała 66 cm została obcięta na szerokość 60 cm. Nie lubię szerokich kierownic. Wysokość kierownicy podniosła się trochę (20 mm), a mostek skrócił rower o 1cm. Teraz jest dużo lepiej...

Dokupiłem też pedały PD-M540 (110 PLN z wysyłką); stare było funkcjonalnie OK, tj. trzymały, ale łożyska były niemiłosiernie luźnie i dzwoniły przeraźliwie. Nb. nowe pedały ważą 350 g a stare były ciut cięższe: 410 g.

Będąc od zawsze użytkownikiem liczników Cateye dokupiłem też Cateye Enduro 8 (97 PLN z wysyłką).To nie koniec modyfikacji: na allego kupiłem używaną korbę XT, kasetę/łańcuch XT oraz całkiem fajne koła na obręczach Mavica 317 z piastami LX. Korby/kół jeszcze nie założyłem W sumie z oryginalnego Author Traction niewiele już zostało:-), ale nie strachu--co odpada z mojego pójdzie do roweru Miśka (koła, korba itp).

środa, 12 listopada 2008

130 tysięcy przebiegu

Z powodu awarii wynikłej z działalności MSNBota z pewnym opóźnieniem odnotowuję historyczne wydarzenie, a mianowicie, że łączny udokumentowany dystans przejechany na rowerze przeze mnie to 130,000 km. Było to dokładnie 7 listopada br.

MSNbot

Administrator gnu.univ.gda.pl, czyli kol. Wanted Sochacki zablokował dostęp do http://gnu.univ.gda.pl/~tomasz/wblog z powodu obciążenia systemu spowodowanego indeksowaniem zawartości przez MSNbota. Zwrócił też uwagę, że dla tego bota nazbyt trudne mogą być URLe generowane w zestawieniu tagów (lewy/górny róg strony, pod zdjęciem) oraz pod każdym wpisem po słowie tagi:.

Oryginalnie linki te są tworzone tak, że kliknięcie w link taga zwracało dokument, w którym tenże tag był dodany do każdego linka w zestawienia tagów i do każdego linka pod każdym wpisem. Wyglądało to jakoś tak:


http://gnu.univ.gda.pl/~tomasz/cgi-bin/blosxom.cgi?-tags=docbook,mplayer,kolibki

Co oznaczało, że wyświetlone mają być dokumenty zawierające albo docbook albo mplayer albo kolibki. W następnym kliku można było dodać następnego taga itd... Reset listy tagów w URLu następował po wybraniu taga już znajdującego się na liście. IMHO ww. sposób działania niewątpliwie generuje dużo, i w znakomitej większości zbędnych linków. [Ale -- dalej IMHO -- nie generuje nieskończonej liczby URLi ani nie tworzy pętli.]

Najbardziej oczywiste dla mnie rozwiązanie, tj. zarąbać szkodliwego a bezużytecznego intruza (parafrazując Knutha, [TeXBook, s. 299]: If you have been so devious as to use MSN, [...] you will deserve no sympathy (w oryginale chodziło o komunikat o błędzie w systemie TeX:-), nie o MSN):


# msn search bot
User-agent: msnbot
Disallow: /

z niejasnych dla mnie przesłanek zostało określone przez Kol. Wanteda jako pochopny krok. Skoro tak, to nie było innego wyjścia jak zmodyfikować sposób działania blosxom.cgi.

Żeby link do taga zwracał dokumenty zawierające ten tag, bez modyfikowania linków innych tagów zmieniłem kod wtyczki tagging w następujący sposób:

$global_tag_list .=  qq|                '' : ''). ##!!! bez ,,rekursji'' !!!
]]>

Wydaje się, że działa

sobota, 1 listopada 2008

Stójka

Stójka na rowerze. Żeby się nie przewrócić trzeba ustawić korby poziomo i skręcić kierownicę w stronę nogi wysuniętej do przodu. No i trzeba wstać z siodła, bo wtedy można balansować ciałem. Wystarczy wpisać na flickr.com track stand i można zobaczyć przykłady (jeden jest reprodukowany obok).

Formatowanie elementu optional (w Docbook XML)

W nazwiązaniu do poprzedniego wpisu. W dokumencie o XPath pojawia się taki oto fragment:

oś::test<optional>[predykat]*</optional>

Co ma oznaczać, że wyrażenie ścieżkowe XPath składa się z  osi i testu oraz opcjonalnego predykatu, który może być powtórzony wielokrotnie (stąd *). Teraz standardowo szablony XSL Docbook (aka XSLDB) zamieniają ww. fragment XML na coś takiego:

oś::test[[predykat]*]

Niezręczność polega na tym, że nawiasy kwadratowe raz są używane do oznaczania części opcjonalnej a raz oznaczają, że należy je wstawić literalnie. W XSLDB znaki wstawiane wokół elementu optional są sparametryzowane -- są to mianowicie: arg.choice.opt.open.str oraz arg.choice.opt.close.str. Zamiast `[' i `]' zdecydowałem się na U+27E8 (Mathematical left angle bracket) oraz U+27E9 (Mathematical right angle bracket) Teraz próba uruchomienia:

xsltproc --stringparam arg.choice.opt.open.str "&#x27e8;" \
--stringparam arg.choice.opt.close.str" select="&#x27e9;" ...

Kończy się błędem basha... Ciekawe czemu? Można podać ww. znaki binarnie -- wtedy wszystko działa. Ale UTF-8 w Makefile? Miałem opory, dodałem więc do arkusza uruchamiającego transformację XML → XHTML:

<xsl:param name="arg.choice.opt.open.str" select="'&#x27e8;'" />
<xsl:param name="arg.choice.opt.close.str" select="'&#x27e9;'" />

Teraz omawiany fragment wygląda mniej dwuznacznie:

oś::test⟨[predykat]*⟩

BTW w trybie nxml wpisanie &#x27e8; powoduje, że automagicznie kształt znaku pojawia się za średnikiem (ale nie jest wstawiany do tekstu -- po prostu jest to podpowiedź Emacsa, jak wygląda kształt znaku.) Dodatkowo po najechaniu myszą na encję wyświetlana jest nazwa znaku (w oknie podpowiedzi zwanym tooltip). Te ułatwienia są fajne w środowisku jednobajtowym--a ja póki co używam jako domyślnego kodowania ISO-8859-2.

Przy okazji użyteczne zestawienie znaków Unicode -- odpowiedników różnych TeXowych symboli matematycznych. Wystarczy zaznaczyć myszą i wkleić do Emacsa a następnie C-x = (what-cursor-position) wyświetli co zacz, w tym numer znaku.

SVG, Docbook i Firefox

Zaczęło się od tego, że chciałem wstawić ilustrację w formacie SVG do dokumentu redagowanego w Docbooku. Jakoś tak:

<figure id='r1' >
<title>Osie (środkowy węzeł <literal>p</literal> jest węzłem kontekstowym)</title>
<mediaobject >
<imageobject>
<imagedata width='90%' format="SVG" fileref="document-axes.svg" />
</imageobject>
</mediaobject>
</figure>

W pliku PDF wygenerowanym FOPem ilustracja wygląda OK. W dokumencie HTML oglądanym w FF 2.0.0.16 wygląda dziwnie: wyświetlany jest tylko fragment rysunku a z boku pojawia się pasek do przewijania (scrollbar). I nie idzie tego się pozbyć...

Zaktualizowałem zatem Firefoxa do wersji 3.0.3. Teraz rysunek jest wyświetlany prawidłowo. Opera 9.27 nie pokazuje go wcale, ale jeżeli pominie się atrybut width, to rysunek jest wyświetlany prawidłowo. Skoro tak to wymyśliłem sobie coś takiego:

<figure id='r1' >
<title>Osie (środkowy węzeł <literal>p</literal> jest węzłem kontekstowym)</title>
<mediaobject >
<imageobject>
<imagedata width='90%' format="SVG" fileref="document-axes.svg" />
</imageobject>
<caption condition='html'><para>Na wypadek gdyby powyższy rysunek
był niewidoczny tu jest wersja <ulink url="document-axes.png">w formacie PNG</ulink>
</para></caption>
</mediaobject>
</figure>

Powyższa uwaga w pliku PDF jest bez sensu. Na szczęście łatwo się go pozbyć, bo w Docbooku zaimplementowano warunkowe przetwarzanie dokumentu (profiling). Następujące kilkanaście atrybutów może być używanych do tego celu:

Nazwa atrybutu Opis Parameter XSL
arch Computer or chip architecture, such as i386. profile.arch
audience Intended audience of the content, such as instructor. profile.audience
condition General purpose conditional attribute, with no preassigned semantics. profile.condition
conformance Standards conformance, such as lsb (Linux Standards Base). profile.conformance
lang Language code, such as de_DE. profile.lang
os Operating system. profile.os
revision Editorial revision, such as v2.1. profile.revision
revisionflag Revision status of the element, such as changed. This attribute has a fixed set of values to choose from. profile.revisionflag
role General purpose attribute, with no preassigned semantics. Use with caution for profiling. profile.role
security Security level, such as high. profile.security
status Editorial or publication status, such as InDevelopment or draft. profile.status
userlevel Level of user experience, such as beginner. profile.userlevel
vendor Product vendor, such as apache. profile.vendor
wordsize Word size (width in bits) of the computer architecture, such as 64bit. Added in DocBook version 4.4. profile.wordsize

Teraz po wpisaniu <caption condition='html'> ... </caption> do dokumentu należy uruchomić procesor XSLT z odpowiednią wartością parametru (podanego w trzeciej kolumnie tabeli). Mówiąc konkretnie:


## Transformacja za pomocą xsltproc xml2xhtml
xsltproc --stringparam chunker.output.doctype-public "-//W3C//DTD XHTML 1.0 Strict//EN" \
--stringparam chunker.output.doctype-system http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd" \
--stringparam profile.condition "html" -o plik.xhtml szablon.xsl plik.xml

## albo za pomocą procesora saxon:
saxon -o plik.fo plik.xml szablon.xsl profile.condition="pdf"

Do tego zamiast standardowego arkusza XSL-ROOT/xhtml/chunk.xsl (XSL-ROOT oznacza katalog główny dystrybucji arkuszy XSL Docbook) należy w przypadku zamiany na XHTML uruchomić XSL-ROOT/xhtml/profile-chunk.xsl. Podobnie zamieniając XML na FO/PDF należy uruchomić XSL-ROOT/fo/profile-docbook.xsl zamiast XSL-ROOT/fo/docbook.xsl. Oczywiście ww. arkusze są uruchamiane pośrednio, poprzez arkusz dopasowujący nastawy XSL Docbook do moich potrzeb. Początek tego arkusza wygląda zatem następująco:

<xsl:stylesheet 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns="http://www.w3.org/1999/xhtml"
version="1.0" >
<xsl:import href="/usr/local/sgml/stylesheets/xmldocbook/1.72.0/xhtml/profile-docbook.xsl"/>
<!-- itd ... -->

Teraz jest tak: plik PDF jest OK. Plik XHTML nie do końca--nie widać wpisu Na wypadek gdyby powyższy rysunek.... Zasłania go rysunek; co ciekawe identycznie wygląda to w Firefoksie i Operze (tzn. identycznie nic nie widać). Relewantny fragment pliku XHTML wygląda następująco:

<div class="figure">
<a id="r1"></a> <p class="title">
<b>Rysunek 1. Osie (środkowy węzeł <code class="literal">p</code> jest węzłem kontekstowym)</b> </p>
<div class="figure-contents">
<div class="mediaobject">
<object data="document-axes.svg" type="image/svg+xml" width="90%"/>
<div class="caption">
<p>Na wypadek gdyby powyższy rysunek był niewidoczny tu jest wersja
<a href="document-axes.jpg">w formacie JPG</a> </p>
</div> </div> </div> </div>

Jeżeli się wstawi element object do elementu p, to tekst się pojawia... Ale żeby object był wewnątrz akapitu to trzeba zmienić relewantne szablony XSL Docbook; w tym przypadku nie aż tak trywialne zadanie... Poddałem się i uwagę dodałem w formie akapitu pod pod rysunkiem. Ostatecznie wygląda to tak.

Dopisane 2 listopada 2008: Wzmiankowany dokument wyświetla się w programie Exploder czy jakoś tak, tzw. czołowej firmy zupełnie kuriozalnie, mianowicie do połowy (tj. do rysunku). W związku z tym nawet ostrzeżenie: Na wypadek gdyby powyższy rysunek był niewidoczny tu jest wersja... nie jest wyświetlane, ani link do pliku PNG, ani nic po rysunku. Ci to zawsze potrafią zaskoczyć.

Firma owa uparła się bowiem ignorować standardy a wciskać na siłę swoje szajsowe rozwiązania typu VML czy jakiś EMF. Ich sprawa...

niedziela, 26 października 2008

Projektowanie schematów XSD w edytorze Emacs

Można używać nxml-mode do tworzenia schematów XSD. To odkrycie jest wynikiem szukania edytora/IDE ułatwiającego projektowanie Schemy. Oczywiście jest XMLSpy ale tylko dla MSW. Jest też jakiś moduł do netBeans, którego nie próbowałem... Niezbędny dla działania nxml-mode schemat do schemy w formacie RNG/RNC jest dostępny ze strony www.relaxng.org. W związku z tym odkryciem zmieniłem konfigurację emacsa:


(load "rng-auto.el")
;; http://www.emacswiki.org/emacs-en/NxmlMode
(add-to-list 'auto-mode-alist (cons (concat "\\."
(regexp-opt '("xml" "xsd" "rng" "xslt" "xsl" "svg" "rss") t) "\\'")
'nxml-mode))

Należy teraz ,,zarejestrować'' schemat do schemy w pliku konfiguracyjnym pakietu nxml-mode (schema/schemas.xml):


<uri pattern="*.xsd" typeId="XML Schema"/>
<namespace ns="http://www.w3.org/2001/XMLSchema" typeId="XML Schema"/>
<typeId id="XML Schema" uri="xmlschema.rnc"/>

Oryginalny schemat powoduje błąd: regular expression too big in xmlschema.rnc. Na tej stronie jest to dokładnie opisane i jest udostępniony plik .diff, tyle że nie byłem w stanie go zastosować uruchamiając patch. Poprawiłem plik ręcznie. Nie ma 100% gwarancji, że poprawka jest OK, ale dla kilku schematów nxml-mode działał poprawnie, więc szanse są, że tak jest. Poprawiony plik .rnc jest tutaj

Teraz wszystkie pliki XML (w tym szablony XSLT oraz schematy XSD) mogę edytować w trybie nxml (dowód w postaci zrzutu ekranu obok).

poniedziałek, 13 października 2008

Kopia zapasowa i rsync

Z myślą głównie o zdjęciach, których zbiór się rozrósł niebywale kupiłem dysk USB pn. My Book firmy Western Digital o pojemności 500 Gb. Ponieważ pierwsza próba kopiowania plików na ww. dysk skończyła się komunikatem, że plik już istnieje, co by wskazywało na Windziany system plików, sformatowałem go poleceniem:

/sbin/mkfs.ext3 /dev/sdb1


Teraz z kolei, zwykły użytkownik nie ma uprawnień do zapisu.
Pomogło wpisanie do /etc/fstab:




/dev/disk/by-id/usb-WD_5000AAV_External_57442D574341535535303634313031-0:0-part1 \
/media/external-disk ext3 noauto,user,rw 0 0

Do zrobienia kopii uruchamiam rsync:


rsync -avh --delete --exclude-from=/home/tomek/.rsync/exclude \
/home/tomek/ /media/external-disk/PC/tomek/
rsync -avh --delete --exclude-from=/home/eros/.rsync/exclude \
/home/eros/ /media/external-disk/PC/eros/

Uruchamiam powyższe jako root (w dokumentacji piszą żeby tego unikać, ale znalazłem też opinie przeciwne: Running rsync as root is perfectly fine. Consider this: your mail daemon is running as root all day, everyday.), bo inaczej kopiowanie kończy się komunikatem o błędzie. Format pliku ~.rsync/exclude ustaliłem empirycznie konsultując się z dokumentacją (na blogach dotyczących rsynca są proponowane prostsze formaty, ale u mnie nie chciały one działać):


- /Dist/**
- /.mozilla/**
... itd ...

Należy uważać przy korzystaniu z opcji --delete (por. wpis tutaj) i zwrócić uwagę na różnicę pomiędzy rsync dir dir2rsync dir/ dir2/.

Drugą kopię chcę zrobić na DVD. W tym wypadku archiwum nie wejdzie w całości i trzeba je podzielić na kawałki:


tar -cz katalog | split -d -b 1150m - archiwum.tgz && \
md5sum archiwum.tgz.* > archiwum.md5

Powyższe podzieli na kawałki wielkości 1,15Gb, które później mogą być nagrywane po 4 na DVD. Plik archiwum.md5 będzie zawierał sumy kontrolne. Scalenie i rozpakowanie wyglądałoby zaś następująco:


md5sum -c archiwum.md5 && cat archiwum.tgz.* | tar -xz

Jeszcze uwaga nt. strategii... starsze zdjęcia oraz pliki mp3, pdf itp... umieszczam w /cmn/. Ten katalog ,,robi'' za ,,wstępne'' archiwum. Kopiuję jego zawartość na USB/DVD, a to co jest niepotrzebne (np. zdjęcia z 2006 r.) sukcesywnie usuwam. Z tego względu:


rsync -avh /cmn/ /media/external-disk/PC/cmn/

Bez opcji --delete, bo to by spowodowało usunięcie plików z dysku USB.

sobota, 11 października 2008

Stłucz pan termometr, nie będziesz miał pan gorączki

Tytuł wpisu to cytat z Lecha Wałęsy aka dobra narodowego, który kiedyś w taki bezczelny sposób odpowiedział Andrzejowi Wielowieyskiemu. Dziś przeczytałem wpis na blogu Marka Shuttlewortha dotyczący globalnego kryzysu finansowego. Dla przypomnienia MS jest bardzo bogatym człowiekiem więc w temacie ekonomii ma jak to się mówi zweryfikowaną emirycznie wiedzę ekspercką (w przeciwieństwie do różnych pseudoekspertów z tytułami przed nazwiskiem) a do tego jest sponsorem projektu Ubuntu. Co pisze MS każdy może sobie przeczytać więc streszczać nie będę, przytoczę tylko jedno zdanie: Expect a steady flood of announcements of setbacks, restructurings and bankruptcies as companies that were bought with borrowed money turn out to be unable to service their debt.

A czemu tytuł wpisu brzmi Stłucz pan termometr, nie będziesz miał pan gorączki? A bo czynniki rządowe utrzymują, że wystarczy nie siać paniki -- w tym a zwłaszcza opozycja nie powinna tego robić -- a będzie dobrze. Być może jest to wersja dla publiki, a jednocześnie najtęższe głowy: min. Vincent i prof. LB w ścisłej tajemnicy deliberują nad planem B? :-) Może...

niedziela, 28 września 2008

Mistrzostwa Europy U19 w Rugby

Impreza odbyła się w Sopocie (jest nawet info na www.irb.com). Wczoraj był finał: Rumunia vs Gruzja 31 : 28. Emocjonujący mecz, po cztery przyłożenia a do tego 2 drop gole (również po jednym dla każdej ze stron). Oglądałem też półfinał w minioną środę, w którym Gruzja rozniosła Rosję 37 : 0. Zdjęcia z obu ww. meczy umieściłem na flickr.com.

poniedziałek, 22 września 2008

Rowerowanie z Jasiem

W Sobotę pojechaliśmy razem z Jasiem na wycieczkę rowerową. Jakoś tak niedawno Jaś zapalił się całkiem na serio do rowerowania i zaczął jeździć -- sam -- po 20--30 kilometrów. Widząc co się dzieje dokupiłem mu pedały SPD (Shimano PD-M520) + buty (Shimano SH-M075G). W sklepie Żuchlińskiego 299 zł (na Allego trochę taniej, ale przecież nie będę robił wiochy mierząc buty w sklepie i kupując na Allegro) Do tego kask dla bezpieczeństwa i rajtuzy żeby wyglądał godnie (to z kolei kupiliśmy w sklepie Marka Szerszyńskiego w Sopocie).

Ponieważ po drogach się bałem z Jasiem jeździć pożyczyłem rower klasy Mountain Bike od Bogusia L. Pojechaliśmy do Oliwy a dalej ul. Kościerską do Owczarni, tam trochę pogubiliśmy drogę i zamiast pojechać dalej ul. Nowy Świat w stronę jeziora Wysockiego pojechaliśmy Meteorytową. [Tutaj uwaga: ww. ulice to wiejskie drogi a nie żadne ulice; a Meteorytowa nie dość że jest drogą polną to jeszcze do tego po ostatnich deszczach pełna kałuż i błota.] Dalej jadąc ul. Dębową dojechaliśmy do Barniewic a stąd kawałek brzegiem lasu po czym skręt w prawo. Jadąc teraz prosto przejechaliśmy w poprzek cały las pomiędzy Chwaszczynem, Tuchomkiem a Barniewicami, mijając po drodze kopalnię żwiru i parę malowniczych [zapewne pożwirowych] stawów. Po dojechaniu do Chwaszczyna -- ulicą Mickiewicza -- skręciliśmy do Osowy i dalej do Sopotu przez las. Powrót przez Wielką i Małą Gwiazdę. Ślad można obejrzeć tutaj [dystans: 35 km].

Następnym razem -- jak się nie pogubimy -- chcemy pojechać prosto Nowym Światem aż do Tuchomka, przeciąć drogę Gdynia-Kościerzyna i objechać jezioro Tuchomskie.

Dopisane 11 października 2008: Wczoraj byliśmy w Osowej ale wybraliśmy krótszą trasę: Owczarnia -- ul. Gnieźnieńska -- Źródło Marii. Powrót do Sopotu przez Gołębiewo. Bardzo fajna trasa, długość około 30 km (na liczniku wyszło 29,20). Ślad na mapie jest tutaj. A tutaj wersja eksperymentalna, na której można (klikając) wyświetlać średnią prędkość. Mianowicie należy kliknąć dwa razy na ślad, definiując w ten sposób początek i koniec odcinka śladu a zostanie pokazana średnia prędkość na tym odcinku. Uwaga: odcinek będzie zdefiniowany od--do najbliższych (miejsca kliknięcia) punktów ze śladu GPX. Uwaga2: nie należy celować myszą ,,w ślad'', tj. czerwoną linię tylko trochę obok....

poniedziałek, 15 września 2008

Parę statystyk dotyczących zdjęć z flickr.com

Od pewnego czasu pobieram dane z flickr.com dotyczące najbardziej interesujących zdjęć [sposób w jaki flickr.com tworzy listę `najbardziej interesujących' zdjęć nie jest znany]. Konkretnie wykonuję flickr.interestingness.getList pobierając 500 zdjęć dla każdego kolejnego dnia.

Dla takiego zbioru policzyłem: -- średnią liczbę tagów, tagów maszynowych (tj. takich, które zawierają dwukropek, np.: geo:lat=54.00) i tagów wielowyrazowych; -- średnią liczbę zbiorów i średnią liczbę puli, do których należy zdjęcie. Wreszcie -- odsetek zdjęć geokodowanych. Wszystkie ww. statystyki w rozbiciu na kolejne miesiące...

Teza była taka, że z czasem średnie/udziały będą miały większe wartości bo użytkownicy coraz chętniej będą swoje zdjęcia oznakowywać, doceniając płynące stąd korzyści. Rosnąca liczba tagów maszynowych i/lub wielowyrazowych oraz rosnący odsetek zdjęć geokodowanych w pewnym stopniu świadczyłaby o rosnącej semantycznej precyzji metadanych na flickr.com. Dane przedstawione poniżej nie potwierdzają tego założenia:


Statystyki flickra. Od : 2006-11-28 do 2008-08-28
-----------------------------------------------------
Mc/Yr : Loc MTag Poo RTag Set Tag
--> 200611: 13.9 0.067 8.810 1.704 1.543 8.975
--> 200612: 13.3 0.064 8.690 1.740 1.501 8.942
--> 200701: 14.0 0.066 8.607 1.603 1.596 9.281
--> 200702: 13.8 0.063 8.862 1.413 1.654 9.675
--> 200703: 13.4 0.063 9.159 1.398 1.679 9.936
--> 200704: 13.6 0.056 9.556 1.434 1.703 10.302
--> 200705: 14.4 0.056 10.229 1.432 1.700 10.568
--> 200706: 13.2 0.057 9.968 1.386 1.688 10.217
--> 200707: 12.8 0.048 8.136 1.401 1.613 9.547
--> 200708: 14.0 0.059 7.770 1.585 1.773 10.249
--> 200709: 13.5 0.053 7.321 1.638 1.767 10.174
--> 200710: 13.6 0.057 6.939 1.610 1.743 9.722
--> 200711: 12.9 0.055 6.698 1.532 1.714 9.392
--> 200712: 12.4 0.048 6.698 1.606 1.749 9.644
--> 200801: 12.1 0.052 6.818 1.599 1.685 9.456
--> 200802: 11.2 0.049 6.962 1.603 1.664 9.401
--> 200803: 10.4 0.049 6.786 1.637 1.675 9.457
--> 200804: 10.3 0.049 6.475 1.623 1.672 9.315
--> 200805: 10.6 0.053 6.505 1.661 1.690 9.205
--> 200806: 10.0 0.047 6.369 1.693 1.650 9.023
--> 200807: 10.0 0.038 6.534 1.664 1.658 9.101
--> 200808: 11.1 0.048 6.181 1.726 1.715 9.471
-----------------------------------------------------

Gdzie: Loc -- odsetek zdjęć geokodowanych; MTag -- średnia liczba tagów maszynowych; Poo -- średnia liczba puli; RTag -- średnia liczba tagów wielowyrazowych ; Set -- średnia liczba zbiorów ; Tag -- średnia liczba tagów.

Jak widać w zasadzie wartości są stałe. Można nawet zauważyć, że odsetek zdjęć geokodowanych uległ niewielkiemu obniżeniu (z 13--14, do 10--11%). Także spadła nieznacznie przeciętna liczba puli, do których wysłano zdjęcie... Liczba tagów maszynowych jest śladowa. Hmmm...

Dopisane 16 września 2008: Policzę jeszcze ww. statystyki dla danych bardziej losowych. Ściągnę mianowicie opisy zdjęć za pomocą flickr.photos.getRecent:


do { $pageno++; ## następna strona

my $resp = get ( "http://www.flickr.com/services/rest/?" .
"method=$method&api_key=$api_key&per_page=$max_per_page&" .
"page=$pageno&extras=geo,views,tags,machine_tags,license" );
## sprawdź czy jest OK:
eval { $photos = $parser->parse_string($resp) } ;

unless ($@) {## pomiń stronę z błędami
## ... obrób dokument XML zawarty w $resp ##
}
} while ( ($current_page < $total_pages) && ($pageno < $max_pages) );

Konstrukcja eval{ ... } służy do tego żeby skrypt się nie wywalał po fatal error tylko wykonywał następną iterację. A potrafi się wywalić na parsowaniu XML bo rzadko-bo-rzadko ale czasami coś jest nie tak z kodowaniem (UTF).

Skrypt, którego fragment jest wyżej będzie uruchamiany losowo plus/minus co 15 minut:


#!/usr/bin/perl
## Do forever with 15 min random delay or ca 4 x hour (\approx 100 per 24 hrs)
while (1) { my $runTask = `perl flickr_photo_recent.pl`;
sleep (int(rand(600 )) + 600); }

Plan jest taki żeby ściągać dane przez 10 dni. Zakładając 100 tys zdjeć na dzień da to próbę wielkości 1 mln zdjęć.

Dopisane 26 września 2008: Niebuforowany zapis do STDOUT oraz do pliku. Sprawa ciut niejasna: w Internecie większość tekstów wskazuje, że problem załatwia nadanie zmiennej $| wartości niezerowej. Mi to jednak nie działa... W końcu znalazłem działającą odpowiedź:


#!/usr/bin/perl
use FileHandle;

# to make STDOUT flush immediately, simply set the variable $|
$| = 1;

# to prevent buffering when writing to files, set autoflush on
# the file handle
open (OUT, ">>test.out") || die "could not create test.out - $!";
OUT->autoflush(1);

print OUT "writing to file\n";

close(OUT); exit(0);

Dopisane 2 października 2008: Pierwsze wyniki dla danych z 18.09--30.09 (łącznie 364,127 zdjęć): 1) odsetek zdjęć zawierających co najmniej jeden tag: 40,77%; 2) odsetek zdjęć geotagowanych: 4,06%; 3) odsetek zdjęć tagowanych i umieszczonych w co najmniej jednym pulu: 10,17%; 4) odsetek zdjęć geotagowanych, tagowanych i umieszczonych w co najmniej jednym pulu: 1,15%. Przeciętnie zdjęcie było oznaczone 2,5 tagami. Jak widać najbardziej interesujących zdjęcia są ca 3 razy częściej geotagowane i mają 3--4 razy tyle tagów... Zrozumiałe bo znaczna część zdjęć jest wrzucana ,,jak leci'' bez oznaczenia ich czymkolwiek. Z reguły też zdjęcia takie są mało interesujące dla szerszej publiczności...

Dopisane 4 października 2008: Dziś wylosowałem 2,5% z 233520 użytkowników flickr, których zdjęcia pobrałem w ostatnich dniach. Te 2,5% to było dokładnie 5838. Ściągnąłem za pomocą flickr.people.getInfo informacje dotyczące liczby zdjęć i daty zawartej w elemencie firstdate. (The firstdate element contains the unix timestamp of the first photo uploaded by the user.). Myślałem, że to data pierwszego uploadu, ale tak nie jest. Wygląda to raczej na (opis jest raczej lakoniczny) na datę wykonania pierwszego zdjęcia zamieszczonego na flickr.com. Data ta jest zapewne odczytana z odpowiedniego pola Exif, a co za tym idzie może jej nie być, albo może być lipna... Anyway wyniki są następujące:


Wyszczególnienie N mediana średnia dominan od.st. max min Ws Ws'
L.zdjęć 5837 191.00 846.11 200.00 3121.26 171182 0 0.21 (0.63)
L. dni 5837 307.00 435.80 18.00 546.00 14157 2 0.77 (0.71)

L. dni, to liczba dni od firstdate (coś w rodzaju stażu). Próba się zmniejszyła do 5837, bo z jednym użytkownikiem był problem... Ws to współczynnik skośności Pearsona (x-D)/sd (a w nawiasie podobny współczynnik skośności (Ws') liczony na podstawie Mediany, jako 3(x-Me)/sd.) Rozkłady są zatem prawostronnie asymetryczne. A ten gość co ma 170tys zdjęć jest tutaj:-). Interpretacja: 50% użytkowników, którzy publikują swoje zdjęcia ma ich mniej niż 191... BTW element count zawiera liczbę wszystkich zdjęć umieszczonych na flickr.com, nie tylko zdjęć o statusie public. Nie jest to napisane w dokumentacji ale zweryfikowałem empirycznie...

niedziela, 14 września 2008

Na MSIE nie działa

Dokumenty z http://pinkaccordions.homelinux.org/wblog nie wyświetlają się poprawnie w IE 6. Czy się wyświetlają w nowszych Eksplorerach to nie wiem -- nie sprawdzałem. Nawet chciałem dziś coś w tej sprawie dłubnąć ale nic z tego nie wyszło. Ostatecznie poprzestałem na dodaniu uwagi w nagłówku, że w MSIE nie działa. W sumie używanie dziś MSIE to dziwactwo, bo czemu nie korzystać z czegoś co jest lepsze skoro to nic nie kosztuje?

Dopisane 17 września 2008: Ponieważ arkusz CSS działał z przeglądarkami FF/Opera a z MSIE nie, więc uważałem że problem jest -- jak prawie zawsze -- z systemem specjalnej troski. Tak to już jest, że jak ktoś notorycznie coś psuje, no to podświadomie się zakłada, że ów ktoś ma zawsze popsute. [Pamiętam zwłaszcza w tym kontekście hasełko reklamowe MS Polska sprzed paru lat: kto pomyśli -- my pomyślimy. Na wydruku brak było tzw. polskich liter: kto pomyli -- my pomylimy. Brawo dla tych panów za szczerość:-]

Jednak w wolnej chwili sprawdziłem, i się okazało, że strona nie wyświetla się prawidłowo w IE7 też, co by mogło znaczyć że być może mój arkusz na 100% nie jest poprawny. Przyznam się przy okazji bez bicia, że nie znam/nie używam ,,zaawansowanych'' właściwości CSS -- arkusz skopiowałem kiedyś z pewnej strony i wydawało się że działa. Teraz po krótkich konsultacjach dodałem left do właściwości lewej/prawej kolumny. Teraz działa lepiej, a przynajmniej działa w IE7. BTW arkusz, o którym mowa jest tutaj: 2cols.css.

Wyszukiwanie zdjeć na flickr.com

W książce Flickr Hacks Paula Bauscha i Jima Bumgardnera do manipulowania danymi w formacie XML przesyłanymi z flickr.com używa się XML::Simple. Jakoś XML::Simple nie wydaje mi się specjalnie simple w tym wypadku. Zdecydowanie wolę XML::LibXML, który pozwala przede wszystkim na dotarcie do poszczególnych fragmentów dokumentów XML w prosty sposób bez używania karkołomnych referencji. Przykładowo poniższy skrypt (fragment) wykonuje zapytanie flickr.photos.search [najistotniejszą częścią skryptu -- zaznaczoną odmiennym kolorem tła -- jest pętla do { ... }]:


use XML::LibXML;
use LWP::Simple;
use Getopt::Long;

require 'login2flickr.rc';

our $api_key;
our $my_flickr_id;

my $tags_txt;
my $show_help;
my ($user_id, $all_users, $report_views);
my @Photos;

GetOptions( "all" => \$all_users,
"user=s" => \$user_id, "views" => \$report_views,
"tags=s" => \$tags_txt);

unless ( $user_id ) { $user_id = $my_flickr_id; }
if ( $all_users ) { $user_id = ''; } ## search all photos

my $parser = XML::LibXML->new;
my $pageno;
my $method = 'flickr.photos.search';
my $max_per_page = 500;
my ($total_pages, $current_page);

my $search_query = "&extras=geo,views"; # http://www.flickr.com/services/api/flickr.photos.search.html
if ( $user_id ) { $search_query .= "&user_id=$user_id"; }
if ( $tags_txt ) { $search_query .= "&tags=$tags_txt" }


do {
$pageno++;

my $resp = get ( "http://www.flickr.com/services/rest/?" .
"method=$method&api_key=$api_key&per_page=$max_per_page&page=$pageno" .
$search_query );

## sprawdź czy jest OK:
my $photos = $parser->parse_string($resp);
unless ( $photos->getElementsByTagName('rsp' )->[0]->getAttribute( 'stat' ) eq 'ok') {
die "Problems with retriving photo list!\n" }

push @Photos, $photos->getElementsByTagName('photo' );

$total_pages = $photos->getElementsByTagName('photos' )->[0]->getAttribute('pages' );
$current_page = $photos->getElementsByTagName('photos' )->[0]->getAttribute('page' );

# Dla dużych zbiorów zdjęć może długo trwać, więc wypisz że coś robisz:
printf STDERR " *** Page %d of %d retreived...\n", $current_page, $total_pages;

} while ( $current_page lt; $total_pages );

## Lista @Photos zawiera wszystkie zdjęcia...
## ... dalsza część skryptu ...

Pętla jest niezbędna ponieważ flickr API organicza wielkość zwracanego dokumentu do maksymalnie 500 zdjęć. Jeżeli zdjęć jest więcej, to zapytanie należy zadać wielokrotnie, zmieniając wartość parametru page. Przy czym liczbę wszystkich stron określa wartość atrybutu pages.

Po ściągnięciu dokumentu skrypt sprawdza czy wszystko jest OK. Jeżeli tak, to za pomocą getElementsByTagName pobiera wszystkie elementy photo i dodaje je do listy @Photos. Teraz pobierane są wartości atrybutów pages/page w celu ustalenia czy wszystko już ściągnięto. Jeżeli pages < page to pętla działa dalej...

Zwracam uwagę, że od jakiegoś czasu zapytanie może zawierać parametr extras, dzięki któremu zwracany dokument XML zawiera dodatkowe informacje, takie jak: tagi, współrzędne geograficzne, liczbę odsłon, itd... Jest to opisane w API na flickr.com a także tutaj. W wyżej przedstawionym skrypcie deklaracja:


my $search_query = "&extras=geo,views";

Oznacza, że do standardowych opisów zdjęć będą dodane także współrzędne geograficzne (oczywiście tylko wtedy gdy zdjęcia będą nimi oznaczone) oraz liczba odsłon. BTW dodanie extras=views powoduje, że kiedyś niemożliwy do wykonania poprzez API problem ustalenia ile razy zdjęcie było oglądane teraz jest jak najbardziej wykonalny. Zatem skrypty -- opisane w Nowa usługa na flickr.com oraz Czy flickr umie liczyć -- lepsze rozwiązanie -- są już niepotrzebne.

Kompletny skrypt pobierający zdjęcia z flickr.com i wypisujący plik GPX dla tych, które zawierają współrzędne geograficzne jest tutaj. Ale uwaga: próba wykonania zestawienia wszystkich wież ciśnień z flickr.com:


flickr_photo_gsearch.pl -a -t 'wieżaciśnień,wasserturm,watertower' > wasserturme-alles.xml

Skończyła się pobraniem ponad 23 tysięcy zdjęć (z tego około 6 tys. było geokodowane). Plik GPX pn. wasserturme-alles.xml miał 1,8 Mb i za nic nie szło tego wyświetlić w przeglądarce. Za duże... Mniejsze pliki są ok: kaplice [mapa ] albo moje wieże ciśnień [mapa ].

sobota, 6 września 2008

Urwany ślad

Wziąłem aparat na dzisiejsze jeżdżenie rowerowe i popstrykałem trochę zdjęć w czasie jazdy. Rowerzyści są na nich od strony rewersu widoczni w większości (por. rysunek obok), ale to tylko podnosi autentyczność--tak to wygląda w środku peletonu:-)

No i GPS złośliwie się wyłączył w okolicach Kielna czyli tak w 2/3 trasy. Akurat zdjęcia, na których kol. Rysiu mnie sfotografował nie mogą być geokodowane (aka geotagowane), bo ślad się urwał. Pech... Ale, ale... Już kiedyś tą trasą jechałem i ślad mam tyle, że nie do końca tą, pewnie z trochę inną prędokością dziś dziś ale lepsze to niż nic. Tyle, że stempel czasu dla każdego punktu na śladzie jest zły. Pomyślałem, że można by oszukać gpsphoto ,,uzupełniając'' dzisiejszy ślad kawałkiem starego. Okazało się to całkiem proste dzięki gpsbabel:


gpsbabel -t -i gpx -f plik-we.gpx -x track,move=spec-czasu -o gpx -F plik-wy.gpx

Gdzie spec-czasu ma postać znak99d99h99m99s (99 oznacza stosowną liczbę, a poszczególne składniki są opcjonalne.) Przykładowo +2h przesunie czas o dwie godziny do przodu. Podobnie +32d0h1m42s przesunie o 13 dni, minutę i 42 sekundy ,,do przodu''.

Teraz w Google maps ustaliłem gdzie się kończy dzisiejszy ślad a następnie znalazłem punkt na śladzie z 23 sierpnia z grubsza odpowiadający tej pozycji. Zrobiłem to zupełnie na piechotę metodą ,,kilku przybliżeń'' (tj. wstawiałem do pliku GPX element wpt odpowiadający punktowi ze śladu, który był ,,w okolicy'' szukanego miejsca. Oczywiście pierwszy strzał był niezbyt celny, ale po kilku podstawieniach znalazłem szukany punkt). Od tego punktu wyciąłem do końca (bo akurat do końca trasy się pokrywały) i zapisałem jako plik tmp.gpx. Teraz ustaliłem różnicę czasu między obu punktami. Do tego ostatniego zadania użyłem Perla:


#!/usr/bin/perl
# Uruchom np.: delta_days.pl -w 2008:8:24:10:2:9 -p 2008:9:6:10:3:51
use Date::Calc qw/Delta_DHMS/;
use Getopt::Long;

GetOptions("w=s" => \$wszesniej, "p=s" => \$pozniej);
@wczesniej = ex ($wszesniej); @pozniej = ex ($pozniej);

my ($d, $h, $m, $s) = Delta_DHMS(@wczesniej, @pozniej);
print "Różnica: d: $d, h: $h, m: $m, s: $s\n";

sub ex { my $w = shift ; return ( split /[:;-]/, $w ) }

Różnica wyniosła 13 dni, minutę i 42 sekundy. Teraz uruchomiłem gpsbabela:


gpsbabel -t -i gpx -f tmp.gpx -x track,move=+13d0h1m42s -o gpx -F tmp-out.gpx

Śladem z plik tmp-out.gpx uzupełniłem dzisiejszy, niekompletny ślad. Skrypt gpsphoto (uruchomiony via My-photo-sync.sh) zsynchronizował wszystkie fotki. Oczywiście jest błąd (np. wynikający z tego, że wtedy i dziś poruszałem się z różną prędkością), ale imho jest to błąd akceptowalny...

Całość jest tutaj. No i niech ktoś się teraz nie upiera, że Windowsem i Excelem to on wszystko obliczy....:-)

Jak już jestem przy tematyce rowerowej, to szukając butów SPD dla młodego usiłowałem obejrzeć stronę WWW jednego z większych trójmiejskich sklepów. Nie udało się... nur für Windows. I to tak dramatycznie: nic nie widać, w nic nie można kliknąć...

czwartek, 4 września 2008

Propaganda

Czasy kiedy tzw. media informowały wydają się czasami minionymi... Przez kilka ostatnich dni nachalnie wtłaczana była do pustych głów teza, pn. ``absencja L. Wałęsy w katalogu IPN to skandal i oczywisty dowód politycznej zależności Instytutu od jego politycznych mocodawców''. Jak już puste głowy uwierzyły w tę kolejną niegodziwość PiS, to w GW ukazał się -- przyznam zaskakujący -- tekst opisujący tę sprawę tak jak ona wygląda: Osób, które otrzymały z IPN status pokrzywdzonego, jest ponad 50 tysięcy. To właśnie nazwiska ludzi z tej grupy są [...] najczęściej wpisywane do katalogu. Tymczasem na zamieszczonej przez IPN liście znajduje się zaledwie 2129 nazwisk [...] Na liście brakuje wielu znanych działaczy opozycyjnych w tym Antoniego Macierewicza, Jana Olszewskiego i Ludwika Dorna. Dodatkowo: [...] Wskutek zapisu ustawy nakazującego zgodę osoby, której dane są publikowane, w katalogu niestety nie mogą zostać zamieszczone nazwiska osób rozpracowywanych, które nie żyją [...] To oznacza, że na liście nie będzie nazwisk wielu znanych opozycjonistów, jak choćby Jacka Kuronia czy Bronisława Geremka. (cf. ). Naiwne pytanie: po co było zatem wcześniej wiatr robić, pisząc bzury i mącąc w głowach?

Teza, że ,,Kłamstwo powtarzane wielokrotnie staje się prawdą'' przez wielu jest przypisywana J. Goebbelsowi. Mniej znane jest, że Reichsminister osobiście zweryfikował powyższe twierdzenie empirycznie. W swoich artykułach z Der Angriff uporczywie określał on szefa berlińskiej policji, Dr. Bernharda Weissa, jako ,,Izydor Weiss'' [Imię Izydor ma/miało w Niemczech podobną konotację jak w Polsce, np. imię ,,Mosiek'']. Po 2--3 latach większość berlińczyków była przekonana, że Dr. Weiss ma na imię Izydor. Prowokował Weissa do wytaczania sądowych procesów [Weiss wytoczył mu ich aż -- podobno -- 28], co nagłaśniało ,,spór''. Spór o co? No właśnie... czy coś nie wydaje się w tej historii znajome...

W zasadzie tematów ,,politycznych'' nie poruszam bo się nie znam i wolę się nie ośmieszać. Ale ten nie jest do końca polityczny... Raczej historyczno-socjologiczny:-) A ministerstwo o którym wyżej wspominam oficjalnie i ekshibicjonistycznie się nazywało: Reichsministerium für Volksaufklärung und Propaganda (oświecenia publicznego i propagandy).

środa, 27 sierpnia 2008

Lejkowiec już jest

Dziś znalazłem pierwsze tegoroczne lejkowce. W Lasach Oliwskich wokół Sopotu.

Dopisane 4 września 2008: W lesie naokoło Sopotu jest wysyp borowików jakiego najstarsi ludzie nie pamiętają... I do tego pełno lejkowców, które mało kto zbiera.

Apache Velocity DocBook Framework

Wymieniony w tytule Apache Velocity DocBook Framework (AVDF) to sterowany antem zbiór narzędzi do zamiany dokumentów DocBook na HTML/PDF. Konkretnie tymi narzędziami są Fop (w wersji 0.20.5), Saxon i szablony XSL N. Walsha. Po ściągnięciu archiwum .zip lub .tgz ze strony projektu i rozpakowaniu, na dysku pojawi się następująca struktura katalogów:


<korzeń instalacji AVDF>
|
+---- build-docbook.xml
+---- project.properties
+-- src
+-- styles

+-- docs
+-- build.xml
+-- project.properties
+-- src
+--css
+--docbook
| +--<projekt>
+-- images
+-- target
+-- lib

Katalog lib zawiera fopa i saxona plus niezbędne dodatkowe aplikacje. Katalog src/styles zawiera szablony ,,startowe'', uruchamiane przy zamianie plików XML na HTML i PDF. [Tu trzeba dłubnąć żeby dokonać polonizacji.] Wreszcie dokument ,,źródłowy'' ma być obowiązkowo umieszczony w katalogu docs/src/docbook/<projekt>. Pliki z rysunkami zaś muszą być umieszczone w docs/src/images. Wynik transformacji będzie się znajdował w docs/target/<projekt>. Dodatkowo w docs/src/css znajduje się szablon CSS wykorzystywany przez wygenerowane pliki HTML.

Polonizacja wymaga: 1) ściągnięcia następującego archiwum .zip i rozpakowania jego zawartości w tak sposób aby została dodana do oryginalnej dystrybucji AVDF (kilka plików zostanie nadpisanych); 2) wykonania polecenia ant -f build-docbook.xml dbf.init z poziomu korzenia instalacji AVDF. Tyle -- powinno działać. Reszta tego wpisu dotyczy szczegółów: co, jak i dlaczego. Można nie czytać...

Pliki build-docbook.xml zmieniłem tak, że dodałem do wywołania fopa argument -c plik.cnf, tj.:


<java classname="org.apache.fop.apps.Fop" fork="true" maxmemory="256m"
dir="${basedir}" classpathref="dbf.classpath">
<arg value="${pdf.target.file}.xml"/>
<arg value="${target.dir}/${docbook.dir}/pdf/${docbook.file}.pdf"/>
<arg value="-c"/>
<arg value="${dbf.basedir}/conf/userconfig.xml"/>

</java>

Parametr ${dbf.basedir} to katalog główny, w którym znajduje się cały framework. Dodany katalog conf/ zawiera plik konfiguracyjny fopa + pliki metryczne fontów. Same fonty (pliki .ttf) są w katalogu fonts/. Dodanie do AVDC fontów powoduje, że całość jest gotowa do użycia w każdym systemie. [Można oczywiście tak skonfigurować AVDF żeby używał fontów systemowych]. Z kilku zestawów rozpowszechnianych bezpłatnie fontów truetype (Core fonts for the Web (Nie najwyższej jakości i do tego ich rozpowszechnianie podlega pewnym ograniczeniom), TeX Gyre, Quasi, STIX (tylko jedna odmiana -- brak kroju bezszeryfowego i kroju typu monospace), DejaVue) zdecydowałem się na fonty Quasi. Wprawdzie są one już obsolete ale działają z fopem a fonty TeX Gyre, które są lepszą wersją Quasi -- nie bardzo. [Są problemy nawet po konwersji OTF->TTF.]

Położenie fontów w systemie jest określone w pliku conf/userconfig.conf. Ponieważ ścieżka do fontu nie może być zaszyta na zicher, plik conf/userconfig.conf rozpoczyna się od następującej deklaracji DOCTYPE:


<!DOCTYPE configuration SYSTEM "config.dtd" [
<!ENTITY fop.home "@dbf.basedir@">
<!ENTITY ttf.dir "@dbf.basedir@/fonts">

Napisy @dbf.basedir@ są zamieniane na to co trzeba po uruchomieniu ant -f build-docbook.xml dbf.init (trzeba to zrobić dokładnie raz). Cel (target) dbf.init wygląda zaś następująco:


<target name='dbf.init' description='Adjust some system specific files'>

<copy file="${basedir}/conf/userconfig.conf" tofile='${basedir}/conf/userconfig.xml'
overwrite="true" failonerror="false" filtering="on" >
<filterset>
<filter token="dbf.basedir" value="${basedir}"/>
</filterset>
</copy>
</target>

Jak widać plik conf/userconfig.conf jest kopiowany do conf/userconfig.xml a dodatkowo napisy @dbf.basedir@ są zamieniane na bieżącą wartość ${basedir}. To się nazywa token substitution (cf. Using Ant as a Text Substitution Preprocessor).

Ostatni etap polonizacji AVDF to poprawienie plików html.xsl, htmlsingle.xsl z katalogu src/styles. Dodałem do plików html.xsl oraz htmlsingle.xsl:


<xsl:output method="html"
encoding="utf-8"
indent="no"
saxon:character-representation="native;decimal"
xmlns:saxon="http://icl.com/saxon" />

<!-- zapisuje znaki `natywnie' a nie jako encje (domyślnie) -->
<xsl:param name="chunker.output.encoding" select="'utf-8'"/>
<xsl:param name="saxon.character.representation" select="'native;decimal'"/>

A do pliku pdf.xsl (z tego samego katalogu):


<!-- przełącza się na fonty Quasi, domyślnym fontem szeryfowym jest
QuasiPalatinoTTF, zmień na QuasiTimesTTF jeżeli ma być Times New Roman -->
<xsl:param name="sans.font.family" select="'QuasiSwissTTF'"/>
<xsl:param name="title.font.family" select="'QuasiSwissTTF'"/>
<xsl:param name="body.font.family" select="'QuasiPalatinoTTF'"/>
<xsl:param name="monospace.font.family" select="'QuasiCourierTTF'"/>

Powyższe to minimum: polskie znaki są prawidłowo wyświetlane na ekranie oraz -- co ważne -- zapisywane w pliku jako sekwencje UTF a nie w postaci encji (tj. &oacute;). Jeżeli układ graficzny dokumenty komuś nie odpowiada, no to musi jeszcze bardziej zmodyfikować pliki .xsl i/lub CSS (oczywiście szablony CSS dotyczą wyłącznie dokumentów HTML).

wtorek, 26 sierpnia 2008

Wywiad z Knuthem w CACM

W numerach 7--8 Communications of the ACM jest wywiad z Knuthem (ściśle mówiąc: vol. 51 nos 7--8, 2008). Pierwsza część jest teraz nawet dostępna on-line. Fragment: Then a startup company came to me and said, [...] ``Name your price.'' I said ``Oh, okay, $100,000,'' assuming that this was [outrageous]. The guy didn't blink. He agreed. I didn't blink either. I said, ``I'm not going to do it. I just thought that was an impossible number.'' At that point I made the decision in my life that, I wasn't going to optimize my income.

niedziela, 24 sierpnia 2008

Konwersja OTF na TTF

Poniżej skrypt zamieniający font w formacie OpenType na TrueType.


#!/usr/local/bin/fontforge
# Quick and dirty hack: converts a font to truetype (.ttf)
# cf. http://www.stuermer.ch/blog/convert-otf-to-ttf-font-on-ubuntu.html
Print("Opening "+$1);
Open($1);
Print("Saving "+$1:r+".ttf");
Generate($1:r+".ttf");
Quit(0);

Czy konwersja jest w 100% OK nie jest do końca pewne bo podobno gubiona jest informacja na temat par kernowych.

środa, 20 sierpnia 2008

Przewyższenie i profil śladu

Etrex mimo, że nie ma barometru dość sensownie podaje wysokość npm. Jakoś do tej pory umknęło to mojej uwadze.

Poniżej skrypt wyznaczający długość trasy, łączną sumę wysokości podjazdów (przewyższenie, aka cumulative elevation gain) oraz rysujący profil w postaci pliku PNG. To ostatnie niekoniecznie jest sensowne, bo GD::Graph::lines traktuje dane z osi OX jako napisy a nie liczby i w związku z tym odstępy między poszczególnymi punktami na tej osi są równe. Zamiast GD::Graph::lines trzeba użyć czegoś innego, np. Chart::Graph::Gnuplot.


#!/usr/bin/perl
#
# Tworzy plik PNG przedstawiający profil śladu (wysokość mnpm)
# z danych podanych (jako argument skryptu) w pliku GPX
# tprzechlewski[_at_]gmail.com sierpień/2008
#
use XML::LibXML;
use Geo::Distance;
use Getopt::Long;

GetOptions( 'log' => \$print_log, 'pic' => \$print_pic, );

$usage = "Usage: $0 [-p | -l] plik.gpx ;; -p generate PNG file ; -l show log.\n";

my $geo = new Geo::Distance;

my $file = shift || die "$usage";

my $parser = XML::LibXML->new;

open my $fh, $file || die "problems...";

$doc = $parser->parse_fh($fh);

my @tracks = $doc->getElementsByTagName('trk');
my $ptnum=0;

for $tx (@tracks) {

@segments = $tx->getChildrenByTagName('trkseg');
if ( $name = $tx->getChildrenByTagName('name')->[0] ) { # pierwszy element to nazwa śladu
if ($print_log) { print "<!-- track:: ", $name->textContent(), " -->\n"; }
}

for $sx (@segments) {

@points = $sx->getChildrenByTagName('trkpt');

for $px (@points) {
@data = $px->getChildrenByTagName('*');
@attrs = $px->attributes();

if ($print_log) { print "-> " ; }

for $dx (@data) {
if ($print_log) { print $dx->nodeName, " = ", $dx->textContent(), " ; " ; }
if ($dx->nodeName eq 'ele') { $ele = $dx->textContent();
push @Elevations, $ele;
}
}

for $ax (@attrs) {
if ($print_log) { print " ", $ax->nodeName, " = ", $ax->getValue() ; }
if ($ax->nodeName eq 'lon') { $lon = $ax->textContent() }
elsif ($ax->nodeName eq 'lat') { $lat = $ax->textContent() }
}

if ($print_log) { print " ;;\n"; }

if ( $ptnum > 0 ) {
$curr_dist = $geo->distance( "meter", $plon, $plat => $lon, $lat );
$dist += $curr_dist ;
push @Distances, $curr_dist;
if (($ele_diff = $ele - $pele ) > 0) { $totalEleGain += $ele_diff ; }

} else {
push @Distances, 0;
}

$plon = $lon; $plat = $lat ; $pele = $ele ; $ptnum++;
}
}
}

# http://en.wikipedia.org/wiki/Cumulative_elevation_gain (przewyższenie):
printf "*** Dist: %.1f meters *** EleGain: $totalEleGain ***\n", $dist;

## Drukowanie profilu trasy

unless ( $print_pic ) { exit 0 }

use GD::Graph::lines;
use POSIX; # floor

my $img_file = "${file}.png" ;

my @data = (\@Distances, \@Elevations, );

my $mygraph = GD::Graph::lines->new(400, 300);

# skip some dates to avoid label overlapping on X-axis:
my $x_factor = floor (($#Distances + 1) / 10 ) + 2;
print "$#Distances observations. X-axis labels printed evey ${x_factor}th one!\n";

$mygraph->set_text_clr('black');
$mygraph->set(
x_label => 'Dist',
y_label => '#',
title => "# Elev",
# Draw datasets in 'solid', 'dashed' and 'dotted-dashed' lines
line_types => [1, 1, ],
# Set the thickness of line
line_width => 2,
# Set colors for datasets
dclrs => ['blue', 'red', 'cyan'],
#x_tick_number => 'auto',
x_label_skip => $x_factor,
transparent => 0, ## non-transparent
bgclr => 'white',
fgclr => 'black',
borderclrs => 'black',
boxclr => '#ede7e7',
labelclr => 'black',
#axislabelclr,
legendclr => 'black',
) or warn $mygraph->error;

$mygraph->set_legend_font(GD::gdMediumBoldFont);
$mygraph->set_legend('ele', 'ele2', '???');

my $myimage = $mygraph->plot(\@data) or die $mygraph->error;

## for cgi script uncomment:
##print "Content-type: image/png\n\n";

open ( IMG, ">$img_file") or die " *** Problems opening: $img_file ***" ;

print IMG $myimage->png;

close (IMG);

##print "@Distances\n"; ## debug

##

Wykorzystuję od jakiegoś czasu XML::LibXML. W skryptach do obsługi flickr.com korzystałem z XML::Simple ale do parsowania plików GPX ten pakiet się nie nadaje -- nie zachowuje porządku elementów (bo je czyta do hasza). W oczywisty sposób porządek punktów na śladzie nie może być dowolny.

A tutaj ktoś zrobił coś podobnego tyle, że używając Pythona.

wtorek, 19 sierpnia 2008

7 dni w Świdnicy

To była ciekawa wycieczka. Zwiedzaliśmy okolice Świdnicy oraz byliśmy na Śnieżce i w Górach Stołowych (Szczeliniec/Teplice). Wracając z Teplic zwiedziliśmy klasztor w Broumovie.

Doszło do niewielkiego bałaganu w zbiorze zdjęć przywiezionych z tygodniowego pobytu w Świdnicy. Zdjęcia z kilku dni przegrałem do jednego katalogu i hop, bez zbędnego myślenia uruchomiłem skrypt gpsPhoto.pl aby dodać współrzędne geograficzne. Po tej operacji czas modyfikacji każdego pliku ze zdjęciem się zmienił no i był mały kłopot z szybkim ustaleniem w którym dniu dane zdjęcie było zrobione. Oczywiście ta informacja nie została utracona, bo jest wartością pola DateTimeOriginal, tyle że ,,z poziomu'' wiersza poleceń tego nie widać.

Już chciałem jakiś skrypt klecić żeby pobierał DateTimeOriginal a następnie zmieniał czas modyfikacji pliku, ale w dokumentacji exiftool znalazłem gotowy przykład dokładnie robiący to, co chciałem osiągnąć:


exiftool "-Directory<DateTimeOriginal" -d "%Y-%m-%d" KATALOG

Powyższe przeniesie wszystkie pliki .jpeg z katalogu KATALOG do katalogów o nazwach postaci rok-miesiąc-dzień. Daty modyfikacji pliku to nie zmienia, ale samo uporządkowanie w odpowiednich katalogach w zupełności mi wystarczy.

Mój GPS Logger (używam Iblue 747) dwa razy zarejestrował ślad zawierający kolosalne odchylenie (biegun północny, tj. lat="90.000000000" lon="0.000000000"). Wcześniej nie obserwowałem tego fenomenu, tj. mówiąc dokładnie Etrex H nagminnie oszukuje podając np. średnią/maksymalną prędkość, ale zwykle zgrany ślad jest OK. Próbowałem poszukać jakiś automatycznych sposobów usunięcia takich anomalii ale nie znalazłem. Ostatecznie problem jest źle zdefiniowany więc automatem się nie da. Potrzebny jest edytor i wizualna inspekcja (np. MapSource ale to wyłącznie windziana aplikacja). Z braku takowego ślad wyświetlam na Google Maps a rażące odchylenia usuwam patrząc na współrzędne. Na moje potrzeby super korekta śladu nie jest potrzebna. Tak nawiasem mówiąc wspólnym mianownikiem Loggera i Etrexa jest chip firmy MTK. Ciekawe czy wszystkie czułe GPSy typu Sirf3/MTK robią takie błędy czy tylko MTK?

Ślady w formacie KML ze zdjęciami umieściłem tutaj: świdnica--książwlk.sowa--ludwikowiceszczeliniec--wambierzycekarpacz--śnieżkakompleks--osówka+zamek grodnoteplice--broumovślęża--tąpadła--sulistrowiczki

poniedziałek, 4 sierpnia 2008

piątek, 1 sierpnia 2008

Pedometer

Jak nie zapiszę, to zapomnę. Już kiedyś znalazłem serwis pozwalający on-line na tworzenie tras (routes) w formacie GPX za pomocą klikania w GoogleMaps. Nie zapisałem i oczywiście nie mogłem go znaleźć przez dłuższą chwilę. W końcu jest: http://www.gmap-pedometer.com/. Moja przykładowa trasa: Brodnica-BachotekUMK. IMHO czasami może się okazać przydatne...

Planowanie tras w www.gmap-pedometer.com/

Trasy z google maps zaimportowane do odbiornika GPS są do kitu... Są zbyt proste i bez Gmapy sprowadzają się do linii prostej, łamanej w kilku miejscach. Dużo lepsze efekty daje http://www.gmap-pedometer.com/. Należy także zainstalować bookmarklet GMapToGPX, który -- przynajmniej w Firefoksie -- pojawi się jako guzik na pasku zakładek. Trasę należy wyklikać, a jak już jest gotowa trzeba nacisnąć GMapToGPX. W oddzielnym oknie zostanie wyświetlony dokument GPX, który metodą copy-paste wkleja się do pliku. Teraz należy załadować trasę -- w przypadku mojego Legenda HCx, gpsbabela i FC8, wygląda to następująco:


gpsbabel -r -i gpx -f plik.gpx -o garmin -x simplify,count=225 -F /dev/ttyUSB0

Ważny jest filtr -x simplify,count=225, bo trasy muszą być krótsze od 250 punktów albo zostaną ucięte (co urządzenie zasygnalizuje komunikatem Route Truncated). Dałem limit 225 mogłem 250... być może należy dać jeszcze mniej żeby Garmin nie piszczał non-stop.

Powyższe w praktyce sprawdziło się całkiem całkiem... Przykładowo moja trasa do Gdyni-Oksywia, naokoło przez las. (Na czerwono planowana na niebiesko zrealizowana.) W miejscu gdzie chciałem pojechać wzdłuż Estakady Kwiatkowskiego się okazało, że nie da rady (rura ciepłownicza); na GoogleMaps była tam zaznaczona ścieżka stąd takie nierealistyczne plany.

sobota, 26 lipca 2008

Stocznia złomowa

Stocznia złomowa (ship-breaking yard): ,,zakład zajmujący się rozbiórką i cięciem na złom jednostek pływających. W latach 70. i 80. w Polsce złomowanie odbywało się w porcie wojennym w Gdyni.'' Obecnie większość stoczni złomowych znajduje się w krajach takich jak Indie (Alang), Bangladesz (Chittagong), Pakistan (Gadani) i Chiny.

Praca zatrudnionych tam ludzi wygląda z grubsza tak jak niewolników przy budowie piramid w Egipcie. Wpisując Alang | Chittagong | Gadani + ship-breaking można znaleźć wiele materiałów -- w tym zdjęć -- na ten temat. Jest też trochę zdjęć na flickr.com. Natomiast na googleearth prawie nic nie ma -- jeżeli chodzi o fotografie, za to można obejrzeć jak to wszystko wygląda z lotu ptaka (pierwszy z poniżej zamieszczonych zrzutów z GE przedstawia Alang (lat=21.3847285601, lon=72.1748265443) -- wyróżnia się wrak ex brazylijskiego lekkiego lotniskowca Minas Gerais):

Google earth Google earth Google earth

czwartek, 24 lipca 2008

gpicsync

Znalazłem informację -- czytając pl.rec.foto.cyfrowa -- na temat innego programu do synchronizacji śladu ze zdjęciami, pn. gpicsync. Nie próbowałem ale jest chwalony. No i jest dostępny nie tylko w wersji nür für Windows.

poniedziałek, 21 lipca 2008

Katalog zdjęć umieszczonych na flickr.com

Od dłuższego już czasu przymierzałem się do zrobienia katalogu moich zdjęć umieszczonych na flickr.com. Ponieważ przed wysłaniem zdjęcia na flickr.com jego opis w postaci tagów i współrzędnych kopiuję do pliku ze zdjęciem (do odpowiednich pól EXIF) więc teoretycznie ów katalog można by zbudować wydłubując teraz to co trzeba z każdego pliku z osobna. Można by ale... Ale nie zawsze opis na flickr.com zgadza się z opisem lokalnym, bo jak coś spapram to już drugi raz nie ładuję tylko poprawiam ręcznie, bo kiedyś skrypt umieszczający zdjęcia działał inaczej, itd... Mówiąc krótko prościej będzie ściągnąć to wszystko z powrotem z flickr.com. Zrobiłem rozpoznanie w google i się okazało, że jest narzędzie pn. Net::Flickr::Backup służące dokładnie do tego co chcę zrobić: ściągnąć każde zdjęcie z konta na flickr.com wraz z opisem, który to opis zostanie zapisany w formacie RDF. Co dalej będzie z tym RDF-em -- zobaczymy jak się ściągnie.

Postępując zgodnie ze wskazówkami ze strony leobard.twoday.net zainstalowałem moduł Net::Flickr::Backup:


perl -MCPAN -e 'install Net::Flickr::Backup'
yum install perl-XML-LibXML perl-XML-LibXML-Common

Polecenie yum instaluje moduł XML::LibXML, niezbędny do działania Net::Flickr::Backup. W przypadku fedory moduł ten znajduje się w pakiecie perl-XML-LibXML. (Uwaga: zgodnie z tym co napisano na ww. stronie dla systemów Debianowych odpowiednikiem perl-XML-LibXML jest pakiet libxml-libxml-perl.) Na wszelki wypadek doinstalowałem też perl-XML-LibXML-Common, być może niepotrzebnie. Teraz przepisałem zawartość pliku backup-flickr.pl ze wspomnianej wyżej strony (a na tej stronie z kolei jest to przepisane z dokumentacji:-):


#!/usr/bin/perl
#
use Net::Flickr::Backup;
use Log::Dispatch::Screen;
use Config::Simple;

my $CFGFILE = "$ENV{HOME}/.flickr/flickr_backuprc";
my $cfg = new Config::Simple(filename=>"$CFGFILE");

my $flickr = Net::Flickr::Backup->new($cfg);
my $feedback = Log::Dispatch::Screen->new('name' => 'info', 'min_level' => 'info');

$flickr->log()->add($feedback);
$flickr->backup();

oraz utworzyłem w katalogu ~/.flickr/ plik konfiguracyjny flickr_backuprc o następującej zawartości:


#
# http://leobard.twoday.net/stories/4122767/
# ###
[flickr]
api_key=AAAAAAAAAAAAAAAAAAAA
api_secret=BBBBBBBBBBBBBBBBBB
auth_token=CCCCCCCCCCCCCC
api_handler=LibXML

[backup]
photos_root=/cmn/archive/Flickr/backup
scrub_backups=1
fetch_original=0
fetch_medium=0
fetch_square=1
force=0

[rdf]
do_dump=1
#rdfdump_root=/home/asc/photos

Uruchomienie perl backup-flickr.pl skończyło się wkrótce błędem dotyczącym kodowania:


Can't escape \x{0119}, try uri_escape_utf8() instead at \
/usr/local/share/perl/5.8.8/Net/Flickr/RDF.pm line 1497

Z opisu wynika, że coś jest nie tak w pliku RDF.pm. Przy bliższej inspekcji okazało się, że nazwy miejscowości, zawierające polskie znaki (np. Rębiechowo) nie mogą być zakodowane poprawnie przez procedurę uri_escape (Nazwy geograficzne są używane do tworzenia URI postaci: http://www.flickr.com/places/Poland/Pomorskie/Rębiechowo.)

Nie do końca jestem pewien czy dobrze robię ale wymieniłem (dwukrotnie) wywołanie procedury uri_escape na:


URI::Escape::uri_escape_utf8

Teraz program działa. Zostawiłem go na noc żeby zrobić kopię ale się okazało, że kopiowanie działa bardzo wolno. Przez noc ściągnęło się niewiele; potem jak wyłączyłem maszynę ponownie, to wprawdzie program nie ściągał danych drugi raz, ale samo sprawdzanie, w którym miejscu skończył zajęło mu okropnie dużo czasu. Ponieważ mam dostęp -- od jakiegoś czasu -- do tajnego serwera w pracy więc postanowiłem zrobić kopię wykorzystując ową maszynę.

Maszyna jest całkowicie out-of-date i dodatkowo zainstalowałem na niej Ubuntu... Zainstalowałem zaś Ubuntu z tej prozaicznej przyczyny, że nie mogłem znaleźć dysków z instalacją Fedory a jakąś instalkę Ubuntu akurat miałem pod ręką. Jak powszechnie wiadomo Ubuntu i Fedora różnią się nieco, w szczególności różnią się program służącym do instalowania i aktualizacji systemu.

Próba zainstalowania Net::Flickr::Backup tak jak w Fedorze, tj. poprzez perl -MCPAN -e '...' skończyła się błędem na etapie instalowania pakietu SOAP-Lite. Rozczarowujące, ale się nie załamałem:-) Zrobiłem upgrade a potem zainstalowałem dla pewności SOAP-Lite aptem (akurat był dostępny):


apt-get upgrade #
aptitude search SOAP-Lite # jaki pakiet zawiera SOAP-Lite ?
apt-get install libsoap-lite-perl # instaluję SOAP-Lite

Teraz polecenie


perl -MCPAN -e 'install Net::Flickr::Backup'

Zostało wykonanie pomyślnie. Poprawiam teraz uri_escape na uri_escape_utf8 w sposób opisany wyżej. Kopiuję do ~/.flickr/ plik flickr_backuprc także opisany wyżej.

Teraz mogę uruchomić:


./backup-flickr.pl > BACKUP_FLICKR.LOG 2>&1 &

Wygląda, że działa. I mogę się wylogować. Zobaczymy za parę dni czym to się wszystko skończy.

Dla przypomnienia, zapis >BACKUP_FLICKR.LOG 2>&1 wysyła strumienie stdout i stderr do pliku BACKUP_FLICKR.LOG.

Dopisane 4 sierpnia 2008: Bardziej fundamentalny problem się pojawił. Mianowicie, identyfikatory zdjęć (photo_id), które m.in. definiują adres URL do strony ze zdjęciem są całkowicie do kitu, np.:


<flickr:photo rdf:about="http://www.flickr.com/photos/20425995@N00/-1617918774">

Trudno nawet powiedzieć do jakiego zdjęcia odnosi się powyższe. Przy bliższym oglądzie stwierdziłem co następuje: photo_id są ok dla zdjęć wysłanych na flickr przed rokiem 2008. Zacząłem podejrzewać że gdzieś się ,,licznik przekręcił'', ale jak to się stało w językach beztypowych takich jak Perl? Ponieważ nie za bardzo mi się chciało dłubać w kodzie Net::Flickr::Backup zgłosiłem błąd korzystając -- zgodnie z tym co jest napisane w dokumentacji pakietu -- z http://rt.cpan.org. Do samego zgłoszenia błędu wystarczy napisać list na adres bug-Net-Flickr-Backup@rt.cpan.org (do komentowania trzeba się zarejestrować). Mój raport jest tutaj.

Wygląda, że nikt tego Net::Flickr::Backup nie używa, bo przez 12 dni pies z kulawą nogą się nie odezwał. Ponieważ sprawa nie dawała mi spokoju zacząłem dziś drążyć temat. W szczególności przyjrzałem się jak działa procedura backup zdefiniowana w Net/Flickr/Backup.pm. Podejrzenie padło na wiersz:


$self->log()->info(sprintf("process image %d (%s)",
$id, &_clean($node->getAttribute("title"))));

A konkretnie specyfikację %d funkcji sprintf. Hmm..., jaka jest maksymalna/minimalna wartość dla liczby całkowitej w Perlu? Doczytałem, że jest to system-dependent i można ją ustalić wykonując poniższy skrypt (znalezione na stronie www.issociate.de):


perl -le 'use POSIX; print for SHRT_MAX, INT_MAX, LONG_MAX, FLT_MAX, DBL_MAX;'

U mnie INT_MAX wynosi 2147483647 (tyle samo wynosi LONG_MAX btw) a przykładowo id tego zdjęcia to 2727375455. Ewidentnie 2727375455 jest większe od 2147483647, więc Net::Flickr::Backup nie może działać prawidłowo. Pozostało teraz ustalić jak jest definiowane photo_id w dokumentacji API flickr.com. Jakoś trudno znaleźć, ale jest po dłuższym szukaniu udało się ustalić co następuje: (por. tutaj): The Flickr API exposes identifiers for users, photos, photosets and other uniquely identifiable objects. These IDs should always be treated as opaque strings, rather than integers of any specific type. The format of the IDs can change over time, so relying on the current format may cause you problems in the future. .

Wymieniłem %d na %sNet/Flickr/Backup.pm oraz Net/Flickr/RDF.pm, wszędzie tam gdzie jest drukowane photo_id. Mam nadzieję, że nie pominąłem niczego i teraz da się zrobić poprawnie backup flikra.

niedziela, 20 lipca 2008

Tour de France

Zbliża się rocznica mojego blogowania. Prawie rok temu pisałem o TdF, Michaelu Rasmussenie i aferze w tym dopingowej na tym wyścigu. Tegoroczna pętla również przebiega w atmosferze problemów z dopingiem. Spojrzałem na zestawienie tych co byli na topie w ostatnich pięciu latach: Jan Ullrich, Aleksander Winokurow, Ivan Basso i Floyd Landis -- wszyscy dyskwalifikacja za doping. Andreas Klöden i Alberto Contador trefni bo się zapisali do Astany. Trefni to znaczy nic im nie udowodniono ale organizatorzy arbitralnie uważają grupę Astana za niegodną startu w TdF. Michael Rasmussen, któremu też nic nie udowodniono, ciągle nie ma podpisanego kontraktu z jakąkolwiek grupą. Razem podpadniętych jest zatem 7. Pozostali niezłapani to: Cadel Evans, Levi Leipheimer, Oscar Pereiro, Carlos Sastre. Raptem czterech. Chcesz mieć kłopoty -- startuj w TdF.

EPOPiryna
Goździkowa poleca!!! EPOpiryna

Nie oglądam TdF namiętnie. Większość etapów jest zwyczajnie i jak zwykle nudna. W tym roku oglądałem etapy 9 i 10. Na 9 wspaniale zaatakował pod Col d'Aspin Ricco. Na szczycie miał ponad minutę przewagi, którą utrzymał na 25 km zjazdach do mety. Etap 10 z kolei kończył się podjazdami pod słynny Col du Tourmalet i finalnym podjazdem pod Hautacam (10 km). Wygrał Leonardo Piepoli z tej samej grupy co Ricco (Saunier Duval-Scott). No i co? No i Ricco oraz ten drugi już nie jadą. Doping. Ale lipa... W polskiej Wikipedii też się chyba zniechęcili bo opis wyścigu kończy się właśnie na tym feralnym 10 etapie z 14 lipca.

Wczoraj fantastycznie wygrał finisz z grupy Freire. Spokojnie wyczekał, potem na kole bodajże Zabela podciągnął się bliżej i wreszcie poprawił, jak to mówią. Świetnie pokazane w TV z helikoptera -- jeżeli pojawi się na YouTube (na razie nie ma), to zachęcam do obejrzenia.

A dziś taki sobie średnio trudny etap. Wprawdzie kolarze wjadą na Col Agnel (2744 mnpm), ale to będzie względnie blisko startu więc szaleństw nie będzie. Potem długi zjad prawie do mety. Przed metą górka, ale nie za wysoka, więc różnic dużych nie należy oczekiwać... Wtorek i środa będą dużo trudniejsze. Zwłaszcza środa (Embrun--L'Alpe-d'Huez), bo 1) po wtorku, 2) aż 210 km, 3) dwa niebotyczne podjazdy (Col du Galibier oraz Col de la Croix de Fer) 4) na koniec 14 km decydującego podjazdu pod Alpe d'Huez.

BTW jakby ktoś nie wiedział to L'Alpe-d'Huez należy wymawiać jako Alp diłesla Croix de Fer to jest to samo co Eisernes Kreuz w j. niemieckim. Napis na zdjęciu obok, który NB uważam za b. śmieszny, został namalowany przez anonimowego kibica w czasie Tour de Pologne 2006. Zdjęcie zamieszczono w Magazynie Rowerowym 11--12/2006 -- reprodukcja niestety bez zezwolenia. Jako okoliczność łagodzącą wskazuję na niską jakość/rozdzielczość reprodukcji. Oryginał w formacie A3 w MR.

Dopisane 20 lipca 2008 (po południu): Ah zapomniałem w swoich statystykach o tym kosmonaucie Armstrongu. A więc do niezłapanych dopisuję Lance'a Armstronga, co daje w sumie pięciu. A na Wikipedii się nie zniechęcili, bo dziś ktoś dopisał relacje z trzech następnych etapów.