Damián Avila: RISE 4.0.0b1 is available, please test it!

Quick post! I have beta packages available for you to test RISE, if you can test it that would be awesome!!

In case you don't know about it, with RISE you get your Jupyter notebook rendered as a Reveal.js-based slideshow, where you can execute code on the fly or show to the audience whatever you can show/do inside the notebook itself (but in a "slidy" way).

How you can get it?

Read more… (1 min remaining to read)

Marcos Dione: adding-columns-from-osm-to-postgis-with-osmium

My latest Europe import was quite eventful. First, I run out of space several times during the import itself, at indexing time. The good thing is that, if you manage to reclaim some space, and reading a little of source code[1], you can replay the missing queries by hand and stop cursing. To be fair, osm2pgsql currently uses a lot of space in slim+flat-nodes mode: three tables, planet_osm_node, planet_osm_way and planet_osm_relation; and one file, the flat nodes one. Those are not deleted until the whole process has finished, but they're actually not needed after the processing phase. I started working on fixing that.

But that was not the most difficult part. The most difficult part was that I forgot, somehow, to add a column to the import.style file. Elevation, my own style, renders different icons for different types of castles (and forts too), just like the Historic Place map of the Hiking and Bridle map[2]. So today I sat down and tried to figure out how to reparse the OSM extract I used for the import to add this info.

The first step is to add the column to the tables. But first, which tables should be impacted? Well, the line I should have added to the import style is this:

node,way   castle_type  text         polygon

That says that this applies to nodes and ways. If the element is a way, polygon will try to convert it to a polygon and put it in the planet_osm_polygon table; if it's a node, it ends in the planet_osm_point table. So we just add the column to those tables:

ALTER TABLE planet_osm_point   ADD COLUMN castle_type text;
ALTER TABLE planet_osm_polygon ADD COLUMN castle_type text;

Now how to process the extract? Enter pyosmium. It's a Python binding for the osmium library with a stream-like type of processing à la expat for processing XML. The interface is quite simple: one subclasses osmium.SimpleHandler, defines the element type handlers (node(), way() and/or relation()) and that's it! Here's the full code of the simple Python script I did:

#! /usr/bin/python3

import osmium
import psycopg2

conn= psycopg2.connect ('dbname=gis')
cur= conn.cursor ()

class CastleTypes (osmium.SimpleHandler):

    def process (self, thing, table):
        if 'castle_type' in thing.tags:
                name= thing.tags['name']
            # osmium/boost do not raise a KeyError here!
            # SystemError: <Boost.Python.function object at 0x1329cd0> returned a result with an error set
            except (KeyError, SystemError):
                name= ''
            print (table, thing.id, name)

            cur.execute ('''UPDATE '''+table+
                         ''' SET castle_type = %s
                            WHERE osm_id = %s''',
                         (thing.tags['castle_type'], thing.id))

    def node (self, n):
        self.process (n, 'planet_osm_point')

    def way (self, w):
        self.process (w, 'planet_osm_polygon')

    relation= way  # handle them the same way (*honk*)

ct= CastleTypes ()
ct.apply_file ('europe-latest.osm.pbf')

The only strange part of the API is that it doesn't seem to raise a KeyError when the tag does not exist, but a SystemError. I'll try to figure this out later. Also interesting is the big amount of unnamed elements with this tag that exist in the DB.

[1] I would love for GitHub to recognize something like https://github.com/openstreetmap/osm2pgsql/blob/master/table.cpp#table_t::stop and be directed to that method, because #Lxxx gets old pretty quick.

[2] I just noticed how much more complete those maps are. more ideas to use :)

openstreetmap gis python

Juanjo Conti: Goodreads review: Acerca de Roderer (Guillermo Martínez)

Me gustó, pero no tanto. Se nota que es una primera novela, con partes que sobran y desarrollos apresurados.

Por ejemplo, el capítulo sobre la chica que muere de anorexia nerviosa y el capítulo en el que el protagonista va a pelear a Malvinas sin que antes se hubiese si quiera mencionado que el país estaba bajo una dictadura.

Me gustó toda la descripción del pueblo y las personas que lo habitan.

Rating: 3/5

Original: https://www.goodreads.com/review/show/1723954363

Marcos Dione: our-man-in-marseille

Remember this?

For a few months now I've been trying to have a random slideshow of images. I used to do this either with kscreensaver, which for completely different reasons I can't use now, or xscreensavers' glslideshow, which, even when I compiled it by hand, I can't find the way to give it the root dir of the images. So, based on OMIT, I developed my own.

The differences with OMIT are minimal. It has to scan the whole tree for finding the appropriate files (its definition of "appropriate" could be improved, it's true); it goes into full screen mode with black background; and it (more) properly handles EXIF rotation[1]. All that in 176 LOCs, including proper licensing (GPLv3), and developed in one day and refined the next one.

One interesting thing I found out is that pyexiv2 is deprecated, with is last release in 2011 (!!!). What this new app uses is its recommended replacement, gexiv2.

So, there you are. Like OMIT, it's in PyQt4, but this time in Python3 (that's why I used gexiv2 instead). Its TODO includes porting it to PyQt5 and a few other things. You can grab it here. I plan to do a proper release soon, but for the moment just drop it in your PATH and be happy with it.

[1] http://www.daveperrett.com/articles/2012/07/28/exif-orientation-handling-is-a-ghetto/

omit omim pykde python

Facundo Batista: Redes sociales

Desde que existen sociedades, desde que existen comunidades, desde que existe acción colectiva, existen redes sociales.

Hoy existen plataformas que median esas relaciones sociales, y ahí lo que existen son empresas haciendo lucro y haciendo negocio con las redes sociales.

Entonces nosotros preferimos separar aquellas plataformas que son empresas con fines de lucro, llámese por ejemplo Facebook, de las redes sociales que nos permiten construir colectivamente, construir en comunidad.

Hay que recuperar las redes sociales para la ciudadanía, el concepto de red social. Red social no es Facebook, red social somos nosotros hablando, somos nosotros organizándonos, usemos los medios que usemos.

Por Bea Busaniche, miembro de la Fundación Via Libre, en el capítulo "Ciberactivismo" del programa "En el medio digital" para el Canal Encuentro.

Facundo Batista: Europython 2016, la conferencia

El evento estuvo dividido principalmente en tres partes, tutoriales para principiantes, conferencia propiamente dicha, y los sprints.

A los tutoriales (Beginners day, y Django girls), que duraban un día, no fui.  La conferencia fue de lunes a viernes. Y los sprints fueron sábado y domingo.  Del primer día de conferencia ya les conté, y el domingo estuve viajando. El resto, se los cuento acá :)

Charlas interesantes

Recopilación de lo que más me gustó de la conferencia... ojo, en algunos casos incluyo links a los videos o presentaciones mismas, en otros no porque me dió paja buscarla, pero tienen que estar :)

Por lejos, la mejor Keynote fue la de Jameson Rollins, "LIGO: The Dawn of Gravitational Wave Astronomy", aunque también estuvo buena la de Naomi Ceder, "Come for the Language, Stay for the Community". Tercera podríamos poner "Scientist meets web dev: how Python became the language of data", por Gaël Varoquaux. El resto me aburrió un poco, o no me interesó tanto.

LIGO is a...

Otras charlas que me gustaron fueron "High Performance Networking in Python" de Yury Selivanov, "Build your first OpenStack application with OpenStack PythonSDK" por Victoria Martinez de la Cruz, "Implementación de un Identificador de Sonido en Python" por Cameron Macleod, "FAT Python: a new static optimizer for Python 3.6" de Victor Stinner, "CFFI: calling C from Python" de Armin Rigo, "The Gilectomy" de Larry Hastings, "A Gentle Introduction to Neural Networks (with Python)" de Tariq Rashid, y "Music transcription with Python" de Anna Wszeborowska.

De esta última charla me quedé con el proyecto a futuro (ya lo anoté, está en la posición 1783461° entre otros proyectos) de mostrar en tiempo real, usando Bokeh, la info que levanta y las transformaciones que va haciendo.

Imagen típica de Bilbao

También quiero resaltar dos lightning talks: a Armin Rigo mostrando un "Reverse debugging for Python", y una de alguien que no me acuerdo mostrando "A better Python REPL".

Mis presentaciones

Ya les hablé de la charla que había dado el lunes, pero aprovecho y les dejo el video de la misma.

El martes dí Entendiendo Unicode, en castellano. Fue la 12° vez que la doy, y me podrán decir "dejá de robar con la misma charla"... qué quieren que les diga, el público se renueva. Yo también a veces pienso si no será demasiado, ¡pero a la gente le gusta y le sirve! Una decena de personas me saludaron y me comentaron lo buena y lo útil que fue la charla. Así que nada, la seguiré ofreciendo en próximas conferencias, :). El video, acá.

Espacio común de trabajo

Además de esas dos presentaciones "largas", dí dos lightning talks. La primera sobre fades; no es la primera vez que la doy, pero la había renovado y traducido al inglés, y estuvo muy bien. La segunda fue sobre Python Argentina. La hice el mismo viernes, a los apurones, pero a la gente le gustó mucho (me sorprendió la cantidad de veces que se rieron en esos cinco minutos (cinco minutos que tuve que pelear, como ven en el video, porque me querían dar dos, luego la confusión de que yo iba a hablar de una PyCon).


El sábado, estuve sprinteando, trabajando con fades, más que nada ofreciendo ayuda a gente que quería usarlo o que querían enterarse más sobre el proyecto. Incluso se acercó alguien con un detalle, lo charlamos, lo solucionamos y hasta hice un pull request.


Ese sábado era mi última noche en Bilbao. Medio coordinamos con Juan Luis y fuimos a cenar pinchos con otras personas, luego por una cerveza. Y cuando estaba cerrando la noche, tipo once y media, me comentaron de una zona en la ciudad donde hay toda una movida heavy y punk.

No me la podía perder.

Así que nos fuimos cinco personas hasta allí, saltamos por tres o cuatro bares, tomando algo en cada uno, escuchando muy buena música, terminando en un antro de mala muerte, jugando metegol, pasando música que elegíamos nosotros, y disfrutando mucho.

En un bar punkie

A eso de las dos y media dí por concluido el paseo, porque a las cuatro me pasaba a buscar el taxi, así que con Oriol (uno de los chicos) nos tomamos un taxi, llegué a la habitación, terminé de armar todo, me pegué una ducha, dejé las llaves en la mesa de la cocina y arranqué las 23 horas de viaje que me iban a reecontrar con mi familia :)

Todas las fotos de la conferencia y Bilbao, acá.

Marcos Dione: osm-centerlines-two-days-after

In this last two days I've been expanding osm-centerlines. Now it not only supports ways more complex than a simple rectangle, but also ones that lead to 'branches' (unfortunately, most probably because the mapper either imported bad data or mapped it himself). Still, I tested it in very complex polygons and the result is not pretty. There is still lots of room for improvements.

Unluckily, it's not as stand alone as it could be. The problem is that, so far, the algos force you to provide now only the polygon you want to process, but also its skeleton and medial. The code extends the medial using info extracted from the skeleton in such a way that the resulting medial ends on a segment of the polygon, hopefully the one(s) that cross from one riverbank to another at down and upstream. Calculating the skeleton could be performed by CGAL, but the current Python binding doesn't include that function yet. As for the medial, SFCGAL (a C++ wrapper for CGAL) exports a function that calculates an approximative medial, but there seem to be no Python bindings for them yet.

So, a partial solution would be to use PostGIS-2.2's ST_StraightSkeleton() and ST_ApproximateMedialAxis(), so I added a function called skeleton_medial_from_postgis(). The parameters are a psycopg2 connection to a PostgreSQL+PostGIS database and the way you want to calculate, as a shapely.geometry, and it returns the skeleton and the medial ready to be fed into extend_medials(). The result of that should be ready for mapping.

So there's that. I'll be trying to improve it in the next days, and start looking into converting it into a JOSM plugin.

openstreetmap gis python

Marcos Dione: deriving-centerlines-from-riverbanks-without

For a long time now I've been thinking on a problem: OSM data sometimes contains riverbanks that have no centerline. This means that someone mapped (part of) the coasts of a river (or stream!), but didn't care about adding a line that would mark its centerline.

But this should be computationally solvable, right? Well, it's not that easy. See, for given any riverbank polygon in OSM's database, you have 4 types of segments: those representing the right and left riverbanks (two types) and the flow-in and flow-out segments, which link the banks upstream and downstream. With a little bit of luck there will be only one flow-in and one flow-out segment, but there are no guarantees here.

One method could try and identify these segments, then draw a line starting in the middle of the flow-in segment, calculating the middle by traversing both banks at the same time, and finally connect to the middle for the flow-out segment. Identifying the segments by itself is hard, but it is also possible that the result is not optimal, leading to a jagged line. I didn't try anything on those lines, but I could try some examples by hand...

Enter topology, the section of maths that deals with this kind of problems. The skeleton of a polygon is a group of lines that are equidistant to the borders of the polygon. One of the properties this set of lines provides is direction, which can be exploited to find the banks and try to apply the previous algorithm. But a skeleton has a lot of 'branches' that might confuse the algo. Going a little further, there's the medial axis, which in most cases can be considered a simplified skeleton, without most of the skeleton branches.

Enter free software :) CGAL is a library that can compute a lot of topological properties. PostGIS is clever enough to leverage those algorithms and present, among others, the functions ST_StraightSkeleton() and ST_ApproximateMedialAxis(). With these two and the original polygon I plan to derive the centerline. But first an image that will help explaining it:

The green 'rectangle' is the original riverbank polygon. The thin black line is the skeleton for it; the medium red line is the medial. Notice how the medial and the center of the skeleton coincide. Then we have the 4 branches forming a V shape with its vertex at each end of the medial and its other two ends coincide with the ends of the flow in and flow out segments!

So the algorithm is simple: start with the medial; from its ends, find the branches in the skeleton that form that V; using the other two ends of those Vs, calculate the point right between them, and extend the medial to those points. This only calculates a centerline. The next step would be to give it a direction. For that I will need to see if there are any nearby lines that could be part of the river (that's what the centerline is for, to possibly extend existing rivers/centerlines), and use its direction to give it to the new centerline.

For the moment the algorithm only solves this simple case. A slightly more complex case is not that trivial, as skeletons and medials are returned as a MultiLineString with a line for each segment, so I will have to rebuild them into LineStrings before processing.

I put all the code online, of course :) Besides a preloaded PostgreSQL+PostGIS database with OSM data, you'll need python3-sqlalchemy, geoalchemy, python3-fiona and python3-shapely. The first two allows me to fetch the data from the db. Ah! by the way, you will need a couple of views:

CREATE VIEW planet_osm_riverbank_skel   AS SELECT osm_id, way, ST_StraightSkeleton (way)      AS skel   FROM planet_osm_polygon WHERE waterway = 'riverbank';
CREATE VIEW planet_osm_riverbank_medial AS SELECT osm_id, way, ST_ApproximateMedialAxis (way) AS medial FROM planet_osm_polygon WHERE waterway = 'riverbank';

Shapely allows me to manipulate the polygonal data, and fiona is used to save the results to a shapefile. This is the first time I ever use all of them (except SQLAlchemy), and it's nice that it's so easy to do all this in Python.

openstreetmap gis python

Facundo Batista: Traveller cheques cheques cheques!

Hace catorce años, unos meses antes de viajar a Italia (como parte de mi Master en Ingeniería de la Innovación) fui a un banco en la city porteña y compré 1100 euros en American Express Traveler Checks.

¿Para qué? Bueno, era la primera vez que iba a Europa (la primera vez que salía del país, si no contamos las vacaciones en Fray Bentos, Uruguay), y tenía que llevar bastante dinero para vivir las primeras semanas, y los travelers checks tienen la característica (teoricamente) de que si los perdés o te los roban, American Express te los puede volver a dar, no importa donde estés.

En su momento, en Italia, cambié 800 euros, y como luego empecé a recibir el dinero de la Universidad (viáticos), me quedaron 300 sin cambiar. Volví a casa, guardé eso para un futuro donde los necesitara. Pero cuando volví a viajar a Europa ya tenía una tarjeta de crédito que funcionaba fuera de Argentina, así que no me llevé los cosos esos, sino que quedaron ahí.

Hace unos años decidí sacármelos de encima, pero no los quería cambiar en Argentina, porque no me iban a dar euros, así que esperé a volver a viajar a Europa. Y llegó Europython, y acá estoy en Bilbao, así que decidí irlos a cambiar al banco.

Catorce años después de comprarlos.

Así que almorcé rápido, me cargué la mochila, y caminé unas 10 cuadras hasta el centro de la ciudad. Fuí a un Banco Santander, hablé con una persona, puso cara de no saber qué eran los Traveler Checks, y me dijo que hablara con la cajera. Fui con la cajera y me dijo que ahí no los cambiaban, que vaya a la casa central (que quedaba ahí a la vuelta).

Caminé dos cuadras, entré, averigüé, me dijeron que hable con el Jefe de Cajas, el que me dijo que el Banco Santander ya no cambiaba "de eso".

En la esquina había un BBVA, así que entré y pregunté. Me dijo (con bastante seguridad) que Traveler Checks sólo cambiaban en la casa central (Gran Via 12, enfrente del Corte Inglés). Caminé unas 7 cuadras hasta ahí, entré, pregunté, me mandaron a las cajas.

La cajera puso cara de "queloqué?", le preguntó al de al lado, que llamó a uno de un escritorio, que dijo "sí, esto me parece que lo aceptamos". Se sentó en la computadora de la señora, y empezó a (por lo que veía y suponía yo) navegar ventanas que él nunca había visto en el sistema interno que usan.

En un momento me pidió el pasaporte, le sacó fotocopia, luego lo escaneó, luego firmé los traveler checks y les puse la fecha. En ese momento (unos diez minutos luego de haber empezado el trámite) yo pensé "listo, ya está, esto es la confirmación de que los aceptan, porque ya no puedo llevarlos a otro lado ni nada".

El tipo siguió cargando datos, hasta que en un momento le dió "servicio no disponible". Lo consultó con uno, con otro, volvió a intentarlo, lo mismo. Llamó a Soporte (que por lo visto puede entrar y ver la misma ventana que él estaba usando, al mismo tiempo que él la estaba usando), le contestó veinte preguntas, y volvió a hacer TODO de nuevo.

Cortó, esperó, lo llamaron, volvió a probar algo. Me enteré que la chica de soporte había llamado a Soporte nivel 2. Esperamos. Lo volvieron a llamar. Hizo otra cosa, le pasaron un valor hardcodeado, ahí pudo avanzar y tuvo un "código de autorización". Iupi!

Pero siguió una ventana más, y "servicio no disponible". Volvió a intentar todo, lo mismo. A esta altura el banco había cerrado hace 10 minutos, toda la gente se estaba yendo, los otros cajeros cerrando las cajas, etc.

Lo volvieron a llamar, era Soporte nivel 3. Volvieron a intentar cosas, nada. Vino otra chica (a esta altura quedábamos solamente cuatro en todo el banco). Volvió a probar algo, le dió error y un número de American Express. Llamó (acá me enteré mucho porque puso el móvil en speaker), le pidieron todos los datos (míos, de los cheques, etc), hasta que le dijeron que los cheques estaban autorizados (con el código que ya sabíamos), así que efectivamente era un problema del sistema del banco.

Esperamos diez minutos más, el flaco llamó a soporte de nuevo, le dijeron que estaba en Soporte nivel 4 (!!!), que lo iban a llamar.

Siguieron probando cosas, hasta que el flaco se cansó, agarró y me dió 300 euros (teoricamente yo tenía que pagar una comisión, pero nadie sabía cuanto), y me fui.

Dos horas y media después de entrar al banco :/