Meaning Tool

jueves, 24 de septiembre de 2009
Popego es un prometedor startup Argentino encabezado por Santiago Siri, que si mis cálculos no fallan es además el hermano del talentoso humorista Liniers. La idea básica del sitio web es que utilizando técnicas de aprendizaje automático puede reconocer los intereses de sus usuarios (consultando por ejemplo tu Flickr, tu blog o tu Twitter) y recomendar contenidos nuevos de la web que se relacionen con dichos intereses. La idea sin duda es interesante, y con la creciente proliferación de contenidos creados por usuarios en la red, la organización y filtrado de los mismos se vuelve muy trabajosa.

Conocí Popego cuando un compañero de la facultad, Pablo Ridríguez Zivic (que en su momento era ayudante en mi cursada de Algoritmos 2), entró a trabajar ahí. Popego fue sponsor de la PyCon y tuve la oportunidad de charlar con Francisco, uno de sus empleados en el stand que habían armado.

La novedad

Francisco estaba presentando Meaning Tool, una herramienta derivada de la investigación y desarrollo realizados para Popego y que ahora estará disponible para su uso mediante una API por otros desarrolladores y sitios web. Meaning Tool es (por el momento) una herramienta de clasificación automática de contenido, que se diferencia básicamente de todo lo que yo conocía en que es amigable y puede ser utilizada por cualquiera.

La idea de Meaning Tool es que uno construye un listado de categorías y entrena al sistema con contenidos categorizados para que éste aprenda a reconocer qué temas son tratados por un determinado contenido. Por ejemplo, esta herramienta podría servir para que los posts de mi blog se etiqueten automáticamente en las distintas categorías sin que tenga que hacerlo yo manualmente. Si bien me ahorraría un poco de trabajo, la verdadera magia del sistema está en que puede aplicarse sobre cantidades masivas de contenido (a diferencia de los miserables 2 posts por año de este blog), y las posibilidades son inmensas.

Sin ir muy lejos, el negocio de publicidad de Google comenzó porque tenían a disposición las herramientas de procesamiento semántico que le permitían (y le permiten) colocar avisos publicitarios relacionados con el contenido de las páginas web en qué aparecían. Así, no te encontrás con que mi blog te muestra un aviso sobre licuadoras, sino temas relacionados con el contenido que yo escribo, lo que aumenta muchísimo el impacto de la publicidad. Cosas como esta ahora se democratizan gracias a Meaning Tool, que las pone al alcance de muchos más desarrolladores.

Una ¿loca? opción electoral en la UBA

sábado, 19 de septiembre de 2009
Como todos los años, la última semana se eligieron en Exactas los representantes tanto de estudiantes como de graduados para el Consejo Directivo. Dicho consejo se compone por una mitad de representantes de profesores, y una cuarta parte tanto para alumnos como para graduados. El panorama como siempre es colorido (en cuanto a afiches y trifulcas), y siempre presente está el infaltable acoso electoral, también conocido como ¿ya votaste?


NO es democracia

Este año se presentó a elecciones un grupo de personas con una propuesta particular, la primera que me toca vivir de lo que podríamos llamar Gobierno 2.0. El argumento esgrimido es simple: hoy por hoy, la informática hace que la democracia directa vuelva a ser practicable.

En Atenas las cosas eran más bien simples, dado que las personas con voz y voto constituían un grupo relativamente reducido que se reunía periódicamente para votar a mano alzada. Con el paso del tiempo, la democracia representativa se volvió más viable, tanto por las ventajas del voto secreto como por la dificultad logística de poner a varios millones de personas a votar en un mismo cuarto. Hoy por hoy, la revolución en las comunicaciones hace que podamos sobrellevar estas dos cuestiones y así evitar la problemática de la representación indirecta.

Bajo el curioso lema de No es democracia, el "No" se compromete a organizar un sitio web donde los alumnos de la facultad puedan votar de forma directa en cada una de las cuestiones que se discuten en el consejo directivo. Dada una resolución, los integrantes de dicho foro podrán votar y argumentar a favor o en contra de las medidas a tomar. Finalmente, los consejeros electos del NO asisten a la reunión de consejo directivo, leen los argumentos concensuados en el foro y votan de la manera en que la elección online lo indique1.

Con un sistema de automoderación (hoy por hoy bastante común en la web), los mejores argumentos flotan sobre los peores y la gente puede acceder a la información necesaria para decidir de forma efectiva. En teoría. Asimismo, plantean soluciones técnicas a los problemas usualmente relacionados con la organización de un comicio, desde la integridad de los votos hasta la seguridad del sistema, pasando por las garantías de anonimato para los votantes.

Pero...

No hace falta mucho cráneo para llenar un par de pliegos con potenciales cosas que pueden salir mal en un proyecto de este tipo. Sin duda el problema primordial es que la política universitaria se caracteriza por sobre todas las cosas por la omnipresente apatía del alumnado. Darle la oportunidad a la gente de que tome decisiones potencialmente críticas con la misma liviandad que decide ¿qué Pokemon sos?2 en un jueguito del Facebook puede no ser lo más feliz.

Por otra parte, cualquier comunidad online de tamaño significativo, aún sin intereses profundos de por medio (por ejemplo, un foro de jueguitos o de fotografía), se torna en todos los casos que pude observar en un pequeño caos similar a un programa de chimentos. En general, la gente es muy susceptible y poco cuidadosa con las cosas que escribe, y enseguida las aguas se caldean.

Y sin embargo...

Es innegable que la propuesta es intrigante, y la muestra de estudio es casi utópica para un experimento sociológico como este: un grupo bastante amplio de gente bastante bien calificada en el uso tanto de la tecnología como del marote. Sin más, el solo compromiso de que las discusiones del consejo directivo se publiquen regularmente en Internet para que los alumnos puedan seguirlas con facilidad sin asistir a rallys ni instancias similares, es un gran paso en la dirección correcta.

Al momento de escribir estas líneas, no tengo ni idea de como salieron las elecciones. Pero no puedo negar que estoy intrigado. Hay mucha más información sobre este tema en Meta Government.

1 Para los que estén familiarizados con el movimiento del software libre, es destacable el paralelismo entre el procedimiento de "usar un representante como medio para lograr la democracia directa", y la forma en que la licencia GPL utiliza la legislación sobre copyright para ceder derechos en lugar de restringirlos.

2 Ejemplo cortesía de Manuel Giménez.

Actualización: resultados de la elección


Me quedaré con la intriga al menos hasta el año próximo!

Ilustraciones de Cristoph Niemann

viernes, 18 de septiembre de 2009
Me topé en la web con el trabajo de Cristoph Niemann, un diseñador gráfico e ilustrador americano muy talentoso. Tiene un blog gráfico en el sitio web del New York Times, donde regularmente muestra sus "editoriales". Son muy simpáticas sus creaciones, y me recuerda inevitablemente al espíritu juguetón que tanto me gusta de Liniers.


Como armar un gateway SMS con tu celular

jueves, 17 de septiembre de 2009
Estuve averiguando y al parecer la única manera de hacer una aplicación que reciba mensajes de texto y pueda responder a los mismos, es apersonarse muy bien trajeado en una empresa que brinde servicios de alertas SMS y cuestiones afines, y firmar un jugoso contrato para obtener el muy preciado servicio. Ojo, enviar mensajes SMS desde una computadora es mucho más sencillo: la mayoría de los carriers permiten hacerlo enviando un correo electrónico a una dirección conveniente. El problema está en recibir los benditos textos: ¿qué pasa si quiero hacer el Twitter argentino, y quiero que mis usuarios posteen actualizaciones desde su celular? ¿qué pasa si quiero preguntarle a mi máquina como va la descarga de mi torrent?

El servicio necesario para enviar o recibir SMS desde una computadora conectada a Internet se denomina gateway SMS, y si bien el servicio de envío lo proveen las mismas compañías de telefonía celular, la recepción es más delicada, ya que nadie provee un servicio de acceso sencillo para forwardearme los mensajes que lleguen a un determinado número a mi aplicación. A continuación voy a explicar como se puede fabricar un gateway SMS fatto in casa utilizando un celular común y silvestre.

Ingredientes
  • Una computadora con un adaptador Bluetooth (o no, ver nota a continuación)
  • Un celular con Bluetooth
  • Python + python-bluez
En mi caso utilicé mi maltrecho Nokia 6103, y la solución que propongo debería funcionar en cualquier celular con dos dedos de frente (o sea, la gran mayoría de los Nokia y Sony Ericcsson, y tal vez algún que otro Motorola).

Técnicamente no es necesario usar bluetooth puesto que lo que vamos a hacer es enviar comandos AT estándar sobre un enlace serial. Esto se puede hacer tanto por Bluetooth como con el cable adaptador USB o serial correspondiente, artículo del que no dispongo. Debería ser trivial portar las ideas de mi programa para funcionar con un enlace cableado.

Como sistema operativo utilicé Ubuntu 9.04, pero debería funcionar en casi cualquier sistema actual puesto que las librerías necesarias funcionan también en Windows.

Pasos a seguir

El funcionamiento del gateway que propongo es sencillo; se conecta al teléfono mediante la conexión inalámbrica y puede realizar una de tres acciones:
  • Enviar un mensaje de texto a un número determinado
  • Obtener todos los mensajes de texto almacenados en el teléfono
  • Borrar todos los mensajes de texto almacenados en el teléfono
El único paso manual consiste en identificar la dirección de hardware del teléfono para indicarla al conectarse. En Linux esto puede hacerse habilitando Bluetooth tanto en el celular como en la computadora, activando en el teléfono el modo "visible", y finalmente ejecutando el comando hcitool scan.

Tras ingresar dicho valor en el script que pongo a continuación, se realizará la conexión con el celular. Es probable que el celular requiera una aprobación manual para cada vez que se realice una conexión (un mensaje del tipo "¿Desea conectarse con el dispositivo XXX?"). Como esto no es muy cómodo en un servidor, en los teléfonos Nokia esta opción puede desactivarse una vez que se ha establecido la conexión (en el apartado "Conexiones activas" del menú Bluetooth, se puede indicar que un cierto dispositivo no requiere confirmación).

El código que adjunto a continuación hace el resto del trabajo, gran parte del cual consiste en parsear el extraño formato PDU en que el teléfono entrega los mensajes de texto cuando se le pide. El código que hace esto está fuertemente basado en smspdu, que modifiqué para hacer un poco más amigable.

Seguir leyendo >>

gateway.py

#!/usr/bin/python

#Copyright (c) 2009 Gonzalo Sainz-Trapaga
#Permission is hereby granted, free of charge, to any person obtaining a copy
#of this software and associated documentation files (the "Software"), to deal
#in the Software without restriction, including without limitation the rights
#to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
#copies of the Software, and to permit persons to whom the Software is
#furnished to do so, subject to the following conditions:
#
#The above copyright notice and this permission notice shall be included in
#all copies or substantial portions of the Software.
#
#THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
#IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
#FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
#AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
#LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
#OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
#THE SOFTWARE.

import bluetooth
import select
import pdu

DEBUG = False

class Nokia6103:
    def __init__(self, hwaddr, port):
        self.sockfd = bluetooth.BluetoothSocket(bluetooth.RFCOMM)
        self.sockfd.connect((hwaddr, port))
        self._send('ATZ')

    def _log(self, s):
        if DEBUG:
            print s

    def _read(self):
        i = [self.sockfd]
        w = []
        e = [self.sockfd]
        out = ''
        while True:
            ir, wr, er = select.select(i, w, e, 3)
            if len(ir) == 0:
                self._log("Select: espera finalizada - saliendo.")
                break
            if len(er) > 0:
                self._log("Select: condicion de excepcion - saliendo.")
                break
    
            out += i[0].recv(1000)
            if out.find('OK\r\n') != -1:
                self._log("Select: OK alcanzado - saliendo.")
                break
        return out
    
    
    def _send(self, s):
        self.sockfd.send('%s\r' % s)
        out = self._read()
        self._log(out)
        return out

    def sendSMS(self, num, txt):
        self._send('AT+CMGF=1')
        self._send('AT+CMGS="%s"' % num)
        self.sockfd.send(txt + "\n")
        self.sockfd.send(chr(26))

    def getAllSMS(self):
        s = self._send('AT+CMGL=4')
        lines = s.split('\r\n')
        lines.pop(0)
        msgs = []
        for i, msg in enumerate(lines):
            if i % 2 == 0:
                if not msg.startswith('+CMGL'):
                    break
            else:
                msgs.append(pdu.decodePdu(msg))
        return msgs

    def deleteAllSMS(self):
        self._send('AT+CMGD=1,4')

    def close(self):
        self.sockfd.close()

if __name__ == '__main__':
    port = 1
    hwaddr = '00:19:B7:XX:XX:XX'
    n = Nokia6103(hwaddr, port)
    print n.sendSMS('+541150501234', 'Mensaje de prueba!')
    print n.getAllSMS()

pdu.py

#Copyright (c) 2009 Eric Gradman, Gonzalo Sainz-Trapaga
#Permission is hereby granted, free of charge, to any person obtaining a copy
#of this software and associated documentation files (the "Software"), to deal
#in the Software without restriction, including without limitation the rights
#to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
#copies of the Software, and to permit persons to whom the Software is
#furnished to do so, subject to the following conditions:
#
#The above copyright notice and this permission notice shall be included in
#all copies or substantial portions of the Software.
#
#THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
#IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
#FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
#AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
#LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
#OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
#THE SOFTWARE.
from cStringIO import StringIO
from math import ceil
from binascii import unhexlify, hexlify
from itertools import cycle
from datetime import datetime


def decodePdu(s):
    s = unhexlify(s)
    d = StringIO(s)

    # parse SMSC information
    p = {}
    p['smsc_len'] = d.read(1)
    p['type_of_address'] = d.read(1)
    p['sc_num'] = unsemi(d.read(ord(p['smsc_len'])-1))

    p['msg_type'] = d.read(1)
    p['address_len'] = d.read(1)
    p['type_of_address'] = d.read(1)

    p['sender_num'] = unsemi(d.read(int(ceil(ord(p['address_len'])/2.0))))
    p['pid'] = d.read(1)
    p['dcs'] = d.read(1)
    ts = d.read(7)
    p['ts'], p['tz'] = parseTimeStamp(ts)

    p['udl'] = d.read(1)
    p['user_data'] = d.read(ord(p['udl']))
    p['user_data'] = decodeUserData(p['user_data'])

    
    for f in ['sc_num', 'sender_num']:
        if p[f].endswith('f'):
            p[f] = p[f][:-1]
    
    return p

def unnibleSwapChar(c):
    c = ord(c)
    d1 = c & 0x0F
    d2 = c >> 4
    return int(str(d1) + str(d2))

def parseTimeZone(c):
    c = ord(c)
    d1 = c & 0x0F
    d2 = c >> 4

    neg = d1 >> 3
    d1 = d1 & 0x7
    
    units = int(str(d1) + str(d2))
    if neg:
        zona = '-'
    else:
        zona = ''
    zona += str(units // 4)
    zona += ':'
    zona += "%.02d" % ((units % 4) * 15)

    return zona


def parseTimeStamp(s):
    ts = s[:6]
    tz = s[-1:]

    f = [unnibleSwapChar(c) for c in ts]
    f[0] = f[0] + 2000

    zona = parseTimeZone(tz)
    return datetime(*f), zona

def decodeUserData(s):
    bytes = map(ord, s)
    strips = cycle(range(1,9))
    out = ""
    c = 0    # carry
    clen = 0 # carry length in bits
    while len(bytes):
      strip = strips.next()
      if strip == 8:
        byte = 0
        ms = 0
        ls = 0
      else:
        byte = bytes.pop(0)
        # take strip bytes off the top
        ms = byte >> (8-strip)
        ls = byte & (0xff >> strip)
      #print "%d byte %x ms %x ls %x" % (strip, byte, ms, ls)

      # append the previous
      byte = ((ls << clen) | c) & 0xff
      out += chr(byte)

      c = ms
      clen = strip % 8

    if strip == 7:  out += chr(ls) # changed 6/11/09 to incorporate Carl's suggestion in comments
    return out

def unsemi(s):
    """turn PDU semi-octets into a string"""
    l = list(hexlify(s))
    out = ""
    while len(l):
      out += l.pop(1)
      out += l.pop(0)
    return out

PyCon AR 2009 en Buenos Aires

viernes, 14 de agosto de 2009


Hace un tiempo vi en la facultad los primeros afiches llamando a enviar charlas y presentaciones para realizarse en la PyCon 2009, la primera conferencia sobre Python en español! Se va a realizar los días 4 y 5 de septiembre en la sede de la Universidad de Belgrano, las charlas plenarias son de:
  • Jacob Kaplan-Moss, uno de los lead developers de Django
  • Collin Winter, uno de los core developers de Python que está trabajando en Google en el proyecto Unladen Swallow (un intérprete optimizado que busca multiplicar por 5 la velocidad actual de Python).

Además de éstas que son plenarias, está plagado de otras charlas de menor envergadura, además de las llamadas charlas relámpago que duran solo 5 minutos. Los temas son de los más diversos, y van desde una introducción al lenguaje a cómo usar Python para manipular su propio bytecode.

En resumen, novatos, hackers añejos e incluso personas que solo haya oído hablar de Python van a tener cosas para mirar y aprender. La inscripción es gratuita, solo hay que registrarse en el sitio web de la conferencia.

Fotos de la Patagonia Chilena

lunes, 13 de julio de 2009
Buenas, estuve un tiempito sin postear por el ajetreo universitario. No faltan cosas en el tintero, solo el tiempo para volcarlas. De momento terminé de editar un largo batch de fotos que saqué en febrero pasado cuando estuvimos de viaje por Chile con mi familia. A continuación van cuatro seleccionadas y si les interesa pueden ver el set de Flickr (o el slideshow!).




Olympus anuncia la E-P1

martes, 16 de junio de 2009
Como comentaba hace un tiempo, el nuevo sistema Micro Cuatro Tercios de Olympus es un guiño al pasado y la tradición de la marca que comenzara hace 50 años con sus cámaras portables y compactas. Hoy se anunció la primera cámara Olympus para este sistema (ya existía la Panasonic G1), y me sorprende agradablemente ver que no solo el estilo de la cámara sigue de cerca al de la Pen F, sino que la línea se lanza bajo el nombre de "Pen digital".


Hay un preview de la Olympus E-P1 en DPreview. Además del tamaño compacto, la cámara tiene estabilizador de imagen, limpieza automática del sensor y sale con un lente de 17mm f/2.8 pancake en dos colores (blanca o gris).

Miniaturas de código fuente

lunes, 8 de junio de 2009
Desde la primera vez que ví un iPhone me pareció que había muchas cosas para aprender el innovador diseño de su interfaz. Sin embargo, algo que me saltó a la vista enseguida fue la novedosa implementación de la lista de artistas. Además del consabido scroll con el dedo en el que se desliza la lista, en el costado de la misma, en lugar de una barra de desplazamiento convencional aparecen todas las letras del alfabeto.

Esta sencilla idea es muy eficiente desde un punto de vista de usabilidad: llegar al artista que uno desea se hace inmediato simplemente tocando la letra correspondiente, en lugar de tener que buscar con la vista en el desfile que se produce cuando scrolleamos la pantalla. Una idea similar utiliza Exposé en Mac OS X: con solo pulsar una tecla, todas las ventanas aparecen a la vista para seleccionar la más conveniente, un procedimiento mucho más rápido e intuitivo que buscar el nombre correcto en la barra de tareas. Las buenas ideas tienen éxito, y rápidamente variantes de Exposé vieron la luz tanto en Linux como en Windows Vista.

Para mí gusto, la implementación más feliz de esto es la que actualmente utilizo en Ubuntu. En Linux se utilizan mucho los llamados escritorios virtuales, con lo cual en lugar de mostrarse todas las ventanas cuando el usuario lo desea, se muestran simultáneamente todos los escritorios. La superioridad de esta opción por sobre el licuado de ventanas que se produce en Exposé cuando se tienen muchos programas abiertos proviene del hecho de que además de registrar que programa estamos usando, registramos también en qué lugar de la pantalla está ubicado. Al ver los escritorios completos, esta información se conserva, y nos permite reconocer más fácilmente la aplicación que buscamos, por obra y gracia de alguna extraña combinación entre memoria espacial y fotográfica.


Hace un tiempo se me ocurrió una aplicación de esta idea a la programación. Gran parte del tiempo, si los programas tienen una complejidad sustancial los archivos de código que los componen se vuelven largos (en líneas) con lo cual es vital estar permanentemente scrolleando dentro de los mismos. Muchas veces me encuentro pasando varias veces sobre un archivo para encontrar lo que busco. Si bien podría usar la búsqueda para llegar rápidamente al lugar que deseo, no me resulta intuitivo hacerlo. La existencia de este problema es innegable: un recuerdo particular que conservo de Google son los programadores con cuatro (4!) monitores de 24" dispuestos de forma vertical uno al lado del otro, para poder visualizar una mayor cantidad de código simultáneamente y sin tantos "cambios de contexto" entre una ventana y otra.


La idea es entonces sencilla: en lugar de mostrar una barra de desplazamiento vertical convencional, se muestra en el costado del editor de código un thumbnail o miniatura del archivo completo de código, con alguna indicación de que parte se está viendo en este momento. La idea es que la estructura irregular del código fuente permite identificar fácilmente los elementos del mismo, y llegar con un clic al lugar deseado. A su vez, un menú contextual desplegable puede aparecer cuando se cambia de pestaña dentro del editor para acceder directamente a la sección deseada del archivo.

Como para probar, hice un script con PIL que crea una imagen a partir de un archivo fuente en Python, a razón de 1 pixel por caracter, y con un coloreado de sintaxis minimalista (declaraciones y comentarios). Esta es la pinta que tiene mi trabajo práctico de Teoría de Lenguajes después del proceso:


Haciendo unas pruebas rápidas me pareció que si se reduce el ancho de las miniaturas a un 50% del tamaño que utilicé, todavía resulta identificable la estructura del código, y se ahorra espacio en pantalla (puesto que es vital que la miniatura esté siempre a la vista). En mi opinión esta sencilla idea puede ser muy cómoda para programar. Ahora solo me falta convencer a alguien de que la implemente en Eclipse o algún otro editor Open Source.

Mientras programaba esto hace unos días me encontré con que Microsoft Research tiene un paper de 2006 (que no pude leer, dado que es pago) sobre source code thumbnails (miniaturas de código fuente), pero no encontré ningún programa que lo implemente al día de hoy.

Muerte por PowerPoint

martes, 26 de mayo de 2009

Fecha: viernes 22 de mayo
Hora: 8 de la noche
Materia: Bases de Datos

La presentación que fotografié arriba cumple con una cantidad de requisitos que producen el tristemente frecuente síntoma denominado Muerte por PowerPoint.

Un ambiente oscurecido es receta segura para adormecer a la audiencia: la glándula encargada de producir melatonina, la hormona del sueño, se activa con la luz tenue. Un disertante sentado en esa oscuridad, leyendo el contenido de la presentación de PowerPoint, no solo no es interesante ni atrapante, sino que se torna innecesario: los presentes pueden leer más rápido de lo que él lo hace en voz alta. La puerta cerrada vicia el aire dificultando la concentración. La fatiga mental que se produce un viernes por la noche, acentuada por una clase sin intervalos, la complica aún más.

Tres escultores tres

lunes, 11 de mayo de 2009
En una nota un poco inusual, dejo unos links para que vean las obras de tres escultores muy poco convencionales (cada uno a su manera) cuyo trabajo me parece fabuloso.

Ron Mueck


Ron Mueck es un escultor hiperrealista, que tuvo sus inicios haciendo modelos y animatronics para su uso en publicidad y crea unas obras impresionantes conjugando un nivel de detalle y perfección aterrador, con un uso de la escala sorprendente.


Theo Janssen


Theo Jansen es un escultor cinético: usando materiales livianos construye "criaturas" que caminan empujadas por el viento por las playas de Holanda. Hace varios años trabaja para lograr que sean autosuficientes y puedan vivir indefinidamente en las playas, sin ahogarse en el mar ni encallar en la arena más blanda de las dunas. Para esto, dota a sus animales de un "cerebro" analógico concebido a partir de botellas, tuberías y válvulas, que permite a las bestias tomar decisiones sencillas. Hay más información en Strandbeest, su sitio web oficial.


Eric Joisel


Eric Joisel es experto en origami: todas sus obras son construídas a partir de una única hoja de papel que el artista pliega incansablemente hasta obtener las figuras más insospechadas. Para lograrlo utiliza la técnica de wet folding, en la que los pliegues del papel se humedecen levemente para permitir formas más orgánicas. Para sus modelos más complejos, Joisel puede comenzar con un papel de un metro cuadrado para lograr una figura de apenas diez centímetros.

Mi historia de Taringa

viernes, 8 de mayo de 2009
Seguramente la mayoría de quienes leen un blog tan técnico como este saben lo que es Taringa, pero no está de más aclarar. Taringa es un sitio web que creó Fernando Sanz (alias Cyph3r) allá por el 2003, donde la gente intercambia links a contenido de interés. Yo conocí a Fernando a través del foro de PC++ hace varios años, y gracias a él conseguí mi primer trabajo en Power Site cuando estaba cursando el CBC antes de entrar a la carrera de Computación. Trabajamos juntos 6 meses allí hasta que yo renuncié para poderme concentrar en mis estudios, y junto con otros tránfugas que programaban y diseñaban sitios web en esa empresa puedo decir que la pasamos bastante bien. Hoy por hoy, Taringa es el octavo sitio más visitado de Argentina, por delante de Clarín o Mercado Libre.

Pero volviendo a lo que nos aqueja: Fernando creó la página cuando estaba aprendiendo a programar en PHP, pero se encontró con un éxito online que le resultaba difícil de manejar. El costo de alojamiento de la página era muy alto, y era imposible poner anunciantes a pesar del enorme tráfico porque gran parte del contenido de Taringa era software ilegal, o pornografía. Por esta razón, Taringa no permitía crear nuevos usuarios, puesto que ya con la cantidad existente el problema era complejo, y si se disparaba el tráfico del sitio, iba a ser imposible mantenerlo en línea. Fernando además estaba en otra, con proyectos que Taringa (por la atención que requería) le hacía muy complicados, y estaba preocupado por la naturaleza ilegal del contenido (lo que dicho mal y pronto significa que no quería terminar en cana).

Fue así como Fernando vendió el 90% de Taringa a los hermanos Botbol (dueños de Wiroos, una empresa de hosting). Rápidamente, Taringa renació con la atención que le pusieron pero con la popularidad empezaron a surgir entrevistas a estos "creadores" del sitio donde se veían declaraciones extrañas, desde como habían creado el nombre (que había sido elegido por Fernando), hasta como se les había ocurrido la idea de crear un sitio así (que había sido creado por Fernando a partir de Teoti).

Un tiempo más tarde Cypher aclaró en su blog la verdadera historia, que es más o menos la que les cuento acá. El tema es que el mes pasado un podcast de Esteban Mancuso trajo luz a las internas de la sociedad Botbol, de la que él había sido parte. Me entero de esto a través de una nota que le hicieron a Fernando en La Nacion Online.

El podcast de Mancuso fue censurado por los administradores de Taringa para que no se difundiera dentro del sitio, y todas las apariciones de su nombre en posts y comentarios se reemplazaron por asteriscos para que no pudieran ser encontradas por los buscadores. No conforme con esto, le enviaron una carta documento al responsable de Vacas Volando, sitio que alojaba el podcast, para que lo eliminara.

Por esta razón escribo este post, y cortesía del efecto Streisand, les dejo el link para que puedan descargar el podcast con la historia de Taringa, que no tiene desperdicio (y contiene más de una valiosa lección para emprendedores).

Descargar podcast de Esteban Mancuso: La historia de Taringa

Python 3: iteradores en map y filter

martes, 28 de abril de 2009
Las primitivas funcionales map y filter se agregaron a Python en Enero de 1994 por un programador cuya identidad hoy se desconoce. De esta manera, lo que antes se escribía repetidas veces con un bucle puede reducirse a una única y expresiva línea de código.
lista = [1,2,3,4]

# utilizando un bucle
lista_mapeada = []
for e in lista:
    lista_mapeada.append(f(e))

lista_filtrada = []
for e in lista:
    if f(e):
        lista_filtrada.append(e)

# utilizando map y filter
lista_mapeada = map(f, lista)
lista_filtrada = filter(f, lista)
En Python 2.0 se agregaron listas por comprensión, que ofrecen una sintaxis más intuitiva para las primitivas map y filter.
lista_mapeada = [f(e) for e in lista]
lista_filtrada = [e for e  in lista if f(e)]
Si están familiarizados con lenguajes como Haskell, que utilizan evaluación lazy o perezosa conocen algunas de las ventajas de esta característica en un lenguaje de programación: la evaluación de algunas expresiones no se hace inmediatamente sino que se pospone hasta que el valor es realmente necesario.

En el contexto de las primitivas map y filter que nos conciernen, la ventaja de la evaluación lazy es que no se computan hasta tanto no se accede al contenido de las listas resultantes. Con esto en mente, en Python 2.4 se agregaron generadores por comprensión (simplemente remplazando los corchetes por paréntesis en la sintaxis anterior). El resultado es un generador: un objeto que se comporta parcialmente como una lista, dado que puede iterarse sobre el (aunque no puede indexarse y accededer directamente a su i-ésimo elemento).
gen_mapeado = (f(e) for e in lista)
gen_filtrado = (e for e  in lista if f(e))
La mejora más inmediata es la performance: en lugar de aplicar la función completamente en el momento, no se hacen los cómputos requeridos hasta que se accede al resultado. Por esta razón, la librería estándar itertools incluye primitivas imap, ifilter y varias más que devuelven generadores en lugar de listas, puesto que en muchos casos este comportamiento es deseable.

En Python 3, sencillamente se cambió el comportamiento de las primitivas convencionales para que devuelvan iteradores en lugar de listas. Así, los nuevos map, filter, zip y compañía se comportan como los anteriores itertools.imap, iterators.ifilter y iterators.izip.
# Python 3
>>> l = map(f, [1,2,3,4])
>>> l[2]
TypeError: object is unsubscriptable
El nuevo comportamiento no es compatible hacia atrás, pero puede resolverse esta diferencia sencillamente cambiando todas las llamadas map(l) (y los otros) por list(map(l)), lo cual produce un comportamiento casi idéntico en Python 3 y Python 2 (y digo casi porque si el map original devolvía una tupla o un string, pueden haber diferencias).

Envisioning Information

jueves, 23 de abril de 2009
Hace unos días saqué de la Infoteca del Departamento de Computación de la UBA el libro Envisioning Information de Edward Tufte, y terminé de hojearlo hoy mientras me comía un rico sandwich (tenía una pinta tal que le tuve que sacar una foto con la cámara de la compu).

El autor

Edward Tufte es un profesor de Yale muy reconocido por sus estudios (y sus libros) sobre diseño y presentación de la información, y un ferviente crítico del mal uso de PowerPoint. Sin duda es uno de los autores más reconocidos del área, al punto que un artículo del New York Times lo llamó una vez el Da Vinci de los datos.

Una idea hoy popular sobre la que Tufte atrajo la atención hace mucho tiempo son los sparklines, pequeños gráficos de tamaño similar a las palabras de un documento que permiten representar mucha información en un espacio reducido y sin agregar una cantidad significativa de ruido gráfico. Los sparklines son hoy moneda corriente en aplicaciones de visualización de información que tengan mucha densidad de datos, como podrían ser aplicaciones de monitoreo de bolsas financieras, o de estadísticas detalladas de utilización de sitios web (o tal vez para cuestiones más mundanas, como seguimiento de los accidentes con mascotas en diversas líneas aéreas).


El libro

Confusion and clutter are failures of design, not attributes of information.
"La confusión y el desorden son fallas de diseño, no atributos de la información". Esta frase de Tufte resume el espíritu del área de la visualización de información, que busca la manera más apropiada de entregar datos a las personas para que puedan ser utilizados.

El libro no solo está hermosamente editado y encuadernado (como es de esperarse para un libro cuyo contenido refiere al diseño), sino que además utiliza una lógica que encuentro de lo más apropiada. A lo largo de sus 6 breves capítulos, el autor presenta cada uno de los aspectos esenciales en la construcción de un documento gráfico, así como ideas y efectos que son de interés, acompañando cada uno de ejemplos no solo vistosos y muy atinados, sino que provenientes de contextos históricos y sociales diversos. Así, el libro es mitad estudio de la visualización, y mitad anécdotas gráficas observadas en detalle. Algunas cosas que aparecen:
  • La tabla donde se resumen los antecedentes penales de los testigos en el caso contra el mafioso John Gotti, que fue la última pieza de evidencia que el jurado pidió rever antes de absolverlo, lo que le valió por mucho tiempo el apodo de "teflon Don" (ya que nunca quedaba pegado)
  • Una factura de hospital de los 26 últimos días de vida de Mrs. K en 1984, donde un médico externo comenta en base a los cargos de la factura la situación de la paciente, así como las ramificaciones de los costos (que son de unos US$50.000)
  • Las anotaciones de Galileo Galilei sobre sus primeras observaciones de las lunas de Júpiter
  • El monumento a la memoria de los veteranos de Vietnam en Washington DC, y la lógica detrás del diseño de la arquitecta Maya Lin
A lo largo de este interesante recorrido, Tufte introduce varios conceptos relativos a la presentación de datos, como la noción de 1+1=3 o el uso de pequeños múltiples.

1+1=3 se refiere al hecho de que dos elementos de una página pueden generar más información contextual por la interacción que hay entre ellos. A continuación un ejemplo: los círculos construyen, por la relación entre sus posiciones, un quinto elemento (el rectángulo central). Este efecto debe cuidarse ya que bien usado puede ser de ayuda para la comunicación, pero si se lo ignora se puede producir ruido visual involuntariamente. El estilo de escritura es muy ameno y conciso, y puede leerse en profundidad o simplemente sobrevolarse rápidamente (el libro consta de apenas 120 páginas). Es interesante que esto concuerda con el estilo que el autor pregona para mostrar información compleja: una visualización que pueda verse tanto a escala micro como macro (según se desee) y en ambos casos exhiba efectivamente los datos. Un detalle más que denota lo pensado que está el libro.

Work Hard. Be nice.

lunes, 13 de abril de 2009
Hace unos días me llegó un pedido de libros de Amazon y el primero que leí fue Work Hard. Be Nice. de Jay Mathews.

Antes que nada hace falta aclarar que no se trata de un libro de autoayuda. El libro fue escrito por un periodista de educación y cuenta la historia de Dave Levin y Mike Feinberg, dos graduados universitarios que tras egresarse ingresaron al programa Teach for America, en el que jóvenes universitarios recién recibidos tienen la posibilidad de entrar en las aulas de escuelas primarias y medias como maestros de jóvenes en grupos étnicos y sociales desfavorecidos.

Allí se conocieron y comenzaron a gestar el Knowledge is Power Program (KIPP), que hoy cuenta con más de 60 escuelas en Estados Unidos, y tiene un nivel académico sorprendente, y más aún si se tiene en cuenta el estrato social del que provienen la mayoría de sus alumnos. Las escuelas KIPP son charter schools, colegios públicos administrados por entidades privadas que reciben dinero del estado para funcionar, de modo que son gratuitas pero no necesitan ceñirse al sistema de educación convencional en lo que se refiere a bibliografía, horarios ni programas de estudio.

KIPP no tiene ninguna receta mágica para el aprendizaje: simplemente tienen días de escuela muy extensos (más de 9 horas, sin contar una o dos horas adicionales de tarea para hacer en casa, contra las aproximadamente 6 que tiene un americano promedio) y un alto nivel de exigencia, así como un énfasis muy fuerte en la calidad de los docentes para transmitir y para mantener motivados a los alumnos. El sistema le confiere además una alta importancia a los resultados de los alumnos: es más importante obtener buen rendimiento, que cual es exactamente la manera de lograrlo.

El libro es una excelente crónica periodística (y me gusta mucho el género), muy amena de leer por sus capítulos muy cortos. Conocí el libro cuando Bill Gates lo regaló a la audiencia de TED en su Ted Talk de 2009.

Personalmente me da un poco de escalofríos pensar en un sistema tan pragmático (por llamarlo de alguna manera), pero retrospectivamente me doy cuenta de que yo también pasaba 9 horas por día en el colegio - y no es que haya sido muy ameno - y de que el docente que más me marcó en toda mi escolaridad tenía un perfil en muchos aspectos similar al de los maestros KIPP. No pude evitar al leer el libro revivir las poco ortodoxas técnicas de aprendizaje y motivación de Bernard Desbois, mi profesor de matemáticas de cuarto año, que además de análisis y álgebra nos mostró lo que era realmente una persona que ama su trabajo y le pone todo el empeño necesario. Varios años después recibimos un mail de una asociación de padres de Bangkok preguntando, esencialmente, qué estaba haciendo este tipo con sus hijos, y si era normal lo que estaba pasando: cantos, gritos, aplausos, exámenes semanales y otros excentricismos. La realidad es que de normal no tenía nada, pero fue una de las personas que más me marcaron en todo mi período escolar.

Olympus: de Maitani al Micro Four Thirds (Parte 3)

miércoles, 11 de marzo de 2009
En la segunda parte de este artículo revisamos el nacimiento del formato Cuatro Tercios (también llamado 4/3) que Olympus utilizó desde 2001 como base para sus cámaras digitales SLR. Sin embargo, el sistema nunca estuvo a la altura de sus promesas: las cámaras no fueron sustancialmente más compactas que las DSLR de otras marcas, lo cual debía ser su característica distintiva.

¡El problema es el visor!

El mayor factor limitante para reducir una cámara fotográfica réflex es, precisamente, el sistema réflex. En una cámara de este tipo, la lente debe tener una separación importante del sensor (o la película) para alojar el espejo que la hace réflex. A su vez, y dado que los lentes deben estar a esa gran distancia del sensor (lo que se conoce como flange distance), el diseño de los mismos se ve afectado haciéndolos más complejos, pesados, caros y limitando su calidad.


Como se observa en la imagen, el espejo (en verde) ocupa un lugar importante, así como también lo hace el pentaprisma en la parte superior. A su vez, como dijimos, la separación que es necesaria para alojar el espejo complica el diseño de las ópticas.

Entonces ¡qué se vaya!

Antes de quitar el visor réflex de una cámara fotográfica, hay que analizar algo muy básico: ¿por qué lo pusieron ahí en primer lugar? Las cámaras no-réflex ya existen hace mucho tiempo, se las llama "de visor directo" (dado que su visor es directo, o sea que no atraviesa la lente de la cámara fotográfica - es una ventanita en una esquina del cuerpo). Las cámaras de visor directo tienen un sinnúmero de particularidades. La legendaria Leica M que blandió Cartier Bresson era una cámara de este tipo. Y en efecto, era sustancialmente más compacta que una cámara réflex.


En la imagen de arriba se observa una comparación entre una réflex digital Canon y una cámara Bessa de visor directo, mucho más compacta tanto en su cuerpo como en su óptica.

El problema está precisamente en que las cámaras de visor directo no ven a través del lente. Esto tiene una serie de consecuencias poco deseables, de las cuales la más obvia tal vez sea que es posible sacar una foto con la tapa puesta en el lente sin notarlo. A su vez, como siempre se mira a través de una ventanita en el cuerpo, si se cambia el lente por uno diferente, la perspectiva que se observa en el visor nunca cambia: esto las hace particularmente inútiles para fotografía de objetos lejanos.


Electrones al rescate

Afortunadamente, en la era digital hay una tercera opción para visores fotográficos. Se trata de la consabida pantallita que todo el mundo utiliza hoy por hoy en su cámara digital. Ya no es necesario, con un captor digital, observar a través del lente de la cámara por un visor óptico - el sensor puede enviarnos la señal a una pantalla apropiada para poder observarla y componer la imagen. Esta es la base del sistema Micro Cuatro Tercios, presentado por Olympus y Panasonic en Agosto de 2008.


A excepción de la costosísima Leica M8, el sistema Micro Cuatro Tercios es el primer estándar de sistema fotográfico de lentes intercambiables que no es réflex! Y por primera vez, aparece la posibilidad de disponer de un sistema fotográfico digital con alta calidad (determinada por el tamaño del sensor), pero también portable, ligero y con la posibilidad de intercambiar los lentes.

Las cámaras

La primera cámara del sistema Micro Cuatro Tercios fue la Panasonic G1, con un diseño similar al de una réflex digital, aunque más compacta. Si bien es una cámara muy interesante, no es genuinamente representativa de las posibilidades del sistema M4/3.

Muy distinto es el prototipo que presentó Olympus, una declaración abierta de volver a los ideales de Maitani: una cámara de alta calidad, muy portable y sencilla de usar. Ésto es lo que miles de fotógrafos cansados de acarrear sus equipos réflex estaban esperando hace muchos años: una cámara que en lugar de prolongar el paradigma de 1990 a la era digital, aproveche las nuevas posibilidades al máximo. Una cámara que cabe en un bolsillo, pero produce fotos de gran calidad. Una cámara sencilla de usar, pero no limitada en sus prestaciones. Una cámara que haga honor a las convicciones de Maitani, con la tecnología de hoy.


Un guiño al pasado

Con esto concluye este largo artículo sobre la historia de Olympus y del sistema Micro Cuatro Tercios. Sin embargo, no quiero publicarlo sin antes mencionar una curiosidad con la que me topé en la web hace unos días. Si tienen buena memoria recordarán a la Olympus Pen F, esa cámara de 1960 que fuera la primera creación de Maitani y que discutimos en la primera parte del artículo. La particularidad de aquella cámara era su formato half-frame: utilizaba para cada imagen solo el 50% de la superficie de la película de 35mm. El formato Micro Cuatro Tercios utiliza un sensor aún más pequeño, pero con las dimensiones apropiadas para poder utilizar los antiguos lentes del sistema Pen F en cámaras modernas con un adaptador. Y es sólo el comienzo!

Olympus: de Maitani al Micro Four Thirds (Parte 2)

martes, 10 de marzo de 2009
En la primera parte de este artículo hablamos sobre Yoshihisa Maitani y sus tres formidables diseños: la Olympus Pen F, la Olympus OM y la Olympus XA. A continuación vamos a examinar lo que pasó con Olympus durante estos primeros años de la era digital, para llegar así al sistema Micro Cuatro Tercios (Micro Four Thirds) anunciado recientemente.

La caída del sistema OM

Antes de la revolución digital, existió otro gran momento de cambio en la tecnología fotográfica: el autofoco. Si bien el autofoco no era el primer automatismo que se salía de lo puramente manual, sí era el primero que requería de cambios dramáticos en la interacción entre el lente y la cámara: la cámara tenía que decirle al lente que se mueva para enfocar, y por si fuera poco, éste tenía que obedecer. Dado que esta interacción entre lente y cámara es lo que define a un sistema de cámaras (como el OM de Olympus, el F de Nikon o el FD de Canon), era necesario tomar una decisión al respecto:
  • ¿Se crea un sistema totalmente nuevo, haciendo obsoletos todos los lentes antiguos? Esto fue lo que hizo Canon, que abandonó el sistema FD para introducir al moderno sistema EOS.
  • ¿Se adapta el sistema existente para incluir las nuevas funcionalidades? Esto fue lo que hizo Nikon, lo cual le ganó muchos adeptos en aquellos tiempos, pero finalmente se volvió un dolor de cabeza con la modernización que las cámaras sufrieron más adelante.
Olympus se enfrentaba además al hecho de que la tecnología de autofoco estaba patentada, y para una empresa relativamente pequeña, resultaba difícil afrontar los costos de licencias para la patente. Olympus jamás consiguió integrar el autofoco a su sistema OM, y esta funcionalidad se volvería totalmente determinante para las cámaras profesionales en los años que siguieron. Así, el sistema de réflex OM de Olympus fue superado por los demás (y con él gran parte de la marca, puesto que la línea réflex funciona como buque insignia de una compañía fotográfica).

La era digital

Película analógica vs. Sensor digital

Junto con las primeras cámaras digitales, se avecinaba una nueva revolución en los sistemas fotográficos. Así, en el inicio de la era digital Olympus tuvo que decidir nuevamente qué camino elegiría para desarrollar sus sistemas digitales.

En la imagen de arriba se observa un cuadro de película (diapositiva, no negativo) de 35mm al lado de un sensor en una cámara réflex digital Canon. Hagamos ahora un poco de memoria: en los tiempos de la foto analógica, el laboratorio y el revelado, los fabricantes de cámaras solo hacían una cosa: las cámaras y sus lentes. Existía un segundo integrante clave de la industria fotográfica, y era uno muy importante: el fabricante de películas, de los cuales el más popular es sin duda Kodak.

Repentinamente se dio un cambio de paradigma: para producir cámaras digitales de calidad no sería posible que el fabricante de la cámara y el del sensor digital fueran entidades disjuntas, sino que sería necesario un arduo trabajo conjunto de integración. Era crítico que el fabricante de la cámara y el del sensor que viajaría dentro de ella trabajaran juntos para lograr la correcta (y compacta!) integración de los componentes.

En efecto, las primeras cámaras digitales profesionales eran simplemente cámaras analógicas a las que Kodak les construía captores digitales y se ocupaba de que trabajaran juntos (más o menos). El grado de éxito con que esto se logró es relativo. No hay más que ver la foto de la integración Kodak/Nikon de 1994 al lado de estas palabras. Aparte de su ridículo costo, tenían resoluciones de entre medio y un megapixel, y sensores mucho más pequeños que la película de 35mm.

Para Olympus resultaba crítico tomar una decisión estratégica sobre el camino a seguir para ingresar a la era digital. La disyuntiva era la siguiente:
  • ¿Era conveniente desarrollar su propia tecnología de sensores?(con los costos siderales que esto representa)
  • ¿O sería mejor comprar tecnología ajena de algún fabricante especializado? (como por ejemplo, Kodak)


El sistema cuatro tercios

La decisión tomada fue un híbrido. En 2001, Olympus anunció su alianza con Kodak para desarrollar lo que se convertiría en el estándar Cuatro Tercios. En lugar de afrontar los costos de un sistema nuevo por su cuenta, Olympus estableció que el formato que desarrollaría sería abierto: otros fabricantes podrían acceder a las especificaciones de la montura y fabricar cámaras compatibles con el sistema de Olympus. Así, sería más factible que un consorcio de pequeñas empresas pudieran hacerle frente a los gigantes Canon y Nikon.

En ese momento establecieron que el estándar Four Thirds sería réflex, y utilizaría un sensor del 50% del tamaño de la película de 35mm, a diferencia de Canon o Nikon que optaron por desarrollar sus propios sensores, con formatos del orden del 65% de la película tradicional. Esta consideración es clave: mientras más grande es el sensor, mayor es la calidad de la imagen, pero también es mucho más alto su costo, así como el tamaño y peso de las cámaras y lentes que lo acompañan. En 2001 los sensores full frame (de cuadro completo, es decir del 100% del tamaño de la película de 35mm) no soñaban con ver la luz, y Olympus decidió apostar a minimizar los costos y aprovechar el formato más pequeño para construir cámaras más compactas y portables (no olvidemos la Kodak de arriba!).

Para darse una idea, a continuación se ven los distintos tamaños de sensores digitales que existen al día de hoy. Los sensores que aparecen en la última línea de la imagen son los que se utilizan en las cámaras compactas digitales. Salvo contadas excepciones, para tener un sensor de la segunda línea para arriba, es necesario comprar una cámara réflex digital. Esa es la razón principal de la diferencia de precio que existe entre réflex y compactas, así como también lo que motiva que a los usuarios de réflex no les importe que la última cámara que compró su cuñado tenga "un zoom de 30x".

Pero sin embargo...

El problema mayor fue que el sistema Cuatro Tercios sencillamente no estuvo a la altura de lo prometido. Como era de esperarse por su sensor más pequeño, la calidad de imagen es inferior a las alternativas de Canon y Nikon, pero por contrapartida las cámaras no son sustancialmente más pequeñas ni más baratas. No hay más que ver a la E-430 (la cámara más pequeña que Olympus fabrica) comparada con una D60 (una de las más pequeñas que fabrica Nikon al día de la fecha). La E-420 tiene aproximadamente el mismo precio que una Nikon D40x, la más barata de las cámaras Nikon. Pero hay más! ¿Qué tal si la comparamos con la OM1 que concibiera Maitani 50 años antes? ¡Ouch! La cámara de cuadro completo de hace 50 años es más pequeña (con diferencia) que la E-420. Si recordamos que el formato de sensor pequeño de la cámara Cuatro Tercios debía conducir a cámaras más compactas, la comparación resulta poco favorable: la OM1 tiene un "sensor" (la película) mucho más grande y sin embargo logra ser sustancialmente más compacta.

En resumen

El ingreso de Olympus al mundo digital no fue muy feliz: si bien el sistema Cuatro Tercios parecía una alternativa prometedora, la realidad es que no estuvo a la altura de sus promesas. Las cámaras muy compactas, económicas y ligeras nunca llegaron. En la tercera parte de este artículo, vamos a hablar de la vuelta de tuerca faltante para el sistema Cuatro Tercios que se dio en 2008: el estándar Micro Cuatro Tercios.

Olympus: de Maitani al Micro Four Thirds (Parte 1)

La Olympus Corporation nació en 1919 como una compañía especializada en termómetros y microscopios. Fue recién en 1949 que cambió su nombre a Olympus y comenzó a establecerse como una compañía enfocada a la fotografía con un carácter único. Sin lugar a dudas Olympus es un claro ejemplo de la mentalidad japonesa de posguerra que los llevó rápidamente de la derrota y la destrucción a convertirse en una potencia industrial.

Aclaremos algo: Olympus nunca fue uno de los grandes jugadores del mercado de fotografía. Los gigantes Canon y Nikon manejan volúmenes de producción muy superiores a los de esta compañía japonesa. Sin embargo, en los últimos 50 años Olympus creó tres líneas de cámaras fotográficas hoy consideradas de culto. A continuación, voy a sobrevolar cada una de estas tres líneas como preludio a la que podría convertirse en la cuarta: el estándar Micro Cuatro Tercios o Micro Four Thirds.

Yoshihisa Maitani: el ideólogo

En 1956 se une a Olympus un joven ingeniero de 23 años llamado Yoshihisa Maitani. Este hombre sería el padre de las tres líneas de cámaras que voy a describir a continuación, y que le dieron a Olympus su posición dentro del mercado fotográfico. Desde que construyó su primera cámara a los 10 años de edad, Maitani siempre fue fiel a su filosofía: la cámara es una herramienta de expresión y como tal su objetivo mayor está en quitarse del medio para que el fotógrafo pueda hacer su tarea. De este modo el enfoque de sus diseños siempre estuvo fuertemente centrado en la usabilidad.

Maitani entendió esto en 1956. Aún al día de hoy, en que la usabilidad es un término conocido al punto de que existen ingenieros en usabilidad, todavía las grandes compañías no prestan la suficiente atención a este aspecto y sufren las consecuencias. Empresas como Google o Apple son conscientes de esta necesidad y construyeron su liderazgo en los últimos años a partir de un enfoque proactivo en la usabilidad de sus productos (desde GMail hasta el iPhone), destacándose sobre gigantes pesados como Microsoft.

La Olympus PEN F

Copyright oldglass


Desde el primer momento, Maitani entendió también que parte de la practicidad en el uso de las cámaras estaba dada por su tamaño y su peso. Así, se esforzó en crear sistemas de cámaras que fueran tan pequeños y ligeros como fuese posible. Esta es la motivación del sistema Pen y su formato half frame. En fotografía, los "35mm" de los que se habla corresponden al tamaño que la foto ocupa en la película. La Olympus Pen utilizaba solo la mitad del cuadro de 36x24mm, tomando dos imágenes verticales más pequeñas.

Esta reducción de formato no solo le permitía tomar el doble de fotos con la misma película (72 fotos por rollo!), sino que además reducía significativamente el tamaño de los lentes y cámaras, manteniendo el visor réflex, y con él la posibilidad de mirar la foto a través del lente de la cámara (y no por una pequeña ventana a un lado de la lente, como era el caso en la mayoría de las cámaras pequeñas de la época, que no eran réflex). Para darse una idea del tamaño de la cámara, vean esta imagen del manual de la cámara. Se vendieron más de 10 millones de cámaras de esta línea.

La Olympus OM

En 1972 sale al mercado la Olympus OM1, la primera de un sistema réflex de 35mm marcado por las mismas ideas que el sistema Pen: muy pequeño, muy ligero y muy sencillo de usar (pero no demasiado). Tras la experiencia de la Pen, Maitani buscó transportar la filosofía de aquellas camaritas al formato de 35mm, que brinda una mayor calidad que el pequeño half frame.

El sistema fue un éxito, porque presentaba cualidades impresionantes en un formato muy pequeño. El visor de la OM1 era magnífico y sigue siéndolo para los estándares actuales, y tenía una línea de lentes muy completa. El obturador de tela (a la Leica) le daba un disparo muy silencioso, y por su tamaño y funcionamiento discreto hubo quienes la llamaron "la Leica de los pobres". Siguieron a la OM1 muchas otras cámaras, en particular la OM2 que era electrónica (la OM1 era totalmente mecánica). Mi Olympus OM2 es la que se aprecia en la foto de arriba, y con la que tomé muchas de mis fotografías. En este autorretrato se puede apreciar el tamaño compacto de la cámara.

La Olympus XA

Si todavía estás leyendo es probable que sea porque te interesa la fotografía. Pero aunque no te interesara ni un poco, si naciste antes de 1990 seguro conocerías a las hijas o a las nietas de esta cámara: ¡están en la mano de todos los turistas japoneses! Llevando el concepto de portabilidad de Maitani a su extremo, la Olympus XA de 1979 fue la primera cámara con tapita.

La Olympus XA tenía un lente que no sobresalía de la cámara, permitiendo así el diseño deslizante que después se haría muy popular. Su modelo original (la XA a secas) tenía un modo de funcionamiento en prioridad de diafragma que la hace muy atractiva aún al día de hoy, puesto que las cámaras de este tamaño, por ser orientadas a consumo masivo, se hicieron totalmente automáticas rápidamente. También tengo la suerte de tener una de estas, aunque prácticamente no la usé desde que la compré hace alrededor de un año.

Hay una muy buena página web dedicada a la Olympus XA. Una curiosidad: los rectángulos rojos que están por toda la página imitan el obturador sensible al tacto de la Olympus XA, solo uno de los aspectos técnicos de avanzada para la época que tenía esta simpática cámara.

Resumiendo

Hicimos un recorrido rápido por las creaciones de Yoshihisa Maitani mientras trabajaba para Olympus. El sitio web Maitani Fan tiene mucha más información sobre Maitani y Olympus, así como sobre algunos de sus proyectos más esotéricos que nunca vieron la luz (como la OM-X, una cámara modular de 35mm al mejor estilo Hasselblad).

En la segunda parte de este artículo vamos a hablar sobre las desventuras de Olympus en la era digital, y como el formato Micro Cuatro Tercios marca el regreso a los ideales de Maitani.

Python 3: codificaciones y más

sábado, 21 de febrero de 2009
Unicode, bytes y strings

Otro punto importante de cambios en Python 3 es como el lenguaje trata el texto, unificando todos los strings bajo Unicode. Históricamente, Python tenía un tipo especial de string Unicode, con una sintaxis especial, que era hermano del str convencional (dado que ambos heredaban de BaseString).

Esta distinción entre str y unicode como tipos básicos se efectuaba en el código fuente con su sintaxis específica:
str_normal = "Hola Mundo!"
str_unicode = u"Hola Mundo!" # nótese la 'u' antes de la primera comilla
Sin embargo, este paradigma no era muy feliz. Un str convencional carecía de una codificación particular y podía producir una serie de ambigüedades, en particular a la hora de realizar comparaciones entre cadenas de texto Unicode y cadenas de texto de 8 bits convencionales (en muchos casos se pueden producir Warnings o incluso excepciones).

A partir de Python 3, se utiliza una convención mucho más apropiada. Existen finalmente dos tipos básicos para las finalidades en las que regularmente se utilizan strings:
  • bytes, que es una secuencia de caracteres de 8 bits sin ninguna codificación particular
  • texto, que es una secuencia de caracteres textuales, y como tal representa palabras u otro texto y soporta la noción de encoding
La sintaxis para éstos es:
str_bytes = b"Hola Mundo!" # nótese la 'b' antes de la primera comilla
str_texto = "Hola Mundo!"
Esto tiene como consecuencia que al momento de declarar un string (y como lo más usual es utilizarlas para almacenar texto), se utilizará una cadena Unicode como corresponde para tener correcto soporte de internacionalización. Para el manejo de datos binarios o blobs de caracteres sin interpretación, el tipo bytes está disponible.

Codificación del código fuente

A su vez, y dado que Python históricamente no soportaba varias codificaciones de fuente, a partir de Python 2.0 (y junto con la introducción del soporte Unicode) se introdujo la posibilidad de declarar la codificación de un archivo mediante un comentario especial. Finalmente, desde 2.5, la aparición de caracteres no-ASCII en un archivo de fuente Python que no tuviera su codificación declarada producía un error.

A partir de Python 3, la codificación por defecto es UTF-8 a menos que se indique lo contrario utilizando la declaración que existe desde Python 2. Este valor por defecto es más razonable (ya que UTF-8 es el estándar de facto en la mayoría de los entornos modernos) y evita la necesidad de estar especificando permanentemente la codificación cada vez que debe crearse un nuevo archivo de código fuente.

En resumen

Una vez más se reemplazaron algunos casos por defecto para hacerlos más apropiados, rompiendo así la compatibilidad hacia atrás en pos de la sanidad del código fuente. El soporte de cadenas de texto internacionalizadas es ahora transparente y no requiere ningún esfuerzo adicional por parte del programador. Asimismo, la modificación en el source encoding ahorra un poco de texto innecesario al comienzo de cada nuevo archivo, manteniendo la esencia minimalista del código fuente de Python.

Como siempre, hay un resumen completo de los cambios en el changelog de Python 3. Además, hay una discusión interesante en Slashdot respecto de este tema, donde además se discuten las diferencias respecto del método adoptado por Ruby para soporte Unicode (es interesante puesto que Ruby tiene sus raíces en países de Asia, que es donde Unicode recibe más críticas por supuestas limitaciones técnicas).

¡Se me pisan los horarios!

viernes, 20 de febrero de 2009
Un grafo es esencialmente un dibujito que consta de bolitas y rayitas. Detrás de su inocente aspecto, los grafos ocultan poderosas herramientas matemáticas para resolver problemas muy comunes. Por su naturaleza simple, son una buena muestra de que la matemática no trata solamente de números.

El plan de carrera de Ciencias de la Computación es un poco peliagudo. La carrera está prevista para hacerse en 5 años, a los que se suma el Ciclo Básico Común para lograr un total de 6. Este cuatrimestre (el primero de mi cuarto año en la facultad) me toca una situación que hasta ahora vine esquivando por poco.

Resulta que si bien el plan indica que en este año deben cursarse 4 materias obligatorias y 2 optativas, mis planes de hacer 3 obligatorias en el primer cuatrimestre se ven frustrados por la superposición de horarios. Las materias se superponen solamente una hora, con lo cual parecería ser que alguien intentó (sin éxito) que esto no ocurra.

¿Y ahora quién podrá defenderme?

Con mis planes aparentemente arruinados por la burocracia, me veo en la disyuntiva de elegir qué cursar. Tengo una serie de problemas: hay algunas materias cuyos horarios se superponen, otras que no me interesan, otras que me quiero sacar de encima y al menos una que la tengo que cursar sí o sí porque una materia del segundo cuatrimestre la requiere.

Este problema es un caso típico de algo que se resuelve de forma sencilla utilizando grafos. Lo primero que hay que hacer es modelar la información que tengo, que son materias, días y horarios. El grafo que propongo tiene una bolita o nodo por cada materia, y una rayita o eje une a dos materias cuando los horarios de éstas se superponen.

Para construir el grafo voy a usar un pequeño pedazo de código que a partir de los horarios decide si dos materias se superponen o no. A continuación este programa produce un archivo dot, que utilizando GraphViz puedo representar como imagen. Si me limito a las materias que puedo cursar en este momento (obviando las que ya hice, y las que todavía no puedo hacer), me queda algo así:



Puse de color verde las materias obligatorias, y la única materia que tengo que cursar obligadamente es Paradigmas de Lenguajes de Programación, ya que Ingeniería de Software II depende de ella.

El dibujo tiene una complejidad muy alta, ya que hay muchas materias. Si miran con cuidado verán que hay una línea que une a Bases de Datos con Teoría de Lenguajes, ambas de color verde. Por lo tanto, estas dos materias tienen sus horarios superpuestos y no puedo cursar ambas a la vez.

Una cualidad interesante es que el dibujo de arriba contiene toda la información necesaria para resolver el problema: los días de la semana, las horas, la aritmética, los feriados y la mar en coche desaparecieron de la vista. Esta capacidad de abstracción es un rasgo fundamental del uso de grafos.

¿Qué estamos buscando?

Necesito encontrar un conjunto de materias (bolitas en el grafo) que no tengan líneas entre sí. Esto se llama, en términos de grafos, un conjunto independiente. Existen muchos conjuntos independientes, y uno muy sencillo es simplemente tomar una materia sola. Claro que si curso una sola materia por cuatrimestre no me voy a recibir muy rápido, así que voy a intentar hacer algo mejor.

Me gustaría que el conjunto de materias elegidas tenga las siguientes características:
  • Tiene que ser independiente (sin rayitas entre las bolitas), ya que de otro modo dos materias tendrían sus horarios superpuestos.
  • Tiene que contener a la materia Paradigmas de Lenguajes de Programación (porque de otro modo me atrasa el cuatrimestre que viene)
  • Tiene que contener al menos otra materia obligatoria, sea Teoría de Lenguajes o Bases de Datos
  • Y por último, tiene que tener al menos 3 materias
Si escribo el código de esta restricción en Python, me queda lo siguiente:
def esConveniente(s):
    return esIndependiente(s) and \
           "Paradigmas de Lenguajes de Programación" in s and \
           ("Teoría de Lenguajes" in s or "Bases de Datos" in s) and \
           len(s) >= 3
Para terminar solo es cuestión de dejar que la computadora haga su trabajo, y me diga qué me conviene cursar el cuatrimestre que viene. Tras una (instantánea) corrida, resulta que solo hay 7 combinaciones posibles que reúnen los criterios que describí arriba:
gomo@ciabatta:~$ python inscripcion.py
Formas válidas de cursar materias: 233
Formas de cursar 'convenientes': 7

Paradigmas de Lenguajes de Programación, Lógicas Modales, Bases de Datos
Paradigmas de Lenguajes de Programación, Computación Gráfica, Bases de Datos
Visualización de la Información, Paradigmas de Lenguajes de Programación, Teoría de Lenguajes
Visualización de la Información, Paradigmas de Lenguajes de Programación, Lógicas Modales, Teoría de Lenguajes
Paradigmas de Lenguajes de Programación, Lógicas Modales, Teoría de Lenguajes
Visualización de la Información, Paradigmas de Lenguajes de Programación, Computación Gráfica, Teoría de Lenguajes
Paradigmas de Lenguajes de Programación, Computación Gráfica, Teoría de Lenguajes
Solo me resta elegir la opción que más me divierta, y voilà! Pueden ver el código completo en Python si siguen leyendo este post.

Ver el código completo >>

Código completo en Python

#!/usr/bin/python
# *-* encoding: utf-8 *-*

materias = {'Estadística y Data Mining':               (('Ma',1800,2100), ('Mie',1800,2100)                   ),
            'Inteligencia Artificial':                 (('Lu',1800,2200), ('Ma', 1900,2200)                   ),
            'Metaheurísticas':                         (('Ma',1800,2100),                                     ),
            'Redes Neuronales':                        (('Ma',1800,2100), ('Jue',1800,2100)                   ),
            'Seguridad de la Información':             (('Lu',1800,2200), ('Mie',1800,2200)                   ),
            'Teoría de Juegos':                        (('Lu',1800,2100), ('Mie',1800,2000)                   ),
            'Paradigmas de Lenguajes de Programación': (('Ma',1700,2000), ('Jue',1700,1930)                   ),
            'Bases de Datos':                          (('Mie',1830,2200),('Vie',1700,2230)                   ),
            'Teoría de Lenguajes':                     (('Lu',1800,2100), ('Mie',1700,1930), ('Jue',1930,2200)),
            'Lógicas Modales':                         (('Lu',1400,1800),                                     ),
            'Computación Gráfica':                     (('Lu',1400,1700), ('Vie',1400,1700),                  ),
            'Procesamiento de Lenguaje Natural':       (('Mie',1900,2200),                                    ),
            'Grafos y Tratabilidad Computacional':     (('Ma',1800,2200), ('Jue',1800,2200),                  ),
            'Programación Orientada a Objetos':        (('Lu',1900,2200), ('Mie',1900,2200),                  ),
            'Simulación de Eventos Discretos':         (('Lu',1800,2200), ('Mie',1800,2200),                  ),
            'Visualización de la Información':         (('Vie',1900,2200),                                    ),
}


def sePisan(h1, h2):
    '''Determina si dos horarios se superponen'''
    for c1 in h1:
        for c2 in h2:
            if c1[0] == c2[0]:

                # cual empieza antes?
                if c1[1] <= c2[1]:
                    prim = c1
                    seg = c2
                else:
                    prim = c2
                    seg = c1

                # si la primera termina despues de 
                # que empiece la otra, se pisan
                if prim[2] > seg[1]:
                    return True

    return False


def getDot():
    '''Devuelve un source DOT para el grafo de materias'''
    buf = []
    
    buf.append('graph grafo {')

    # genero IDs para los nodos
    i = 0
    ids = {}
    mats = {}
    for m in materias:
        ids[m] = i
        mats[i] = m
        i += 1

    for i in ids.values():
        buf.append('node%s [label="%s"]' % (i, mats[i]))
 
    ejes = []

    for m1 in materias:
        for m2 in materias:
            if m1 != m2 and sePisan(materias[m1], materias[m2]):
                if not (ids[m2], ids[m1]) in ejes:
                    buf.append('node%s -- node%s' % (ids[m1], ids[m2]))
                    ejes.append((ids[m1], ids[m2]))

    buf.append('}')

    return '\n'.join(buf)


def subconjuntos(s):
    '''Dada una secuencia s devuelve todos los subconjuntos de sus elementos'''
    if s == []:
        return []
    else:
        e = s[0]
        resto = s[1:]

        sin = subconjuntos(resto)
        con = subconjuntos(resto)

        for sub in con:
            sub.append(e)
        con.append([e])

        return sin + con
            

def esIndependiente(s):
    '''Determina si el conjunto de materias es independiente'''
    for m1 in s:
        for m2 in s:
            if m1 != m2:
                if sePisan(materias[m1], materias[m2]):
                    return False
    return True


def esConveniente(s):
    return esIndependiente(s) and \
           "Paradigmas de Lenguajes de Programación" in s and \
           ("Teoría de Lenguajes" in s or "Bases de Datos" in s) and \
           len(s) >= 3
           

if __name__ == '__main__':
    s = subconjuntos(materias.keys())
    
    print "Formas válidas de cursar materias: %s" % len([x for x in s if esIndependiente(x)])
    print "Formas de cursar 'convenientes': %s" % len([x for x in s if esConveniente(x)])
    print

    for c in [x for x in s if esConveniente(x)]:
        print ', '.join(c)