Archivo de la categoría: Lo que he aprendido

Lo que he aprendido: pdfjam y la ANECA

Estoy en plena diversión de la ANECA. Llevo dos semanas pidiendo certificados para justificar todas las actividades que he llevado a cabo en la universidad y añadiéndolas una a una a un formulario. Luego diremos que si endogamia en la academia y cosas, pero ¿qué esperamos si la manera de acreditarse como profesora pasa por haber guardado todos los papeles que te han dado en tu vida? ¿Quién sabe esto?

Lo que nunca imaginé es que este lío de papeles, firmas electrónicas y plataformas estatales con certificados de seguridad caducados me llevaría a aprender a manipular pdfs desde la terminal. Todo ello porque el sistema pide cosas como un documento que reúna la primera y la última página de los artículos publicados u otro con la portada, índice y resumen de la tesis doctoral. En mi entorno windowsero laboral hubiera usado el Acrobat Reader pero (¡oh, ironías!) parece ser que la versión que tenemos no es compatible del todo con la versión que tenemos de Windows.

Me puse por lo tanto a buscar alteranativas. Encontré un par de herramientas visuales como PDFsam, que lleva licencia GPL, y PDFtk y alguna otra herramienta para la terminal como Coherent PDF Command Line Tools pero al final me quedé con PDFjam, un conjunto de programillas para la terminal para manipular archivos pdf basado en el paquete de LaTeX pdfpages. La razón no puede ser más pragmática: viene con las distribuciones de LaTeX por lo que no tenía que instalarlo.

Si habéis usado alguna vez pdfpages, recordaréis que permite incluir en un documento hojas así variadas de un pdf y girarlas, empequeñecerlas o hacer múltiples manipulaciones con ellas. El caso más sencillo, que sería incluir simplemente unas páginas de un pdf en otro documento, tendría una pinta así:

\documentclass{article}
\usepackage{pdfpages}

\begin{document}
    \includepdf[pages={1,6-7,10}]{input}
\end{document}

Pues PDFjam nos permite hacer esto mismo desde la terminal:

pdfjam input.pdf '1,6-7,10' --outfile output.pdf

Extraer la primera página de unos documentos y unirlas en un único documento final se convierte de repente en una tontería:

pdfjam input1.pdf '1' input2.pdf '1' --outfile output.pdf 

¡JA, ANECA, creías que ibas a vencerme!

Me queda como investigación para el futuro hacer un buclecillo que vaya haciendo algo de este tipo automáticamente para todos los archivos de una carpeta.

Otro tema interesante es que las versiones anteriores a la 3.02 incluyen unas pocas funciones para rotar las páginas en sentido antihorario (o positivo para los científicos):

pdf90 input.pdf # produce input-rotated90.pdf
pdf180 input.pdf
pdf270 input.pdf

que, como se puede ver en el repo en el que están ahora son wrappers de pequeños scripts del tipo:

pdfjam --suffix rotated90 --angle 90 --fitpaper true --rotateoversize true "$@"

Leer el manual de pdfpages y compararlo con este script nos ayuda a entender que las opciones de PDFjam son las mismas que las de pdfpages pero con sintaxis de terminal.

¡Otra vez la magia del software libre salva el día!

Aunque igual no…

Ya que cuando creía que tenía todo bajo control hubo un plot twist:

Usted se registró en cl@ve por Internet y el trámite que está intentando realizar requiere que el registro en cl@ve haya sido de forma presencial.

Contra la burocracia no hay magia que sirva.

Referencias

PDFjam en Github

PDFjam-extras en Github

pdfpages en CTAN

Quickly extracting individual pages from a document en TeX exchange

Command line: How do you rotate a PDF file 90 degrees? en Unix&Linux Stackexchange

Lo que he aprendido: la clase standalone

¡He aprendido nuevas cosas LaTeXianas! El tema es que quería hacer un diagrama de flujo con unas ecuaciones y cosas y después de dedicarle quince minutos en el Draw me di cuenta de que estaba perdiendo el tiempo. ¡Cuánto mejor se hacen esas cosas en LaTeX! Encontré un bicho que me molaba en TeXample y me puse a modificarlo.

Todo fue muy bien hasta que me di cuenta de que yo tenía que mandar el historio a una revista y que debían compilarlo allí y que eso iba a fallar seguro. Y luego vendría el horror (¡el horror!) de editar el archivo original hasta que aquello funcionase. Aquí fue cuando (entre sudores fríos) descubrí la clase standalone: una clase que permite compilar un trocito de LaTeX y recorta la salida. Perfecto para crear gráficos, exportarlos y usarlos como si fueran imágenes.

Su uso más básico sería:

\documentclass{standalone}

\begin{document}
Cosas que queremos que aparezcan en un pdf recortado al máximo
\end{document}

El ejemplo anterior igual es un poco ridículo, pero se pilla la idea. Es esto especialmente útil para las imágenes producidas con TikZ. Por ejemplo, para guardar en un pdf una de mis típicas vigas hago:

\documentclass{standalone}

\usepackage{stanli} % paquete para estructuras
\usepackage[ugly]{units} % paquete para unidades

\begin{document}
\begin{tikzpicture}
  \scaling{2};

  % Nodos 
  \point{a}{0}{0};
  \point{b}{3}{0};

  % Barras
  \beam{2}{a}{b}; 

  % Apoyos
  \support{1}{a}
  \support{2}{b}

  % Fuerzas
  \lineload{1}{a}{b}[0][1.5];
  \notation{1}{b}{\unit[6]{kN/m}}[above=18mm];

  % Nombres de nodos
  \notation{1}{a}{A}[left=3mm];
  \notation{1}{b}{B}[right=3mm];

  % Cotas
  \dimensioning{1}{a}{b}{-1.5}[{\unit[9]{m}}]; % horizontal

\end{tikzpicture}

\end{document}

Ahora puedo usar mis dibujos chulis de LaTeX cuando escribo (dios no lo quiera) en Word.

El propio paquete TikZ tiene una opción que hace algo similar, pero implicar activar el shell escape y no me apetecía. Y bueno, que aparte de la clase, también existe el paquete standalone, que hace más cosas y que tal vez investigue en el futuro.

Referencias

Documentación de la clase

Compile a LaTeX document into a PNG image that’s as short as possible en TeX Exchange

Cropping the output file to its content in LaTeX

Lo que he aprendido: formato y exportación de figuras de Matlab

Matlab me está tocando la moral. Qué sorpresa. Me tiene tan sumamente cansada tener que programar en semejante entorno hostil (pun intended) que he decidido adoptar prácticas defensivas. Una de ellas es guardar las imágenes en el formato fig de Matlab y darles el formato que me parezca más tarde con una función. Aprovecho, además, para exportarlas a svg porque mi Matlab está borracho y no me exporta las fuentes correctamente cuando uso eps. Esto implica, claro, que necesito un paso posterior de pasar de svg a eps porque a las revistas no les gusta el svg. Ya veis, hacemos nosotras el currelo pero ellos se ponen exquisitos con los formatos. pero no importa porque viene el software libre al rescata, en este caso Inkscape.

En fin, que os dejo aquí la función que uso para cambiar el estilo de los gráficos y exportarlos y un script de muestra. No funciona bien si la figura tiene subfiguras, pero iremos mejorando.

Cambiar el estilo de una figura en Matlab

Para ello he escrito esta función, que se puede mejorar pero más o menos funciona:

function layout(h, fontSize, font, markerSize, lineWidth, gridOn, sizes)
% Change layout of graphic
%
% LAYOUT(h, fontSize, font, markerSize, lineWidth, gridOn, sizes)
% 
% where:
% - h: figure handle
% - fontSize: fontsize in points
% - font: name of font
% - markerSize: size of markers
% - lineWidth: line width 
% - gridOn: true set the grid to on
% - sizes: [width, height] of output

box on
set(gca,'FontSize', fontSize)
set(gca,'FontName', font)

% Change sizes of all elements
alldatacursors = findall(gcf,'type','hggroup');
set(alldatacursors,'FontSize', fontSize)
set(findall(gcf,'type','text'),'FontSize', fontSize)

% Change line width of all lines and markers
allLines = findall(gcf,'type','line');
set(allLines,'LineWidth', lineWidth)

% Set size of marker
if isprop(gca,'MarkerSize')
    set(h,'MarkerSize', markerSize)
end

% Grid
if gridOn
    grid on
end

x0 = 10;
y0 = 10;
set(gcf,'position',[x0,y0,sizes(1),sizes(2)])

Cambiar el estilo de todas las figuras de una carpeta

Uso la función layout en el archivo figStyle para dar formato y exportar a svg todas los gráficos de una carpeta. Supongo la siguiente estructura de archivos:

.
├── fig
│   ├── fig1.fig
│   └── fig2.fig
├── figStyle.m
├── layout.m
└── svg
    ├── fig1.svg
    └── fig2.svg

Es decir, cogeré las figuras de la carpeta fig y las guardaré en la carpeta svg después de transformadas. He escrito este script para la figuras del paper en el que estoy trabajando:

clear
clc

folder = 'fig';
addpath(genpath(pwd)) % Add subfolder to path
files = ls(folder);
files = files(3:end, 1:end); % delete first two entries (. and ..)
files = cellstr(files); % convert to cell to ease manipulation

number = size(files,1);

% Output names = names without extension
outName = cellfun(@(x) x(1:(end-4)), files, 'UniformOutput', false); 

for f = 1:number

    h = openfig(files{f},'new','invisible'); % open fig without showing
    layout(h, 24, 'Century Schoolbook', 14, 1.5, true, [800,600])

    % Save modified figure
    name = [folder '\..\svg\' outName{f}]; % saves figures in eps folder
    saveas(h,name,'svg')

    close(h);
end

Pasar de svg a eps

Una vez obtenidas las figuras en svg, uso un bucle en la terminal (de Windows) para pasarlas a eps con Inkscape. Aquí tuve líos petardos porque si pongo la carpeta de Inkscape en el Path, tengo un Python extra. Finalmente decidí que lo más práctico era llamar a Inkscape con la ruta completa. Por lo tanto, tiro esta línea en la carpeta donde están los svgs:

for %i in (*.svg) do "C:\Program Files\Inkscape\inkscape" -E %~ni.eps  %i

Aprendí gracias a esta historia que %~n es el nombre del archivo sin extensión. Ya os podéis imaginar la necesidad que tengo yo de saber mierdas cosas de la terminal de Windows. Ah, lo he guardado como svg2eps.cmd para futuro uso.

Y hala, cada día me vuelvo más robótica.


Suena:

Lo que he aprendido: manejar referencias bibliográficas en Emacs

Detesto instalar programas, aprender dónde están los botoncillos en un programa nuevo y que luego no me convenza y vuelta a empezar. Supongo que es uno de los motivos por los que me encanta Emacs: mismo programa, miles de tareas diferentes.

Últimamente he estado hurgando un poco en sus habilidades como gestor bibliográfico. Como ya os conté, yo suelo usar Jabref que es el programa que aprendí a usar en su momento y con el que me apaño bien para añadir referencias directamente desde la web, pero hay veces en las que manejar texto plano a pelo me parece más conveniente. ¡Y para eso no hay nada que iguale a Emacs! Os cuento un poco.

El modo BibTeX

La forma más básica para trabajar con bibliografías en Emacs es el modo BibTeX: se carga directamente al abrir un archivo con extensión .bib y nos permite organizar (M-x bibtex-sort-buffer) y adecentar (C-c C-c ) nuestras referencias.

Para insertar entradas tenemos el comando genérico C-c C-b tras el que podemos usar autocompletado, o el grupo de comandos que empiezan por C-c C-e. Por ejemplo, para crear una entrada de tipo artículo podemos hacer lo siguiente:

  • con C-c C-e C-a (o M-x bibtex-Article) creamos una plantilla para artículo;
  • rellenamos los datos necesarios, algunos comienzan por OPT porque son opcionales;
  • al acabar hacemos C-c C-c (o M-x bibtex-clean-entry) para quitar los campos opcionales que no hemos rellenado y que nos corrija el formato;
  • si no le hemos puesto una palabra clave nos sugerirá una y la entrada estará finiquitada y lista para ser citada.

Otro comando interesante es M-x bibtex-fill-entry (generalmente C-c C-q ) para alinear correctamente cada entrada bibliográfica. Y tampoco está mal establecer la variable bibtex-maintain-sorted-entries para tener las referencias en orden alfabético.

Como siempre, podemos recurrir a M-x describe-mode para que Emacs nos explique qué hace el modo. Es un modo chiquitico, pero muy útil para embellecer la lista de referencias ya que ayuda a cambiar de mayúsculas a minúsculas, quitar espacios innecesarios y míticas mierdas que, a las que somos maniáticas, nos ponen muy nerviosas.

Helm-bibtex

Mi modo favorito para gestionar las referencias bibliográficas en Emacs es Helm-bibtex. Lo descubrí intentando abrir los artículos que cito directamente desde Emacs y lo he introducido directamente en mi rutina de escritura científica (que algún día os contaré) junto con AUCTeX y RefTeX.

Es sencillito de usar: una vez instalado, lo llamamos con M-x helm-bibtex. Nos aparecerá entonces una lista de nuestras referencias bibliográficas en la que podremos elegir la entrada que queramos. Dándole a TAB vemos las acciones posibles, que se ejecutan todas en las teclas F1F12.

Como sugieren en su ayuda, he enlazado M-x helm-bibtex a la combinación Menú + b añadiendo esta línea al archivo de configuración:

(global-set-key (kbd "<apps> b") 'helm-bibtex)    

con la idea de configurar el resto de las historietas de Helm también en la tecla Menú y pulsar menos botoncicos.

Evidentemente, aunque sea muy listo este modo, tenemos que decirle dónde tenemos el archivo de bibliografía, los artículos en cuestión y las notas al respecto, si las estamos usando. Yo, como tengo un archivo y una carpeta con referencias para cada tema, establezco unas variables locales para el artículo que esté escribiendo

%%% Local Variables:
%%% eval:(setq bibtex-completion-bibliography '("refs.bib"))
%%% eval:(setq bibtex-completion-library-path  '("references/"))
%%% End:

pero si tuviera todas las referencias juntas, podría añadir ese par de líneas al archivo de configuración directamente con las rutas correspondientes.

ACTUALIZACIÓN (16/10/2019) Por algún motivo que desconozco (Windows), la ruta relativa dejó de funcionar de un día para otro y tuve que poner la ruta absoluta.

Una cosa que me encanta de este modo es que, por medio de RefTeX, localiza la bibliografía local si se usa helm-bibtex-with-local-bibliography en lugar de helm-bibtex. Algo bastante útil sobre todo cuando estamos manejando bibliografías de otras personas.

De esta manera, cuando estoy escribiendo un artículo y quiero citar algo o a alguien, abro mis referencias, busco entre ellas lo que necesito y abro directamente el archivo en el propio Emacs usando pdf-tools. En Windows (sorpresa) esto no me carrula, así que he añadido esto al archivo de configuración

(setq bibtex-completion-pdf-open-function
  (lambda (fpath)
    (call-process "acrobat" nil 0 nil fpath)))

para que me abra los pdfs con al Acrobat Reader. Si, por lo que sea, lo que busco no está entre mis referencias, el cacharro me busca en repositorios online. Me falta investigar cómo funcionan las notas, que hasta ahora no he tenido necesidad de ellas.

Sigue leyendo

Lo que he aprendido: Julia, Babel y Org

Ya sabéis que me gusta llevar la contraria. También que me gusta el minimalismo y usar el mínimo de herramientas posible. Así que cuando me ha dado por explorar la programación literaria y la investigación reproducible en Julia, en lugar de aprender a utilizar los cuadernos Jupyter como una persona normal, me he puesto a jugar con mi adorado modo Org y su funcionalidad para incluir bloques de código Babel1. Supongo que es lo que tiene ser la única de tu entorno (laboral) que hace estas cosas y no tener por tanto limitaciones en la elección de herramientas. Total, como en la academia no se colabora, no se va a dar el caso de que mi elección me limite. En fin, dejo la academia, que me caliento, y os explicito los motivos:

  • No instalo más software: ya estoy programando en Julia en Emacs así que no necesito mil programas y mi ordenador durará años y años.

  • Utilizo mis atajos de teclado y configuración: como sigo usando el mismo programa, no tengo que aprender dónde están otros botoncillos. Además, tengo definido cómo exportar a pdf desde Org pasando por LaTeX en mi archivo de configuración por lo que el documento final es exactamente como yo quiero.

  • Puedo cambiar de lenguaje de programación: el sistema funciona para una pila de lenguajes de programación. Puedo incluso mezclar código de diferentes lenguajes en un único documento2.

Visto esto, parece que elegir Org es una buena idea, así que paso a contaros en qué consiste la programación literaria, cómo se aplica en Org y qué tiene de especial el caso de Julia.

La idea: escribir para humanos

La idea de la programación literaria, como tantas otras buenas ideas, fue de Donald Knuth. Consiste en cambiar de lector objetivo al escribir un programa: en lugar de una secuencia de instrucciones para una máquina salpicada por algún comentario sobre la implementación, el programa se convierte en una descripción de la lógica detrás de la implementación salpicada por algún fragmento de código. De esta manera, no es necesario descifrar qué hace el programa leyendo el código porque las decisiones de diseño y la lógica se explicitan. Se puede pensar en el programa, entonces, como en una obra literaria.

Como me dedico a los métodos de cálculo, es decir, propongo una manera de calcular algo y luego demuestro mediante un ordenador que mi manera es mejor que la manera anterior, este enfoque me interesa por dos motivos:

  • Investigación reproducible: puedo escribir un artículo científico que incluya mis datos y mi código con lo que quien lo lea puede acompañarme en el proceso, obtener mis mismos resultados y verificar si que mis conclusiones son correctas.

  • Documentación útil: puedo explicar en el propio programa mi proceso mental para implementar numéricamente un cálculo que inicialmente era analítico, incluyendo matemáticas si es preciso.

Solo nos queda responder a una pregunta: ¿cómo demonios se lee esa mezcla de texto y código sin volverse una loca? Pues mediante los procesos de weaving, que deja solo lo humano, y tangling, que deja solo lo que entiende la máquina. ¡A ver si os habíais pensado que el señor Knuth no había pensado en esto! La cuestión aquí es que como tanto la documentación o explicación y el código salen de un mismo documento, ambos crecen juntos y limitamos la típica divergencia de según la documentación esta función tiene dos variables de entrada pero según el código tiene tres.

Programación literaria en Org

Ahora que sabemos qué es lo que queremos hacer, vamos a ver cómo lo hacemos en Org. No puede ser más fácil: cuando queramos meter un cacho de código escribimos

#+BEGIN_SRC lenguaje opciones_cabecera

Código

#+END_SRC

y ya está. Impresionante. Más os voy a decir: los bloques se pueden crear con las plantillas fáciles de Org situándonos en el principio de la línea y haciendo <s TAB.

Para poder ejecutar el trocito de código necesitamos primero decirle a Org que vamos a usar el lenguaje en cuestión y que ese lenguaje sea uno de los soportados. Tan sencillo como ir al archivo de configuración y añadir elementos a la lista de lenguajes:

(org-babel-do-load-languages
(quote org-babel-load-languages)
(quote (
(LENGUAJE1 . t)
(LENGUAJE2 . t)
)))

Ahora si hacemos C-c C-c sobre el trocito, lo ejecutaremos y nos saldrá el resultado debajo. Por seguridad, preguntará si queremos ejecutar y tendremos que contestarle, si somos vagos y nos gusta ver el mundo arder podemos decirle que ejecute todo el código sin preguntar con

(setq org-confirm-babel-evaluate nil)

¡Destrucción! ¡Sí!

Un detallico sobre los resultados: los trocitos de código se ejecutan por defecto como si fueran una función (opción de cabecera :results value) y solo nos devolverán el contenido si se lo pedimos explícitamente, con un return en el caso de Python, por ejemplo. Podemos cambiar la opción a :results output y, entonces, Org nos devolverá el contenido de STDOUT. Para lenguajes interpretados, podemos combinar esta opción con :session, que abre un intérprete y envía allí el código de todos los bloques que contengan dicha opción. Es un poco lío esto, pero jugando un poco con las opciones y leyendo la docu, se entiende.

También usamos las opciones de cabecera para decidir si al crear el documento exportamos el código (:exports code), los resultados (:exports results), el código y los resultados (:exports both) o nada (:exports none); para decirle a Org qué debe hacer con los resultados (:post); o para decir si queremos solo el archivo para la máquina (:tangle ARCHIVO_DESTINO), que por defecto no nos crea.

También podemos configurar cómo exporta el código al documento final. En mi caso, como el documento final es un pdf y eso pasa por LaTeX, quiero que use listingsUTF8 para los bloques de código. Se puede configurar para minted también, claro.

;; Exportar código como listings
(require 'ox-latex)
(setq org-latex-listings t)

;; Paquetes de LaTeX para código
(setq org-latex-default-packages-alist
'((""    "listingsutf8"  t)
("usenames,dvipsnames,svgnames,table"    "xcolor"    t))))

Las cuqueces y los colorinchis no se limitan al documento final, con

(setq org-src-fontify-natively t)

también tendremos colores en nuestro Org.

Ah, por cierto, el trocito de código lo podemos modificar en un buffer especial que se abre con C-c '.

El caso de Julia

Julia es uno de los lenguajes que no tiene soporte directamente en Babel porque su autor no le dio el copyright a la FSF. Por lo tanto, aparte de añadir Julia a la lista de lenguajes que puede usar Org, necesitamos los paquetes ESS y ob-julia.

Luego, hacen falta un par de líneas extra en el archivo de configuración para decirle a ob-julia dónde está el ejecutable de Julia (yo lo tengo en el PATH y por eso no le doy la ruta entera) y decirle a Emacs que use ob-julia:

;; Código Julia en Org
(setq inferior-julia-program-name "julia") ;; nombre o ruta de ejecutable
(require 'ob-julia)

(org-babel-do-load-languages
(quote org-babel-load-languages)
(quote (
(julia . t)
)))

Ale, ya puedo jugar a programar explicándome a mí misma lo que he hecho. Ahora solo me falta aplicar estas ideas al archivo de configuración de Emacs para no romperlo nunca.

Seguiremos informando.

Referencias

Documentación de Babel

Babel: active code in Org-mode

Working with source code en el manual de Org

Introduction to Literate Programming

Emacs para ciencias del dato

Julia with Emacs Org mode

Org-mode and julia: an introduction

Literate Programming Examples

Literate programming with Org-mode

Ten simple rules for writing and sharing computational analyses in Jupyter Notebooks

Drops of Jupyter notebooks: how to keep notes in the information age


Os dejo con música:


  1. También hay un paquete específico para Julia, pero ¿me gusta a mí lo fácil? No. 
  2. Lo digo como su supiese programar en múltiples lenguajes, ¿habéis visto? 

Lo que he aprendido: Julia en Emacs

He conseguido por fin poder programar en Julia usando Emacs. Eh, que no ha sido tan fácil: algo tan sencillo como instalar el julia-mode y el ess se convirtió en un infierno. Me pasó de todo.

Primero en GNU/Linux, como no estaba usando la versión más novedosa de elementary, el Emacs de los repositorios era demasiado antiguo y no compatible con los modos que me hacían falta. Me quedaban varias opciones: (i) actualizar el sistema (lo que finalmente hice); (ii) añadir un ppa con un Emacs más moderno (bien, pero prefiero tener los paquetes de mi distro que ya he organizado alguna petarda); o (iii) compilar Emacs desde fuente (ya lo hice alguna vez y no me apetecía repetir).

Luego en Windows, donde sí tenía un Emacs lo suficientemente moderno, parece ser que Julia tiene no sé que bug y se cuelga y hay que darle a C-g para que se reviva.

En fin, que actualicé el sistema operativo y en quince minutos ya tenía un entorno para programar en Julia. Bueno, eso en mi recién estrenado Juno, en Windows me conformo con Atom, ese editor que no es un editor. Qué dura es la vida a veces.

Después de contaros mis desventuras (para eso tengo un blog), paso a resumir qué hice la vez que funcionó todo.

Julia en GNU/Linux

Julia no está en los repos, nos dejan unos binarios genéricos para que descarguemos y ejecutemos sin más. Hay que elegir unos u otros según la arquitectura de nuestro procesador. Yo, como nunca sé qué tengo lo miro así:

ondiz@slimbook:~$ lscpu
Arquitectura:                        x86_64
modo(s) de operación de las CPUs:    32-bit, 64-bit

Descargados los binarios correspondientes, es útil crear un enlace simbólico a algún lugar donde ya estemos buscando ejecutables o añadir la carpeta donde los hemos descargado al PATH, a gusto del consumidor.

Yo he elegido la primera opción, así que he hecho:

sudo ln -s RUTA_A_EJECUTABLE /usr/local/bin/julia

Cuidadín que hay que poner la ruta absoluta al ejecutable bin/julia que si no no carrula.

Julia en Emacs

Pues lo que decía al principio: para tener un entorno chachi para programar en Julia solo hace falta instalar los modos julia-mode y ess. El primero es el modo oficial para editar Julia y el segundo es un paquete que ayuda a trabajar con lenguajes de programación para estadística (ESS viene de Emacs Speaks Statistics) como R, o en este caso, Julia. Se pueden hacer otras cosas, pero esta es la más simple en mi opinión.

Una vez instalados los modos, para activar una terminal juliana inferior solo hay que hacer M-x julia. Luego ya podemos abrir un archivo en la parte superior y jugar con opciones que nos da el modo ESS.

Llevo poco con el tema y solo he memorizado un par de combinaciones útiles (miento, no las he memorizado, las escribo aquí para mirarlas en el futuro):

  • C-c C-l: carga un archivo completo, lo que sería un include("archivo").

  • C-M-x: ejecuta (me encanta esta palabra) un trozo de código en el REPL.

  • C-c C-z: cambia del script al REPL o viceversa.

Hay también una pila de comandos para gestionar errores y para acceder a la documentación que algún día controlaré. O no. También me falta echarle un ojo a imenu anywhere para que me aparezcan opciones de autocompletado en cualquier lugar. Me lo dejo de deberes.

Curiosamente, lo que más trabajo me dio fue acostumbrarme a no darle a la flecha hacia arriba para repetir el último comando en el REPL. Aquí, como las combinaciones de GNU Readline están ya pilladas, hay que usar M-p y M-n (o C-↑ y C-↓) para moverse por la historia. Comint y cosas, ya sabéis, y si no, con hacer C-h b os enteráis.

Y hala, ya tengo un entorno para programar. Contadme qué usáis vosotros para que aprendamos todos, venga.

juliaEmacs

Referencias

Página oficial de Julia

Manual del modo ess

Julia en el modo ess

imenu anywhere en GitHub


Os dejo con un grupo cuyas canciones suelo berrear en los conciertos de las fiestas de los pueblos vecinos y que tiene el mérito de que no me quedase dormida encima del libro de física de primero de carrera. Era abrirlo y bostezar, oigan.

Lo que he aprendido: cambiar el idioma de la bibliografía en LaTeX

Me he dado cuenta de una cosa: ¡siempre que he escrito en LaTeX he hecho la bibliografía en inglés! Así ocurrió que cuando tuve que escribir un artículo científico en castellano, aparte de que no era capaz de redactar correctamente, no sabía cambiar el idioma de la bibliografía. Qué lamentable.

Hasta que descubrí Flexbib ¡ja! Me diréis pero, Ondiz, loca, usa babelbib y hala. No son las cosas tan fáciles, queridos hermanos, como su nombre indica, babelbib trabaja con babel y yo compilo con XeLaTeX y, por lo tanto, uso polyglossia. Ya veis, siempre llevando la contraria.

En fin, os cuento un poco de qué va Flexbib.

Flexbib o no más hegemonía

Cuando trabajas en el academia acabas acostumbrándote a que los autores en tus referencias sean Fulanito and Menganito, las páginas web hayan sido last accessed in y que tus comillas no sean angulares como deberían ser. Tanto te acostumbras que llegas a creer que, como al cambiar el idioma al documento, ya te pone capítulo en vez de chapter está todo hecho. Pero no es así. Flexbib viene a ayudar en la tarea de automatizar el proceso de referenciar otros trabajos cuando no escribes en la lengua hegemónica de la academia. Hace otras cosas también (elegir un modelo autor-año o numérico, elegir paréntesis o corchetes, controlar qué aparece en la lista de referencias…), pero a mí me importan menos.

Flexbib consta de varios archivos que habría que situar en ciertos lugares concretos de nuestra instalación de LaTeX, pero yo paso olímpicamente de cualquier instrucción que puedan darme y simplemente echo el paquete flexbib.sty, el estilo flexbib.bst y el archivo spanishbst.tex en la carpeta principal de lo que vaya a escribir en castellano.

Luego, en mi preámbulo cargo el paquete con las siguientes opciones

\usepackage[spanish, plain, sort&compress, nocomment, noabstract]{flexbib}
  • spanish porque quiero que las partículas aparezcan en dicho idioma;
  • plain para que me cite con numeritos;
  • sort&amp;compress para que en lugar de [1,3,2] aparezca [1-3];
  • nocomment y noabstract para que no aparezcan los comentarios y el resumen del .bib en la lista de referencias.

También añado el estilo de bibliografía allí donde corresponde con

\bibliographystyle{flexbib}

Con esto mis referencias quedan cuquísimas con sus comillas angulares como mandan los cánones:

referencias

Creo que tengo que plantearme migrar a BibLaTeX. Que, claro, luego no será soportado por ninguna revista académica.

Y nada más, os dejo a vosotros la labor de saber si esto es una entrada técnica o una diatriba en contra del sistema.

Metablogging.

Referencias

Manual de Flexbib (pdf)

LaTeX/Bibliography Management en Wikibooks

Software necesario para la bibliografía con Flexbib


Os dejo con Tomasito zapateando en London. Yo quiero esos botines. Y ese arte.

Lo que he aprendido: scraping con Julia

Tengo la intuición de que los artículos de los periódicos son cada vez más sencillos, de que se usan frases más cortas y palabras más comunes. Es posible que se deba a que yo me culturizo con la edad y que, por lo tanto, no tengo la misma percepción de la complejidad que tenía hace unos años. Como cuando veo Saber y ganar y me sé las respuestas, bueno, las es igual exagerar un poco. O puede ser que ocurra como con Willy Fogg, que hizo que una generación entera se criara oyendo a un león en traje decir “detrás de usted, estimado caballero” o frases del estilo, mientras que los dibujos de ahora hablan más en la línea de la chavalada.

Como navego entre la fina línea que separa la cordura de la sinrazón, he pensado que podría analizar diferentes periódicos en diferentes épocas y ver si mi hipótesis (ha evolucionado de intuición a hipótesis ¿habéis visto?) es correcta. Soy una científica, qué leches. Y de ahí el título de esta entrada: cuando una quiere analizar textos, necesita primero conseguirlos y qué mejor manera que usar una técnica que no puede estar más de moda.

Antes de contar qué he hecho va un disclaimer: esto es el resultado de un par de tardes de investigación por parte de alguien que no sabe programar en general y menos en Julia en particular pero que, imbuida por el espíritu hacker, se ha puesto a darle a todos los botones hasta que ha conseguido algo que más o menos funciona. Así funciona la ingeniería, hermanos.

Lo que he entendido sobre el scrapeo

Veamos, si yo me he empanado de algo, scrapear consiste en crear un robot que navegue por una web como si fuera un humano y se descargue algún tipo de dato para luego analizarlo. Para ello, básicamente hay que localizar en el código fuente de la página el elemento en cuestión para decirle a nuestro robot a dónde debe ir y qué debe filtrar.

En mi caso, fui a la hemeroteca de El País para un día determinado, localicé la url de las noticias de ese día y, para cada una de ellas, descargué el texto. Todo ello lo hice con Julia, que se note que estoy aprendiendo.

Scrapear con Julia

Utilicé los siguiente paquetes:

  • HTTP: nos da funcionalidad cliente/servidor HTTP, lo usé para descargar el HTML de la página.
  • Gumbo: un parser HTML, convierte el HTML en un árbol formado por nodos y elementos.
  • Cascadia: un selector CSS, permite filtrar el output de Gumbo por clase o tipo de elemento, por ejemplo.
  • AbstractTrees: sirve para manejar datos de tipo árbol, útil para pasear por los árboles que genera Gumbo.

Seguramente se podría hacer con otros, pero los ejemplos que fusilé y remezclé utilizaban estos, así que para qué complicarse. Los instalé con pkg desde la terminal de Julia.

El proceso tuvo dos partes: localizar las noticias y extraer el texto de cada una de ellas.

Localizar las noticias

Para localizar las noticias, fui a la hemeroteca, elegí una fecha y me fijé en que la url a la que me mandaba era https://elpais.com/tag/fecha/AAAAMMDD donde AAAAMMDD es la fecha con los cuatro dígitos del año (AAAA), seguido de los dos dígitos del mes (MM) y los dos del día (DD).

Una vez ahí, vi que cada una de las noticias estaba dentro de un elemento cuya clase era articulo-titulo y que contenía la dirección de la noticia en cuestión. Así, si conseguía extraer la url de cada noticia, podría hacer que mi robot fuera a esa dirección y descargase el texto.

Hice lo siguiente:

date = 19851010 # Elegir una fecha
url = "https://elpais.com/tag/fecha/"*date # Montar la url
res = HTTP.get(url) # Descargar HTML
body = String(res.body) # Convertir a texto
html = parsehtml(body) # Parsear HTML
articles = eachmatch(sel".articulo-titulo", html.root); # Seleccionar los elementos que contienen las noticias

# Para cada noticia
for f in PreOrderDFS(articles) # Pasea por los elementos
   if f isa HTMLElement{:a} # Si es un enlace
       url = getattr(f,"href") # Extrae la url
       # TODO: extraer texto de cada noticia
   end
end

Faltaba extraer el texto de cada noticia.

Extraer el texto

Despues, fui a varias noticias y vi que el texto de la noticia en sí estaba dentro de un elemento de clase articulo-cuerpo. Ese elemento estaba formado por otros elementos que estaban formados por otros hasta llegar a los elementos HTMLText que contenían el texto. Solo tenía que pasearme por las hojas (los elementos del árbol que no tienen a su vez elementos) extraer su texto y empalmar los trozos, saltando una línea en el caso de que el texto viniese de un párrafo, sin saltar si no.

Escribí este código y lo introduje en el TODO anterior:

html = parsed(url) # Parsear HTML
content = eachmatch(sel".articulo-cuerpo", html.root) # Seleccionar cuerpo
texto = "" # Inicialización
for elem in Leaves(content) # Pasear por las hojas
   if elem isa HTMLText # Si el elemento es texto
   # Si el texto viene de un párrafo saltar línea
       if elem.parent isa HTMLElement{:p}
           texto = texto*text(elem)*"\n"
       else
           texto = texto*text(elem) # Unir a lo anterior
       end
    end
end

Juntando todo, extrayendo el código repetido en un par de funciones y metiendo los textos de las noticias en un array, me quedó:

using HTTP, Gumbo, Cascadia, AbstractTrees

"""
    getText(HTMLNode)
Extrae texto de objeto HTMLNode
"""
function getText(content)
texto = ""
for elem in Leaves(content)
    if elem isa HTMLText
        # Si el texto viene de un párrafo saltar línea
        if elem.parent isa HTMLElement{:p}
           texto = texto*text(elem)*"\n"
        else
           texto = texto*text(elem)
        end
    end
end
return texto
end

"""
   parsed(url)
Devuelve HTML parseado a partir de URL
"""
function parsed(url)
res = HTTP.get(url)
body = String(res.body)
html = parsehtml(body)
return html
end

"""
   scrapElPais(date)
Descarga las noticias de El País para una fecha dada como AAAAMMDD
"""
function scrapElPais(date)
url = "https://elpais.com/tag/fecha/"*date
html = parsed(url)
articles = eachmatch(sel".articulo-titulo", html.root);
# Inicializar matriz que contendrá textos
raw = String[]
for f in PreOrderDFS(articles)
    if f isa HTMLElement{:a}
       url = getattr(f,"href")
       html = parsed(url)
       content = eachmatch(sel".articulo-cuerpo", html.root)
       articleText = getText(content)
       append!(raw, [articleText])
   end
end
return raw
end
################# MAIN #######################
date = "19760504" # Fecha de las noticias
news = scrapElPais(date)

Y así es cómo se scrapea un periódico sin saber scrapear ni programar ni entender cómo funciona la web. Evidentemente, esto se puede afinar, lo iré haciendo y os contaré. Ahora voy a tratar los datos: contaré el número de palabras total, por párrafo y por frase y miraré cuántas palabras aparecen en la lista de palabras más comunes. Será divertido.

Por cierto, WordPress me revienta la indentación y no tiene resaltador de sintaxis para Julia (estoy usando la de Python), para algo más decente tenéis el snippet de Gitlab.

Referencias

Julia: Introduction to Web Scraping (PHIVOLCS’ Seismic Events)

Web scraping with Julia

Web scraping en diferentes lenguajes en Rosetta Code


Os dejo con rap en galego:

Lo que he aprendido: lista de tareas en un documento en LaTeX

Generalmente, tanto cuando escribo algún texto como cuando “programo” me escribo comentarios a mí misma para recordarme lo que tengo que hacer en el futuro. Esos comentarios empiezan por TODO para que me resulte sencillo recuperarlos todos con un simple grep.

Este sistema es simple y eficaz, pero hay ocasiones en las que me gustaría exportar esos comentarios para mí misma al documento que estoy escribiendo, bien para leerlo en su formato final, bien para indicar algunas cosas a mejorar cuando comparto el borrador con algún colaborador.

Como yo siempre escribo en LaTeX, para estos casos he comenzado a utilizar el paquete todonotes que permite anotar el texto en diferentes colores, añadir una señal que indica que falta una figura, o crear una lista de tareas pendientes al final del documento.

Es un paquetillo muy sencillo de utilizar:

  • Se añade una nota a un párrafo en el margen con \todo{Texto de la nota}
  • Se añade una nota en línea con el texto con \todo[inline]{Texto de la nota}
  • Se añade una figura de mentira para avisar de una que falta con \missingfigure{Descripción de la figura}
  • Se incluye una lista de tareas con \listoftodos, esta lista tendrá unos cuadraditos de colores si le pasamos la opción colorinlistoftodos al paquete
  • Soporta varios idiomas, que se mandan como opción cuando llamamos al paquete
  • Si le pasamos la opción disable al paquete nos ventilamos todas las notas

Me parece especialmente práctico si asignamos significado a algunos colores, ya que así podemos ver rápidamente qué nos falta por hacer.

Os dejo para terminar un ejemplo en el que he usado hyperref para al pinchar en la tarea correspondiente nos envíe al lugar donde debemos trabajar:

\documentclass[a4paper]{article}

\usepackage[colorinlistoftodos, spanish, textsize=small]{todonotes}
\usepackage[hidelinks]{hyperref} % hidelinks para que no pinte el cuadrado
\usepackage{lipsum} % texto de prueba

\begin{document}

\lipsum[1]\todo{Reescribir sección}
\lipsum[2]\todo[inline]{Añadir referencias}
\lipsum[3]\todo[inline, color=green]{Comentar los resultados}

\missingfigure{Gráfico mostrando la relación entre las variables}

\listoftodos

\end{document}

Obtendríamos algo así:

tareas

Como siempre, esto es LaTeX, así que podemos cambiar todo lo que nos apetezca. Espero que os resulte útil y que me contéis vuestros trucos.

Referencias

El paquete todonotes en CTAN

How to add todo notes? en StackExchange


Suena:

Lo que he aprendido: plano de fase con PyPlot en Julia

Todo comenzó porque estaba resolviendo numéricamente una ecuación diferencial ordinaria (EDO para los amigos) y quería ver su comportamiento para diferentes condiciones iniciales. ¿Y cuál es la mejor herramienta para eso? El plano de fase. Así que pinté uno en Matlab y luego, como yo no soy de quedarme satisfecha al terminar algo, me pregunté: ¿cómo se hará esta historieta en Julia?

Después de hurgar en la documentación, dar a todos los botones y pintar cosas sin sentido alguno, lo conseguí con PyPlot, uno de los paquetes que se pueden usar en Julia para hacer gráficos.

Os cuento cómo calculé y cómo pinté. Todo es para Julia 1.0.

Unas notas sobre PyPlot

Antes de meternos en harina, no está de más recordar que Julia permite utilizar diferentes paquetes para dibujar, están entre otros el mítico Plots; GR, que va como un tiro y el que he usado yo esta vez: PyPlot, que es una interfaz para Julia del Matplotlib de Python.

No tengo especial predilección por este paquete, simplemente encontré un ejemplo que se parecía a lo que yo quería hacer y seguí la norma básica de la ingeniería: no reinventar la rueda. Norma especialmente certera cuando eres ingeniera mecánica.

Debo añadir también que PyPlot me funcionó directamente, probablemente porque tenía Miniconda instalado y tal vez Matplotlib también. Ni idea. Estoy todo el rato probando chismes, no sé ya ni lo que hago.

En fin, los gráficos en PyPlot funcionan casi como los de Matlab excepto por un par de cosas que a mí me dejaron loca y os pongo aquí para que no os pase lo mismo:

  • Para mostrar la figura actual en una ventana necesitamos hacer gcf() (get current figure), al menos desde un script.
  • PyPlot añade por defecto las figuras encima de las que ya había. Antes había opción hold on como en Matlab pero se desaconseja su uso.
  • A veces no querremos añadir las figuras encima, para borrar anterior tenemos clf() (clear figure)

Sabiendo esto ya podemos hacer gráficos sin control.

El plano de fase

Para que todo el rollo de la ecuación diferencial sea un poco menos abstracto os voy a dar un poco de contexto: estoy estudiando un sistema de un grado de libertad, es decir, una masa atada a una pared mediante un muelle y un amortiguador.

De esta manera, el plano de fase consiste en un gráfico en el que se representa la posición de la masa en el eje horizontal y su velocidad en el vertical y se pintan unas flechillas que indican la dirección en la que saldrá el sistema al darle unas condiciones iniciales de posición y velocidad.

Nos sirve para ver si aumenta o se reduce su velocidad, tiende hacia una posición de equilibrio o no, o para hacer bonito en un paper, la finalidad última de toda nuestra investigación.

Bien, la ecuación que describe el movimiento del sistema de un grado de libertad es la siguiente:

m\ddot{x} + c\dot{x}+kx = 0

donde el puntico hace referencia a la derivada respecto al tiempo y dos punticos a la segunda derivada. Los valores m (masa), c (amortiguamiento) y k (rigidez) son características del sistema y son conocidos.

Voy a hacer una magia todo loca y convertir la ecuación de segundo orden en dos ecuaciones de primer orden. La primera va a ser simplemente el cambio de variable:

v = \dot{x}

osease: que la velocidad es la derivada de la posición respecto al tiempo.

La segunda proviene de la ecuación original y viene a decir que la segunda derivada de la posición (la aceleración) es la primera derivada de la velocidad y por lo tanto:

\dot{v} = \ddot{x}= -\frac{k}{m}x - \frac{c}{m}v

Si cogemos las dos ecuaciones, reorganizamos de tal manera que las cosas con puntico estén a la izquierda y escribimos el sistema en forma matricial tenemos lo siguiente:

\begin{bmatrix}\dot{x}\\\dot{v}\end{bmatrix} =  \begin{bmatrix}0 & 1\\-k/m& -c/m\end{bmatrix}  \begin{bmatrix}x\\v\end{bmatrix}

Todo este lío nos lleva a algo, paciencia. La cuestión es que queremos ver cómo cambia la posición y la velocidad en cada punto. ¿Y qué cacharro matemático explica cómo cambian las cosas? Exactamente, la derivada. Derivada que precisamente tenemos explícitamente representada en el sistema de ecuaciones.

¿Por qué digo eso? Si yo quiero saber cuánto valen las derivadas de mis variables en el punto (1,0) no tengo más que sustituirlo en la ecuación:

\begin{bmatrix}\dot{x}\\\dot{v}\end{bmatrix} =  \begin{bmatrix}0 & 1\\-k/m& -c/m\end{bmatrix}  \begin{bmatrix}1\\0\end{bmatrix}

como m, c y k son valores conocidos, puedo obtener los valores de las derivadas. Sabiendo esto, puedo pintar una flechillas en el plano que indiquen hacia dónde tiende el sistema si le doy determinadas condiciones iniciales.

Antes de pintar las flechillas, os dejo aquí la función que he escrito en Julia para calcular las derivadas de la posición y el desplazamiento en diferentes puntos del plano. Como es una función genérica, he utilizado x e y para referirme a las variables y u y v para referirme a los cambios en cada punto y no para lo mismo que en el texto. Es aposta para confundir.

Perdonadme la falta de eficiencia y el probable uso de estructuras ridículas, soy novata.

"""
vectorfield(R, [x1 x2 y1 y2])

Calcula el plano de fase de una ecuación diferencial

Input
- R: matriz de coeficientes
- span: límites del campo [x1 x2 y1 y2]

Output
- x : posición
- y : velocidad
- u : vector de desplazamiento en un punto (x,y)
- v : vector de velocidad en un punto (x,y)
"""
function vectorfield(R, span)
# Span
x = range(span[1],span[2],length=20)
y = range(span[3],span[4],length=20)

# Rejilla de puntos
x = repeat(x', length(x)) # solo repite filas
y = repeat(y, 1, length(y))

# Inicialización
u = zeros(size(x));
v = zeros(size(y));

# Derivada en cada punto
for i = 1:size(x,1)*size(x,2)
  der = R*[x[i]; y[i]];
  u[i] = der[1];
  v[i] = der[2];
end

return (x,y,u,v)
end

Trayectoria: Euler progresivo

Antes de que pintemos el gráfico, en plan bonus voy a contar aquí cómo he simulado el comportamiento del sistema en el tiempo con un Euler progresivo, el método más sencillo para resolver una ecuación diferencial numéricamente.

Básicamente consiste en echar una línea desde el primer punto, que conocemos al ser las condiciones iniciales, hasta un poquito más lejos. La línea en cuestión tendrá la pendiente de la derivada en el punto inicial, que conocemos ya que nos la da la ecuación diferencial. Una vez que hemos llegado al segundo punto, tiramos otra línea y así poco a poco vamos avanzando.

Es decir, en el instante de tiempo i+1 x valdrá lo que valía en el instante i más el cambio:

x_{i+1} = x_i + \dot{x_i}h

siendo h el paso que damos en el tiempo.

He escrito una función que me calcula la posición y velocidad del sistema en el tiempo. ¡Cuidado si le quitáis el amortiguamiento que se vuelve inestable! Temas numéricos eh, no se volvería inestable en la realidad.

"""
euler(R, ic, N, h)

Calcula la respuesta a una ecuación diferencial con Euler progresivo

Input
- R  : matrices en Y(t+1) = Y(t) + h*R*Y(t)
- ic : condiciones iniciales
- N  : número de puntos
- h  : paso

Output
- x, v : desplazamiento y velocidad del sistema en el tiempo
"""
function euler(R, ic, N, h)

Y = zeros(2,N);
Y[:,1] = ic;

for t = 1:(N-1)
 Y[:,t+1] = Y[:,t] + h*R*Y[:,t];
end

x = Y[1,:];
v = Y[2,:];

return (x, v)
end

El dibujo final

Ahora que ya sabemos cuánto cambian tanto la posición y la velocidad en los puntos del plano y hemos calculado la trayectoria para un caso concreto, vamos a pintar. Para ello he usado la función quiver que, dándole la posición y los componentes en ambas direcciones, pinta unas simpáticas flechillas.

using PyPlot

# Datos del sistema
m = 1
k = 1
cc = 2*sqrt(k*m)
xi = 0.3
c = xi*cc

# Datos de la simulación
N = 1000
ti = 0
tf = 50
t = range(ti,tf,length=N)
h = t[2]-t[1]

ic = [1 0]'
R  = [0 1; -k/m -c/m]
F  = zeros(2,N)

# Trayectoria
x,v = euler(R, F, ic, N, h)

clf()
plot(x,v)
gcf()

# Plano de fase
span = [-1 1 -1 1]
x,y,u,v = vectorfield(R, span)
q = quiver(x,y,u,v,color="gray")
xlabel("x")
ylabel("v")
gcf()

Así, nos aparece este gráfico:

phase

Aparte de ser muy cuco, este gráfico nos indica que si le damos cualquier tipo de condición inicial a nuestro sistema, tenderá a pararse: todas las flechitas llevan al punto (0,0). O como diría yo si me quiero hacer la interesante: las raíces de este sistema son complejas con parte real negativa.

Y hasta aquí hemos llegado, os dejo una pregunta de deberes: ¿qué pinta creéis que tendría el plano de fase si le quitásemos el amortiguamiento? Contadme vuestras sospechas.

Referencias

Ejemplos de gráficos en Julia


Os dejo con la canción más bonita del mundo.