Entradas 2011


martes, 27 de diciembre de 2011

¿Un paseito por la Luna?

Para celebrar fin de año, os propongo este bonito vídeo que he subido a youtube. En él podremos disfrutar un paseo por la superficie lunar con el Lunar Roving Vehicle. A partir del minuto 0:52 la cámara está filmando encima del rover.

El Apolo 16 fué el penúltimo en alunizar y el primero en hacerlo en una zona montañosa. Se lanzo desde Cabo Cañaveral el 16 de Abril de 1972. En total, la misión duró once días de los cuales tres pasaron sobre la superficie de la Luna. El Comandante John Young y el Piloto Charles Duke son los protagonistas del vídeo.

Molts d'anys i bons! Bon 2012!

miércoles, 21 de diciembre de 2011

lunes, 5 de diciembre de 2011

Shell en django

Ocurre muchas veces que necesitamos una shell en django para realizar pruebas o tareas de mantenimiento. Conseguirla es muy sencillo ya que settings.py se cargará desde el primer momento en que importemos un modelo o cualquier módulo de django.  Lo único que tenemos que hacer es exportar la variable DJANGO_SETTINGS_MODULE con el valor del fichero de settings que queremos utilizar. Yo uso este script (suponiendo que nuestros settings están en settings.py):

shell.sh
export DJANGO_SETTINGS_MODULE="settings"
python


desde aquí ya podemos operar con los modelos:

from gesion.models import Cliente
c=Cliente(clave='444', descripcion='Pepe Perez')
c.save()


Si queremos acceder desde un script independiente en python podemos usar setup_environ de esta forma:

mantenimiento.py
from django.core.management import setup_environ

try:
  import settings
except ImportError:
  import sys
  sys.stderr.write("No encuentro el fichero de settings")
  sys.exit(1)

setup_environ(settings)

....


Espero que os sirva.

jueves, 24 de noviembre de 2011

Copiar pdf a iPhone iPad fácil ubuntu

1) Instalar el lector Stanza en el dispositivo.
2) Conectar el dispositivo al PC. Saldrá un directorio llamado "Documentación sobre iPad->Stanza".

Todo lo que copiemos en este directorio nos saldrá luego en el apartado "downloads" del stanza.

Probado con Ubuntu 11. Happy reading!!

miércoles, 23 de noviembre de 2011

Tiempo EST, CET, CEST, PST

Un twitt refiriéndose al lanzamiento del Curiosity dice:


"Liftoff scheduled for 10:02 a.m. EST. http://www.nasa.gov/msl #MSL".


Vale. ¿Y eso qué hora es en España?. El tiempo EST se refiere al tiempo oficial de la costa este de los EEUU. En España peninsular e Illes Balears estamos en el tiempo CET (Central European Time) o CEST en verano (Central European Sumer Time), es decir en GMT+1 o GMT+2 en verano, GMT corresponde a la hora en el meridiano 0 o meridiano de Greenwich .


Si miramos este mapa de husos horarios de wikipedia vemos que Cabo Cañaveral está en la costa este, en el uso GMT-5 (en amarillo). En invierno, como España está en el huso GMT+1 (en verde) tenemos que sumar 6 horas al tiempo EST para que nos dé en tiempo CET. O sea, el Curiosity será lanzado a las 16:02 h, tiempo de España y les Illes Balears, una hora menos en las Islas Canarias.

El tiempo EST es importante por ser el usado por los grandes núcleos de población de los EEUU (Boston, Whashington, Nueva York y Miami). Otra zona horaria importante es la usada en la costa oeste, el llamado PST (Pacific Standard Time) por ser el usado en Seattle, Portland, San Francisco y Los Ángeles. En este caso el huso está en GMT-08 y por lo tanto hay que sumar 8 horas para transformarlo en GMT y de ahí una hora más para pasarlo a EST. En total hay una diferencia horaria de nueve horas.

Observamos que para calcular la hora equivalente en otro huso que está más al Oeste (ir hacia la izquierda) tenemos que restar los husos que vamos pasando. Para calcular la hora equivalente a otro huso que está más al Este (ir hacia la derecha) tenemos que sumar los husos que vamos pasando. De todas formas, hay que consultar el mapa porque como veis, la hora oficial depende de consideraciones políticas p.e. Groenlandia cae en cinco zonas horarias pero sólo usa tres.

La mayoría de países europeos usan CET (en verde) menos Portugal, Irlanda y Reino Unido a la izquierda en los que hay que restar una hora.

viernes, 18 de noviembre de 2011

Encapsulado del Mars Science Laboratoy (MSL) "Curiosity"

El MSL preparado para su encapsulamiento en la cofia. Imagen NASA/KSC
El rover, debidamente protegido dentro de la cápsula de descenso, está ya dispuesto abordo del cohete Atlas V que lo ha de lanzar el 25 de Noviembre rumbo hacia Marte.

En la imagen la etapa de crucero (de forma redonda en la parte inferior), la cápsula (encima, de color blanco) así como el escudo ablativo (de color marrón) que permitirá la entrada en la atmósfera marciana.

El Curiosity usará un original sistema de amartizaje en varias fases. En primer lugar, el escudo ablativo (aeroshell) frenará el vehículo por el rozamiento con la tenue atmósfera marciana. Después desplegará un paracaídas  aprovechando que la atmósfera es cada vez más densa. A una determinada altitud, se desprenderá el escudo y encenderá sus retrocohetes hasta llegar a poca altura del suelo. En este momento, con la nave parada, el rover descenderá mediante una grúa (sky crane).


La maniobra de entrada, descenso y aterrizaje (EDL - Entry, descending and landing) es una de las más peligrosas de la misión y no han sido pocas las naves que se han perdido durante esta fase. En esta animación con música de película, se pueden seguir toda la secuencia de este original y complejo método.



Más vídeos del MSL en la web de la NASA.

Cargan el Mars Science Laboratoy (MSL) "Curiosity" con el generador de radioisótopos

El MSL ha entrado en la fase de ensamblaje final recibiendo el generador termoeléctrico de radioisótopos que ha de servirle de fuente de alimentación durante su periplo por Marte.
Fuente de alimentación del MSL. Imagen NASA/KSC


martes, 15 de noviembre de 2011

ebooks de EdicionesB. Así si.

EdicionesB saca un nuevo sitio de venta de ebooks a bajo precio y sin DRM. Los precios están comprendidos entre los 2 y los 6€, lo cuál me parece de lo más razonable.

Como bien argumentan los promotores, lo primero es que la gente lea y después seguro que acaban comprando los originales siempre que el precio no sea abusivo.

Fuente: el país.

jueves, 10 de noviembre de 2011

Estado de la Phobos-Grunt

25/11/2011
La estación de la ESA en Australia ha sido incapaz de comunicarse con la sonda aunque esta ha pasado directamente en su linea de visión. Se cree que que la nave está rotando y sólo en el caso de que una de las antenas de baja ganancia apunte en ese momento a la Tierra va a ser posible la comunicación. La única buena noticia es que la órbita se ha estabilizado lo cuál puede significar que todos los sistemas (menos las comunicaciones) están funcionando.

24/11/2011
¡¡¡La sonda está viva!!!  La antena de la ESA en Australia han conseguido la portadora en el primer paso y la telemetría completa en el segundo después de instalar un dispositivo específico para contactar con la phobos-grunt. Ahora se trata de ver si puede reprogramarse el ordenador de abordo y decidir cómo se modifica la misión toda vez que la ventana para la misión completa se ha cerrado.


16/11/2011
Seguimos a la espera de un comunicado oficial pero, según parece, después del lanzamiento de la soyuz TMA-22 el jefe de Roskosmos, Vladimir Popovki, tuvo que enfrentarse a los periodistas que le increparon acerca de la política informativa de su agencia en relación a la phobos-grunt.

Según Popovki, intentarán conectar con la sonda mientras exista ventana de lanzamiento (hasta mediados de diciembre). Relató que en ningún momento han conseguido telemetría de la nave. De lograrlo, al menos nos permitiría saber qué ha ocurrido exactamente para llegar a esta catastrófica situación.

El ordenador de abordo está programado para establecer contacto una vez se ha efectuado el primer disparo. Como este nunca se ha producido parece que es prácticamente imposible recuperar el control del artefacto.

Respecto a la reentrada, afirmó que según sus cálculos el combustible tóxico no debería llegar a tierra ya que haría explosión en la alta atmósfera. Esta opinión no es compartida por otros especialistas.

Russianspaceweb informa de que el contacto con la sonda es muy complicado ya que la baja altura de la sonda hace que apenas entre en la cobertura de las antenas por unos segundos. Estas antenas gigantes fueron diseñadas para misiones de espacio profundo. En estas condiciones es muy difícil retomar en control de la nave. El seguimiento óptico para refinar la órbita tampoco está funcionando ya que son sistemas militares diseñados para seguimientos en órbita geoestacionaria, mucho más elevada que la actual. El personal de la ISS intentó fotografiar la sonda infructuosamente, aunque por la curva de luz parece que tiene los paneles desplegados y está correctamente orientada.

Fuentes:
russianspaceweb.com
spaceflightnow.com


11/11/2001
spaceflight.now no aporta nada nuevo hoy. El diario elpais informa de que prácticamente dan la sonda por perdida y ya especula con el lugar donde chocará y que lleva hidracina en sus tanques. http://www.russianspaceweb.com informa de que la nave ha sido diseñada para que todas las operaciones en esta fase sean automáticas y por lo tanto, toda solución debería ser totalmente improvisada.


10/11/2011
Resumen de la misión phobos-grunt
Según russianspaceweb.com los rádares militares de EEUU han localizado la nave y están ayudando a refinar su órbita. Con estos datos, el control de tierra está intentando reprogramar el ordenador. La órbita impide la visibilidad constante por parte de las estaciones rusas que sólo operan desde su territorio por lo que las operaciones sólo pueden efectuarse cuando la phobos-grunt pasa por encima. Aunque al principio se habló de un plazo de tres días por la carga de las batería ahora se habla de una semana antes de que la ventana de la órbita se cierre.

Llama la atención el gran despliegue mediático anterior al lanzamiento y el silencio que se ha hecho desde que empezaron los problemas.

Detalle de la ruta de escape de la phobos-grunt

09/11/2011
Como sabéis, la phobos-grunt no ha sido capaz de encender sus motores una vez en órbita. Los controladores disponen de tres días antes de que se agoten las baterías que gestionan el ordenador que controla el disparo de los propulsores para dar a la nave velocidad de escape e insertarla en una órbita hacia Marte. La carga de propelentes está intacta pero la nave ha sido incapaz de orientarse y por ello ha entrado en modo seguro. Un aficionado al seguimiento óptico de satélites grabó desde Sao Paulo la inserción en órbita






Fuentes:
http://www.russianspaceweb.com/phobos_grunt_launch.html#11_10
http://www.planetary.org/blog/article/00003252/
http://translate.google.com/translate?hl=es&sl=ru&tl=es&u=http%3A%2F%2Fwww.federalspace.ru%2Fmain.php%3Fid%3D2%26nid%3D18227


Imágenes:
Roskosmos

jueves, 3 de noviembre de 2011

Format a pdf file for Kindle or Kindle DX

I guess everyone have it clear ;-) but just in case I remind you that the easiest way to pass a pdf (which is usually in A4 or letter page size) to kindle is to open the document viewer and print it into a file with A6 page size (or A5 for kindleDX), keeping in mind that we must activate the option "Shrink to printable Area" on the tab "page Scaling".

If you don't have any pdf printer installed because you use windows I recommend the CutePDF.

Formatear pdf para Kindle o Kindle DX

Supongo que todo el mundo lo tiene claro ;-) pero por si acaso os recuerdo que la forma más sencilla de pasar un pdf (que suele estar en formato de página A4) al kindle es abrir el documento en el visor de pdf e imprimirlo  en un fichero pdf con el formato A6 (o A5 para el kindleDX), siempre teniendo en cuenta que tenemos que activar la opción "Encoger a un área imprimible" en la solapa "Escalado de página".

Si no tenéis ninguna impresora pdf instalada por que usáis windows os recomiendo el cutepdf.

miércoles, 2 de noviembre de 2011

Cita de Poincaré

C'est avec la logique que nous prouvons et avec l'intuition que nous trouvons.
Jules Henri Poincaré

sábado, 29 de octubre de 2011

Copia de seguridad en pdf o mobi de archivos con DRM de Adobe

Si habéis adquirido algún libro en las librerías de ebooks españolas os habréis dado cuenta de tres cosas:

  1. Adobe Digital Editions no tiene versión para Linux, lo cuál me parece una falta de respeto a los usuarios de este sistema operativo libre.
  2. El renderizado del documento lo hace el propio digital editions siendo la calidad de visualización inferior al de cualquier visor de pdf.
  3. No podéis leer el documento en vuestro lector de ebooks o tableta.

A mí personalmente me parece una tomadura de pelo, por que para eso es mejor comprarse la versión en papel. Por lo tanto, he decidido compartir este link con vosotros para que podáis realizar una copia de seguridad privada en un formato con el contenido en claro. Tened en cuenta que compartir este fichero en claro puede ser ilegal y debe usarse sólo para mejorar el visionado o leer el texto en la tableta.

Método
Según el autor, el DRM de Adobe tiene una debilidad bastante evidente y es que aunque usa una criptografía fuerte para el texto es muy sencillo reproducir la forma como baja y descifra la clave única de usuario usada para descifrar el texto.

Su método hace uso de dos scripts en python: 

  • Uno de ellos rompe la ofuscación de la clave única de usuario y la graba al disco duro (es conveniente guardarla).
  • El otro descrifa el texto usando esa clave.

Sólo tenéis que pasar el fichero con DRM a linux y ejecutar los dos scripts. Para los usuarios de windows hay instruciones adicionales :


  1. Bajar e instalar Python 2.6 y PyCrypto.
  2. Bajar los dos scripts anteriores y guardarlos en un directorio con los nombres intepkey.pyw e ineptpub.pyw.
  3. Guardar el libro a descifrar en el mismo directorio y ejecutar inetkey.pyw y luego ineptepub.pyw sobre el libro.

miércoles, 26 de octubre de 2011

Archivo histórico de la Royal Society de acceso libre

Desde hoy se puede acceder libremente al archivo histórico de la Royal Society y a la primera "revista científica" que existió como tal. Os dejo este comunicado de un tal Isaac Newton explicando su teoría acerca de la naturaleza de la luz y del color.

http://royalsocietypublishing.org/

lunes, 24 de octubre de 2011

La Coalición de la Voluntad

Este interesante documental nos anima a usar las nuevas tecnologías y su impacto social para hacer frente al cambio climático. Muy recomendable.

La Coalición de la Voluntad from Horatiux on Vimeo.

jueves, 20 de octubre de 2011

Retrasado primer lanzamiento Soyuz desde Guayana

Mientras esperamos el histórico lanzamiento podemos disfrutar de este time-lapse de roskosmos Para seguir el evento en directo: http://spaceflightnow.com/soyuz/vs01/status.html

La primera Soyuz desde Guayana preparada para lanzar satélite de posicionamiento europeo Galileo

La primera Soyuz en ser lanzada desde las nuevas instalaciones de Roskosmos en el espacio puerto de la ESA está siendo cargada de combustible a la espera de la cuenta atrás final prevista para hoy a las 12:30 CEST.
Imagen. ESA

miércoles, 19 de octubre de 2011

Buscant-me

grep -r "yo" /

Cadenas de Markov y filosofía de vida


"El anterior ejemplo es una Cadena de Markov (ver definición 122), cuya principal característica es que, aunque el futuro depende del pasado, el futuro resulta condicionalmente independiente del pasado cuando se conoce el presente. Esta propiedad me parece un principio importante para aplicar a una vida positiva: Todo mi futuro depende solamente de quién soy yo en este momento, independientemente de cómo llegué a ser lo que soy. Mi futuro sólo dependerá de mi pasado si yo no sé quién soy en este momento."

Fuente:
200 Conceptos De Probabilidad, Variables Aleatorias Y Procesos Estocásticos En Redes de Comunicaciones. Marco Aurelio Alzate Monroy. Pág 29.


lunes, 17 de octubre de 2011

Poster de la Phobos-Grunt

Via el incombustible Daniel Marín me hago con el poster de la misión.
Ideal para colgar en la pared de la habitación.
Imágen: Roskosmos (Russian Federal Space Agency)/IKI

La actitud es tan importante o más que el currículo

Entrevista al diari d'Eivissa a Javier Cámara, un especialista en portals de contractació:
"El trabajo en equipo, la flexibilidad, la movilidad y el espíritu emprendedor son algunos de los aspectos que más valora una empresa a la hora de contratar a un trabajador"
Les millors preguntes:
–En estos momentos de recesión, ¿qué perfiles son los más demandados por las empresas?
 –Administrativos, comerciales y vendedores siguen estando al a cabeza de la demanda. Después informáticos, ingenieros y profesionales del sector salud. 

–¿Qué formación complementaria o competencias son las más valoradas entre las empresas que ofertan puestos de trabajo?
–Idiomas sin duda es la más valorada, en muchísimas ofertas se solicita el dominio de  Inglés , Alemán y Francés.
–Por último, ¿qué tres consejos podría dar a toda persona que está buscando empleo en estos momentos y no encuentra salida?
–Que no desespere, que aproveche a formarse lo mejor posible, haciendo cursos, máster, postgrados,  y sobre todo, estudiando idiomas hasta conseguir un nivel muy alto, que es una diferencia competitiva tremenda, y que utilice Internet como herramienta para buscar empleo y generar contactos.



viernes, 7 de octubre de 2011

Uso correcto de super en python

Sea
class Base(object):
    def __init__(self):
        print "Base created"
class ChildA(Base):
    def __init__(self):
        Base.__init__(self)
class ChildB(Base):
    def __init__(self):
        super(ChildB, self).__init__()
¿Qué diferencia hay entre la construcción de A y de B?. Pues ninguna, lo que ocurre es que super (versión B) nos permite mayor flexibilidad para gestionar la jerarquía ya que no tenemos que referirnos a una clase en particular.

Usar super es también la única forma de hacer herencia múltiple aunque yo no la uso por ser fuente de errores.

En python 3, la sintaxis se simplifica de super(ChildB,self).__init__() a super().__init().

Fuentes:
Understanding Python super() and init methods
http://stackoverflow.com/questions/576169/understanding-python-super-and-init-methods

How to use 'super' in python
http://stackoverflow.com/questions/222877/how-to-use-super-in-python

miércoles, 21 de septiembre de 2011

Biblioteca de ebooks técnico-científicos

Muchos ya conoceréis este sitio de ebooks técnicos. Supongo que debe ser ilegal pero para los españolitos como yo, sin acceso a bibliotecas universitarias, es una joya.

martes, 20 de septiembre de 2011

Download a youtube playlist

Do you want to download an entire youtube play list?. Follow these steps:


  1. Download the latest version of youtube-dl. It's a python script that you can save in your donws directory as youtube-dl.py or do a chmod +x and save in /usr/bin
  2. Create a new playlist o access to a ready one. Notice that the url is something similar to http://www.youtube.com/playlist?list=PL444659F515B8CC1B
  3. In your download directory run the python script python youtubel-dl.py --max-quality mp4 -t http://www.youtube.com/playlist?list=PL444659F515B8CC1B



That's all!

Bajar lista de reproducción de youtube

¿Quieres bajarte toda una lista de reproducción de you tube a tu PC?. Pues los pasos son los siguientes:

  1. Bajarte la última versión de youtube-dl es un script python que puedes guardar en el directorio de descargas como youtube-dl.py o hacerlo ejecutable y grabarlo en /usr/bin
  2. Te creas una lista de reproducción o accedes a una ya creada y verás que la url es algo similar a http://www.youtube.com/playlist?list=PL444659F515B8CC1B
  3. En el directorio de Descargas hacer python youtube-dl.py --max-quality mp4 -t http://www.youtube.com/playlist?list=PL444659F515B8CC1B

That's all!

viernes, 9 de septiembre de 2011

Campos de un modelo en Django

Podemos acceder a los campos de un modelo de la siguiente forma:

>>> from django.db import models
>>> from personal.models import Seccion
>>> campos=Seccion._meta.fields
>>> print campos
django.db.models.fields.AutoField object at 0x96a33ac, ...
>>> for a in campos:
...  print a.name
...
id
convenio
descripcion
hora_corte
>>>

Toda la información del modelo está en el _meta. Un modelo puede cargarse dinámicamente con:

model = models.get_model('aplicacion', 'Modelo')

Todas las opciones están bien documentadas en el fuente django/db/models/options.py

miércoles, 7 de septiembre de 2011

Alternativa 3

¿Y qué pasaría si en un tiempo tan lejano como 1977 ya se temiera que hemos pasado el punto de no retorno con el efecto invernadero?. ¿Qué alternativas nos quedarían como especie si la Tierra se volviera inhabitable?.

Alternativa 3, vista en "Las puertas del misterio" de Jiménez del Oso es un documental de 1977 en el que salen muchas imágenes de científicos e instalaciones como laboratorios y radiotelescopios de la época. Aunque la calidad es muy mala os recomiendo que lo veáis hasta el final porque os aseguro que no tiene desperdicio.

Vídeo de youtube

martes, 6 de septiembre de 2011

Bookmarks rápidos en chrome

Parece que los monstruos de google no consiguen acabar bookmarks.google.com Mientras tanto, podemos hacer bookmarks rápidos en chrome (en otros no he probado) de la siguiente forma:

1.- Ctrl+Shift+B para sacar la barra de marcadores
2.- Arrastramos cualquier página desde la barra de navegación a la barra de marcadores.
3.- click derecho sobre el marcador -> Editar
4.- Copiar/pegar este código en el campo URL:

javascript:(function(){var a=window,b=document,c=encodeURIComponent,d=a.open('http://www.google.com/bookmarks/mark?op=edit&output=popup&bkmk='+c(b.location)+'&title='+c(b.title),'bkmk_popup','left='+((a.screenX||a.screenLeft)+10)+',top='+((a.screenY||a.screenTop)+10)+',height=420px,width=550px,resizable=1,alwaysRaised=1');a.setTimeout(function(){d.focus()},300)})();


Supongo que irán mejorando el producto pero de momento sirve.

martes, 30 de agosto de 2011

Sincronizar reloj de servidor con ntp diariamente

Podemos hacerlo creando un script en /etc/cron.daily


cd /etc/cron.daily
sudo vi pon-en-hora.sh
#!/bin/sh
ntpdate hora.roa.es

Guardamos y le damos permisos:

sudo chmod 700 pon-en-hora.sh


Y ya tenemos el servidor con el reloj en hora cada día.

sábado, 6 de agosto de 2011

El futuro de django

Vídeo de la conferencia del Core Developer Alex Gaynor en Agosto del 2011 sobre la evolución de la plataforma.

miércoles, 3 de agosto de 2011

Errores en los comunicados de prensa de la ESA

Hoy me ha yegado este comunicado de prensa de la ESA:

Herschel haya pruebas de la existencia de oxígeno molecular en el Universo
03-08-2011 09:00 AM CEST

El observatorio espacial Herschel de la ESA ha encontrado moléculas de oxígeno en una cercana nube de formación de estrellas. Este descubrimiento es la primera prueba irrefutable de la existencia de oxígeno molecular en el espacio. Con él concluye una larga búsqueda, aunque da pie a nuevas cuestiones.


Sin comentarios...

martes, 2 de agosto de 2011

La suma de la serie de los primeros n números enteros

Aunque viene en todos los libros de matemáticas, hoy quiero contaros una historia de Gauss cuando era niño; es muy útil para motivar a vuestros hijos o para impresionar a los amigos en una larga comida de verano.

Contaba Karl Friederich Gauss 10 años cuando un día en clase y en vista de que se portaban mal, el maestro les castigó a que sumaran los cien primeros números pensando que estarían un largo tiempo sin molestar. Efectivamente, todos bajaron la cabeza hacia sus cuadernos y empezaron las largas sumas pero al cabo de unos minutos un alumno levantó la mano y dijo: Ya está profesor. El malhumorado maestro pidió al alumno el resultado -- cinco mil cincuenta Sr. maestro -- contestó Gauss. Pensando que había hecho trampas el profesor exigió a Gauss que explicara cómo había conseguido la suma tan rápido, a lo que el niño contestó:

En vez de sumar 1+2+3+... he hecho 1+100=101, 2+99=101, 3+98=101 y al darme cuenta de que siempre sumaba ciento uno sólo he tenido que calcular 50 veces ciento uno (50*101=5050)...

Sólo podemos imaginar la cara del profesor al escuchar semejante razonamiento de boca de un niño de 10 años, pero cuenta la historia que así empezó la leyenda del "príncipe de la matemáticas".

Formalmente:

lunes, 25 de julio de 2011

36 años de la Viking I. El día que visitamos Marte.

Marte visto por la Viking
El 20 de julio de 1976, la sonda Viking I de la NASA tomó tierra sobre la superficie de Marte. Era la primera vez que un ingenio humano tocaba la superficie del planeta rojo con éxito y tomaba fotografías de alta resolución así como medidas atmosféricas y de composición del suelo.

Eran los años 70 y prácticamente no había límite a lo que el ser humano pudiera llegar a lograr. La misión era tan ambiciosa que incluso se realizaron análisis biológicos en busca de posible vida extraterrestre. Aún hoy los resultados son inciertos en uno u otro sentido pero las Viking fueron -- junto con las sondas Voyager que visitaron los planetas gaseosos -- uno de los mayores logros de la tecnología, la organización y la potencia industrial de EEUU.

Uno de los principales investigadores de la misión fué el astrónomo Carl Sagan quien, de forma magistral, supo comunicar a su país y al mundo la necesidad de la exploración espacial como forma de conocimiento de nosotros mismos.

Ahí queda para el que lo quiera ver.



Marte visto por la Viking I

Imágen: The Viking Project/NASA

viernes, 22 de julio de 2011

Adéu al transbordador

No puc resistir-me a reproduir un poema que cita en Daniel Marín al seu blog Eureka com a despedida del darrer vol d'un transbordador espacial.

Disturb us, Lord, when
We are too well pleased with ourselves,
When our dreams have come true
Because we have dreamed too little,
When we arrived safely
Because we sailed too close to the shore.
Disturb us, Lord, when
With the abundance of things we possess
We have lost our thirst
For the waters of life;
Having fallen in love with life,
We have ceased to dream of eternity
And in our efforts to build a new earth,
We have allowed our vision
Of the new Heaven to dim.
Disturb us, Lord,
to dare more boldly,
To venture on wider seas
Where storms will show your mastery;
Where losing sight of land,
We shall find the stars.
We ask You to push back
The horizons of our hopes;
And to push into the future
In strength, courage, hope, and love.

Francis Drake, 1577.

Hasta siempre, transbordador.

jueves, 23 de junio de 2011

Ejecutar scripts mysql a lo Unix

Una forma es

mysql -u root -p -h localhost nombre_bd < script.sql

y otra

cat script.sql | mysql -u root -p -h localhost

lunes, 20 de junio de 2011

Cuidado con el directorio de instalación de django

El directorio de instalación, tal y como indica el manual , lo obtenemos con

from distutils.sysconfig import get_python_lib;print get_python_lib()

y muestra

/usr/lib/python2.6/dist-packages

Peeero, en realidad en ubuntu se instala en

/usr/local/lib/python2.6/dist-packages
o
/usr/lib/pymodules/python2.6/django

¿Cómo podemos saber la localización de este directorio?. Pues usando la librería sys, que mantiene la localización del __init__.py de cada import:

Python 2.6.5 (r265:79063, Apr 16 2010, 13:09:56)
[GCC 4.4.3] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import sys, os, django
>>> sys.modules['django']
module 'django' from '/usr/local/lib/python2.6/dist-packages/django/__init__.pyc'

Sacado de esta entrada de stackoverflow http://stackoverflow.com/questions/2647862/how-can-i-tell-what-directory-an-imported-library-comes-from-in-python

domingo, 19 de junio de 2011

Opciones para programación con vi / vim

Esta es la config que uso en ~/.vimrc para editar python


syntax on
set number
set expandtab
set tabstop=4
set shiftwidth=4
set nowrap
set foldmethod=marker
set smartindent
set mouse=a
set foldmethod=indent
set foldlevel=99
autocmd BufRead *.py set makeprg=python\ -c\ \"import\ py_compile,sys;\ sys. stderr=sys.stdout;\ py_compile.compile(r'%')\"

autocmd BufRead *.py set efm=%C\ %.%#,%A\ \ File\ \"%f\"\\,\ line\ %l%.%#,%Z %[%^\ ]%\\@=%m

autocmd BufRead *.py nmap :!python %

map ^T :Texplore <CR>


Para sacar el control+T hacemos ctrl+v y luego ctrl+t.

Con esta configuración:
:make para ver errores de sintaxis.
za hace fold/unflod dentro de un método
:retab cambia todos los tabs por espacios o al contrario, según config actual

Window splits
Para dividir la pantalla y no tener que estar arriba y abajo con el mismo fichero:
Vertical Split : Ctrl+w + v
Horizontal Split: Ctrl+w + s
Close current windows: Ctrl+w + q

Unos cuantos links
Un montón de trucos.
El wiki de los trucos.
El clásico Turning Vim into a modern Python IDE.
Artículo Beginner's guide to Vi Improved

sábado, 4 de junio de 2011

Cambiar tamaño de disco en qemu kvm

Una posible forma es la siguiente, suponemos que el disco inicial es inicial.qcow2:

1.- crear disco de destino del tamaño deseado p.e. 60G
qemu-img create -f qcow2 destino.qcow2 60G

2.- arrancamos gparted con un sistema con los dos discos
qemu -hda inicial.qcow2 -hdb destino.qcow2 -cdrom=gparted.iso -boot d

3.- con el gparted hacemos copiar/pegar de un disco a otro con el nuevo tamaño deseado
(tarda bastante si los discos son grandes)

4.- comprobamos que boota y nuevo tamaño de disco
qemu -had destino.qcow2
hacemos df -h para comprobar nuevo tamaño

Si el nuevo dominio no arranca podemos usar la distribuición rescatux y regrabar el grub en la MBR (gràcies Victor ;-))

qemu -hda destino.qcow2 -cdron=rescatux.iso -boot d

Pasar de VirtualBox a KVM o Xen

Para pasar un disco de vdkm o vdi a qcow2 pasamos primero por raw. Es decir:

convertim vmdk de virtual box a raw:
VBoxManage internalcommands converttoraw aaa.vmdk file.raw

comprbar que boota
qemu -had file.raw

Convertimos raw a qcow2
qemu-img convert file.raw -O qcow2 imatge.qcow2

comprobar que boota
qemu -had imatge.qcow2

Cómo virtualizar con ubuntu kvm y no morir en el intento

Ni se os ocurra seguir la server guide porque no solo no funciona sino que confunde. El manual apropiado es el "community"

Community KVM installation

sábado, 21 de mayo de 2011

Python extraer año de datetime.date


datetime.date.today().isocalendar()[0]

Python, más aritmética con meses


def suma_mes(current_date, month_step):
""" suma month_setp mesos a current_date """
carry, new_month=divmod(current_date.month-1+month_step, 12)
new_month+=1
return current_date.replace(year=current_date.year+carry, month=new_month)


¿Cuántos días faltan para el mismo día de hoy del mes que viene?


>>> print (suma_mes(datetime.date.today(), 1)-datetime.date.today()).days

Sumar un mes con python


>>> from datetime import date
>>> current_date=date.today()
>>> carry, new_month=divmod(current_date.month-1+1, 12)
>>> new_month+=1
>>> current_date=current_date.replace(year=current_date.year+carry, month=new_month)
>>> print date.today()
2011-05-21
>>> print current_date
2011-06-21
>>>

lunes, 4 de abril de 2011

Ubuntu One trabaja con IIS!!!

Anda que... estaba yo sicronizando música con Ubuntu One, me da un error de red y me sale:

The page cannot be found

The page you are looking for might have been removed, had its name changed, or is temporarily unavailable.

Please try the following:

  • Make sure that the Web site address displayed in the address bar of your browser is spelled and formatted correctly.
  • If you reached this page by clicking a link, contact the Web site administrator to alert them that the link is incorrectly formatted.
  • Click the Back button to try another link.

HTTP Error 404 - File or directory not found.
Internet Information Services (IIS)


Technical Information (for support personnel)

  • Go to Microsoft Product Support Services and perform a title search for the words HTTP and 404.
  • Open IIS Help, which is accessible in IIS Manager (inetmgr), and search for topics titled Web Site Setup, Common Administrative Tasks, andAbout Custom Error Messages.
UArrrrrrgggg!!

viernes, 11 de marzo de 2011

Django: Evitar error en el administrador "decoding Unicode is not supported"

Si, como es probable, os habéis encontrado con este error en el administrador cuando examináis modelos con caracteres utf-8, creo que puede deberse al hecho de que django sirve los strings en unicode pero sin codificar.

En python, en el momento que intentamos algo como esto:

>>> unicode('pepe', 'utf-8')
u'pepe'
>>> unicode(u'pepe', 'utf-8')

Traceback (most recent call last):
File "", line 1, in
TypeError: decoding Unicode is not supported

Obtenemos el TypeError. En el admin de django, el error lo obtendremos siempre que grabemos caracteres >255. Parece provenir del hecho de codificar el unicode en ascii en vez de utf-8 ¿?.

Si hacemos:

def __unicode__(self):
return unicode(self.descripcion)


Obtendremos el error de decodificación ascii, pero si hacemos...


def __unicode__(self):
return unicode(self.descripcion, 'utf-8')


...nos funcionará pero no podremos usar el admin para examinar el modelo porque nos genera el error anterior.

Tenemos dos posibilidades, aunque no las comprendo en profundidad:

Solución 1):

from django.utils.encoding import smart_unicode

En los modelos poner:

def __unicode__(self):
return smart_unicode(("%s" % self.descripcion))


Solución 2) Llamado "método del literal"

def __unicode__(self):
return (u"%s" % self.descripcion)


En todo caso es conveniente poner el setting

DEFAULT_CHARSET='utf-8'

que fuerza utf-8 a la hora de procesar y servir las plantillas.

Más info sobre este tema estaría bien. En mi caso uso mysql con utf-8 y ordenación spanish2, ubuntu 10.10 con utf-8 y apache forzado a servir utf-8.

jueves, 10 de marzo de 2011

Django: Guardar imágenes (o blobs) desde la red

Debido a las consultas amplío el post anterior para aclarar un poco el proceso suponiendo que bajamos las imágenes desde un servidor sFTP, sólo hay que cambiar los parámetros de pycurl para operar con http, https, etc...

Primero bajamos la imagen a memoria con algún gestor (pycurl por ejemplo o urllib) y guardarlo en un cStringIO:


import pycurl, cStringIO

buf = cStringIO.StringIO()
url=('ftps://%s:990/%s' % (ip, fichero))
privatekey = '/home/sss/.ssh/id_rsa'
options = {
pycurl.USERPWD: 'xxxxx:xxxx',
pycurl.SSLKEYPASSWD: 'adfasdfasdfas',
pycurl.SSH_PRIVATE_KEYFILE: privatekey,
pycurl.SSH_PUBLIC_KEYFILE: privatekey + '.pub',
#pycurl.WRITEDATA: open('/dev/null', 'wb'),
pycurl.VERBOSE: 1,
pycurl.URL: url,
pycurl.HEADER: 1,
pycurl.NOBODY: 1,
pycurl.WRITEFUNCTION: buf.write,
pycurl.NOPROGRESS: 1,
pycurl.SSL_VERIFYPEER: 0,
pycurl.SSL_VERIFYHOST: 0,
}

gestor = pycurl.Curl()
try:
for (k, v) in options.items():
print k, v
gestor.setopt(k, v)
except Exception, msg:
logging.info('Error setopt %s' % msg)

gestor.perform()



Ahora ya tenemos la imagen en memoria (buf), vamos a grabarla (django la graba en disco y en la db solo se guarda el path), el único problema es que ImageField espera un campo file, pero lo solucionaremos con un workaround:

En tu modelo pones:

class Persona(models.Model):
.....
imagen=models.ImageField(upload_to=settings.PATH_FOTOS_CLIENTES, blank=True)


Donde settings.PATH_FOTOS_CLIENTES apunta a la ruta que cuelga de la ruta que tengas en settings.MEDIA_ROOT y tiene el formato siguiente o similar (en settings.py):


PATH_FOTOS_CLIENTES='clientes/%Y/%m/%d'


Ahora tenemos que pasar de la imagen que tienes cargada en memoria a un stream tipo 'file' para que pueda ser guardado por el modelo:


from django.core.files.uploadedfile import SimpleUploadedFile

foto = SimpleUploadedFile('imagencliente.jpg',
buf.getvalue(),
"image/jpeg")


y ya salvamos:

p=Persona( imagen=foto )
p.save()


Comentad si os surge alguna duda.
Saludos,
Pere Vilás.

miércoles, 9 de marzo de 2011

Django: Guardar imágenes desde string

Para guardar una imagen en un campo de tipo ImageField de Model desde una cadena como un POST http o desde memoria hacemos lo siguiente:


from django.core.files.uploadedfile import SimpleUploadedFile
import cStringIO

buf = cStringIO.StringIO()
# adquirimos imagen y la guardamos en buf i.e. mediante pycurl

foto = SimpleUploadedFile('imagen.jpg', buf.getvalue(), "image/jpeg")

# ahora foto contiene el stream pero en formato 'fichero'

p=Modelo( imagen=foto )
p.save()



Espero que os sirva ;-)

Django en la red con el servidor de desarrollo

No basta con python manage.py runserver [num_puerto], esto sólo lo hace accesible desde loopback, para servir en red hay que hacer

python manage.py runserver [ip_fisica]:[num_puerto]


Para saber nuestra ip podemos hacerlo con ifconfig, evidentemente no podemos usar localhost o 127.0.0.1

jueves, 24 de febrero de 2011

Consultas en Django

Unos pequeños apuntes cogidos al vuelo de consultas en django


Un queryset sería el equivalente a un SELECT
Un filter sería el equivalente a un WHERE

Comandos de Query:
Objeto.objects.all() -> Todo el conjunto
Objeto.objects.filter() -> Un filtro para incluir
Objeto.objects.exclude() -> Un filtro para excluir
Objeto.objects.get() -> Busca un solo objeto

Encadenado de filtros

Entry.objects.filter(
headline__startswith=’What’
).exclude(
pub_date__gte=datetime.now()
).filter(
pub_date__gte=datetime(2005,1,1)
)

Todos los que empiezan por What entre 1/1/2005 y ahora.

Cada filtro crea una consulta única

q1=Entry.objects.filter(headline__startswith=’What’)
q2=q1.exclude(pub_date__gte=datetime.now())
q3=q2.filter(pub_date__gte=datetime(2005,1,1))

Buscar un solo objeto con get()

one_entry=Entry.objects.get(pk=1)
Si no hay datos salta la excepción DoesNotExist

from django.core.exceptions import ObjectdoesNotExist
try:
one_entry=Entry.object.get(pk=numero)
except ObjectDoesNotExist, e:
mensaje=("La entrada %n no existe" % (numero))





En cambio filter()[0], no hace saltar ninguna excepción.

Limitar el número de registros devueltos

Entry.objects.all()[:5] # los cinco primeros
Entry.objects.all()[5:10] # del quinto al décimo

Buscar sobre campos

Básicos: Son de la forma campo__tipobusqueda=valor
Ejemplo: Entry.objects.filter(pub_date___lte=’2006-01-01’) se transforma en select from blog_entry where pub_date<=’2006-01-01’

-> exact : headline__exact=’algo’
-> iexact: case insentive exact
-> contains
-> startswith
-> endswith

Relacionales

Entry.objects.filter(blog__name__exact=’Pep’)

Blogs.objects.filter(entry__headline__contains=’Pep’, entry__pub_date__year=2006)
Todos los blogs que tengan alguna entrada cuyo titulo tenga Pep y se haya publicado en 2006

Blogs.objects.filter(entry__headline__contains=’Pep’).filter(entry__pub_date__year=2006)
Todos los que tengan Pep y todos los que se hayan publicado en 2006

Filtros que referencian a otros campos del mismo modelo

from django.db.models import F
Entry.objects.filter(n_coments__gt=F(‘n_pingbacks’))

gt: greather than
n_pingbacks: valor de otro campo del mismo modelo

Primary key

Blog.objects.get(pk=valor)
.get(pk__in=[1,4,7])
.get(pk__gt=14)

Caching

Esta consulta se realiza dos veces:
print [e.headline from p in queryset]
print [e.pub_date from p in queryset]

Esta, sólo una vez (cacheo de resultados):
queryset=Entry.objects.all()
print [p.headline form p in queryset] <- En esta se cachea
print [p.pub_date form p in queryset] <- en esta su usa la caché

Consultas complejas con Q

Las palabras clave en filter, etc... son ANDs, si queremos algo más complejo, necesitamos Qs

django.db.models.Q

Q(question__startswith=’Who’) | Q(question__startswith=’What’)
Q(question__startswith=’Who’) | ~Q(question__startswith=’What’)
Poll.objects.get( Q(question__startswith=’Who’),

Q(pub_date=date(2005,5,2)) | Q(pub_date=date(2005,5,6)) )


Comparando objetos

Para comparar dos objetos usamos el == estándar de python
una_entrada==otra_entrada

La comparación se realiza siempre usando la clave primaria

Borrando objetos

Entry.objects.filter(pub_date__year=2005).delete()
Borra todos los elementos y los foreign key que le apuntan en cascada

b=Blogs.objects.get(pk=1)
b.delete() -> borra la entrada y todos sus comentarios

Update de varios elementos

Entry.objects.filter().update(headline=’Cambiado’)

Objetos relacionados

Si un modelo tiene un foreign key, podemos acceder al objeto foráneo via simple atributo del modelo:

e=Blog.objects.get(id=1)
e.entry_set.all() --> todas las entradas del primer blog
e.entry_set.filter(headline__contains=’Pep’)

Si se ha usado el related_name en la definición del modelo, entonces ese es el nombre del atributo para acceder

blog=ForeignKey(Blog, related_name=’entries’)

b=Blog.objects.get(id=1)
b.entries.all()
b.entries.count()

Métodos del Foreign Manager:
relacionado.add(ob1, obj2, …) Añade al objeto relacionado
relacionado.create(**kwargs)
relacionado.remove(obj1, obj2, …)
relacionado.clear() -> borra todos los objetos relacionados

O también:
b=Blog.objects.get(id=1)
b.entry_set=[e1, e2, …] <- un objeto iterable

Hacer siempre el save del objeto principal para que permanente.