Zim - настольная вики, структуризатор и каталогизатор в одном флаконе: zim wiki outliner



39 коммент.
Согласно заветам Ильича, коммунизм есть советская власть плюс электрификация всей страны. Так и Zim, в духе духа духовных предков, представляет собой каталогизатор (outliner) плюс возможность пользовать вики-разметку. Простой и незатейливый, но полезный в хозяйстве, Zim поможет простым колхозникам быстро разгрести ворох заметок, файлов и набросков и превратить в организованную структуру, расфасованную по каталогам.

Читать далее

ЛаТеХ для продвинутых. Как подружить LaTeX и MATLAB: вставка рисунков из MATLAB в документы LaTeX



39 коммент.

В документе всё должно быть прекрасно — и текст, и картинки

Благодаря ЛаТеХу научные работники (и не только) получили возможность создавать красивые, уравновешенные документы с чётко просматривающейся структурой. Однако "сфера влияния" ЛаТеХа распространяется только на текст и формулы, а внешний вид графиков и иллюстраций находится полностью на совести автора. И вот здесь-то и начинаются полные разброд и шатания: на некоторые рисунки трудно смотреть без слёз :)

Целью данного поста является продемонстрировать один из способов создания математических графиков гармонично сочетающихся с окружающим их текстом.

Постановка задачи

Что отличает рисунок гармонично вписывающийся в основной текст от рисунка плохого? Безусловно, содержание, размер и расположение являются важными эстетическими параметрами. Однако наиболее бросающимся в глаза диссонансом, свойственным львиной доле естественно-научных рисунков, являются шрифты. Да-да, именно шрифты... Речь идёт о подписях к осям графиков, о легендах и т.п. Порой создается ощущение, что у автора серьёзные проблемы со зрением: скажем, рядом с текстом набранным Times 12pt вдруг оказывается график с подписями 16-ым шрифтом... Или, ещё лучше, нечитаемым 8-ым... А о соответствии типа шрифта (начертания) между рисунками и текстом и мечтать не приходится!

Итак, наша основная задача: графики, шрифт на которых совпадает по размеру и начертанию с основным шрифтом документа.

Все дороги, которые ведут в Рим

Достичь нашей цели можно разными путями. Наиболее общеизвестные из них, в порядке убывания ортодоксальности:

  1. Использовать LaTeX для построения графиков. На деле это означает либо использование pgfplots и tikz, либо pstricks.
  2. Использовать около-ЛаТеХные средства, хорошо взаимодействующие с ЛаТеХом. Например, MetaPost или Asymptote.
  3. Использование вашей любимой программы (например, Matlab, Mathematica, Gnuplot и т.д. в сочетании с тем или иным способом конвертации в "ЛаТеХ-код", скажем tikz. Более конкретно: например, matlab2tikz. Или tikz терминал для Gnuplot.
  4. И, наконец, использование вашей любимой программы, как и в предыдущем пункте, с сохранением картинки как eps или pdf и последующей "подменой текста", a la psfrag и т.п.

Каждый из этих способов имеет свои достоинства и недостатки, обсуждение которых выходит за рамки данного поста. Последний способ является, по мнению автора, оптимальным по параметру "отношение качества результата к затраченному времени". Поэтому, именно ему и будет уделено внимание.

В этом посту мы рассмотрим алгоритм экспорта графиков из MATLAB в LaTeX.

Выбор Матлаба для построения графиков диктуется исключительно личными предпочтениями автора. Аналогичные методы применимы и к другим программам — об этом в самом конце.

Как ЛаТеХ с Матлабом подружить

Цель

Собственно: экспорт графиков из Матлаба в ЛаТеХ. При этом предполагается, что подписи и т.п. на графике должны сочетаться с основным текстом.

Желаемый результат изображен ниже. Специально выбран нестандартный фонт (Kepler-подобный из kpfonts вместо стандартного Computer Modern), чтобы подчернуть желаемый эффект.

Средства

Матлаб, версии новее 7.6 (release name 2008a). Кроме того, скрипт matlabfrag.m. Его можно скачать самостоятельно, но он (вернее его улучшенная версия) есть и в архиве с примерами из этого поста: tinyurl.com/amorua-matlabfrag. Поместите его в текущую директорию: туда где будут находиться ваши скрипты для построения графиков. Поместите туда же файлы myfigure.m и mylegend.m из того же архива с примерами.

ЛаТеХ. Нам понадобится пакет pstool, причём версия 2013/02/11 v1.5 или новее. В старых версиях пакета будет работать всё, кроме ссылок из картинок на основной документ, например, на уравнения или номера страниц. Файл pstool.sty нужной версии находится в архиве с примерами. Все примеры можно компилировать либо
pdflatex -shel-escape имя-файла
либо
latex -shell-escape имя-файла
dvips имя-файла
pstopdf имя-файла.ps

но предпочтение должно быть отдано первому варианту.

Если -schell-escape опция не работает, возможно в вашей версии ЛаТеХ она называется -enable-write18.

Строим график

Здесь всё почти как обычно:

01:  %% example 1
02:  close all ; clear all; clc;
03:  %% Интерпретатот текста, по умолчанию, latex
04:  set(0,'DefaultTextInterpreter', 'latex');
05:  %  Размер шрифта такой же как в ЛаТеХ-документе
06:  set(0,'DefaultAxesFontSize',12);
07:  set(0,'DefaultTextFontSize',12);
08:  
09:  %% Создаём картинку   
10:  fig=figure;
11:  %% Рисуем графики ...
12:  x=0:0.1:pi;
13:  y=sin(x); plot(x,y,'r'); hold on;
14:  z=cos(x); plot(x,z,'b');
15:  
16:  %% Подписи к осям
17:  xlabel('$t$, s'); ylabel('$l$, m');
18:  %% Легенда
19:  l=legend('$\sin x$','$\cos x$');
20:  
21:  %% Дополнительный текст на графике
22:  text(0.5,-0.5,'$\int\limits_0^{2\pi}\sin x\, dx = 0$');
23:  text(3,-0.5,'$\gamma = \frac{\alpha}{\zeta}$');
24:  
25:  %% Экспортируем график 
26:  matlabfrag('figs/example1','epspad',[10,10,10,10]);

Теперь по порядку:

  1. В строке 4, latex установлен как интерпретатор текста по умолчанию. Благодаря этому, в подписях к осям (строка 17), легенде (строка 19) и дополнительном тексте (строки 22, 23) мы можем спокойно использовать ЛаТеХ-комманды.
  2. Затем, надо проинформировать Матлаб о том, что весь текст мы хотим набирать 12-ым шрифтом (если используется используется "улучшенная" версия matlabfrag из архива с примерами, то устанавливать размер шрифта не надо — будет автоматически подхвачен текущий размер из ЛаТеХ-документа).
  3. После того как всё готово, в строке 26, использована функция matlabfrag() для сохранения графика. Она создаст два файла: figs/example1.eps и figs/example1.tex (предполагается, что в текущей директории вы создали поддиректорию figs/, куда мы будем складывать все картинки). Если посмотреть на их содержимое, то станет понятно, как это всё работает.
    Сама картинка находится в eps-файле, но вместо текста там "числа-заглушки", вроде 000, 001, 002 и т.д. В tex-файле же находится весь текст в виде, понятном ЛаТеХу.
    Теперь дело за ЛаТеХом.

Вставляем график в документ ЛаТеХ

Как видно из предыдущего рисунка, ЛаТеХ-текст будет вставлен с помощью команды \psfrag из одноимённого пакета. Однако, гораздо удобнее пользоваться им не напрямую, а через интерфейс, предоставляемый пакетом pstool. Делается это так: подключаем пакет pstool и вставляем картинку командой \psfragfig{}.

01:  \documentclass[12pt]{article}
02:  ...
03:  \usepackage{pstool} 
04:  ...
05:  \begin{document}
06:  ...
07:  \begin{figure}\centering
08:    % вставляем картинку: 
09:    % имя файла без расширения!!!
10:    \psfragfig{figs/example1}
11:    \caption{Example of a Matlab plot.}\label{fig:ex1}
12:  \end{figure}
13:  ...
14:  \end{document}

Обратите внимание, что имя файла картинки без расширения. Если картинка находится не в текущей директории, то нужно указать путь к ней.

Кроме того, размер шрифта в самом первой строке установлен в 12pt, в соответствии с размером шрифта на рисунке в Матлабе.

Компилируем командой
pdflatex -shell-escape имя-тех-файла
Пакет pstool сделает за нас всю чёрную работу: он сам сконвертирует на лету связку файлов eps+tex в pdf картинку и вставит её: он прогонит автоматически каждую картинку через ЛаТеХ, dvips и pstopdf. Именно для этого и надо указать ключ -shell-escape при запуске pdflatex — он разрешает пакету запускать внешние программы.

Пакет pstool достаточно разумен: он смотрит на дату создания файлов картинок и "конвертирует" только изменившиеся со времени последнего запуска. Чтобы принудительно переконвертировать все картинки, надо указать опцию process=all, а именно

01:  ...
02:  \usepackage[process=all]{pstool} 
03:  ...
Результат наших усилий показан внизу. Как видите, на графике использованы Computer Modern шрифты ЛаТеХа, размер которых совпадает с размером, использованным в тексте (см. подпись к рисунку).

Тонкая настройка

Теперь, когда последовательность действий в достаточной степени понятна из предыдущего примера, можно обратить чуть больше внимания на детали.

Деталь нулевая

Деталь, к matlabfrag() прямого отношения не имеющая, но тем не менее... Наилучшего, с эстетической точки зрения, результата можно добиться, если вставлять в ЛаТеХ рисунки в том масштабе, в котором они были нарисованы. Т.е. рисовать их лучше сразу в нужном размере! Для этого создаём в Матлабе простенькую функцию

01:  function h=myfigure(width,height)
02:  % создаёт figure с заданной шириной и высотой в см
03:  
04:  if nargin<2 % если дана только ширина, использует золотое сечение для высоты
05:      height = width * 2/(1+sqrt(5)); % высота=ширина/золотое сечение
06:  end
07:  
08:  set(0,'units','centimeters')
09:  scrsz=get(0,'screensize'); % размер экрана в см
10:  % положение и размер картинки
11:  position=[scrsz(3)/2-width/2 scrsz(4)/2-height/2 width height];
12:  h=figure;
13:  set(h,'units','centimeters')
14:  % устанавливаем размер
15:  set(h,'position',position)
16:  % Set screen and figure units back to pixels
17:  set(0,'units','pixel')
18:  set(h,'units','pixel')
Если использовать myfigure(10,8), то размер картинки будет 10см на 8см. Если задать только первый аргумент myfigure(10), то функция сама посчитает высоту исходя из золотого сечения. Файл myfigure.m находится в архиве с примерами.

Деталь первая: UserData matlabfrag

В принципе, необязательно пользоваться интерпретатором latex в Матлабе. Функция matlabfrag() смотрит на свойство UserData и, если оно имеет вид matlabfrag:XXX, вставляет XXX в качестве ЛаТеХ-текста. Например, код ниже делает в точности то же самое, как и разобранный выше пример

01:  %% example 2
02:  close all ; clear all; clc;
03:  %% По умолчанию, интерпретатор текста tex, а не latex,
04:  %  т.е. set(0,'DefaultTextInterpreter', 'tex'); указывать не обязательно
05:  
06:  %% Создаём картинку   
07:  fig=myfigure(10);
08:  %% Рисуем графики ...
09:  x=0:0.1:pi;
10:  y=sin(x); plot(x,y,'r'); hold on;
11:  z=cos(x); plot(x,z,'b');
12:  
13:  %% Подписи к осям
14:  xlabel('t, s', 'UserData','matlabfrag:$t$, s'); 
15:  ylabel('l, m', 'UserData','matlabfrag:$l$, m');
16:  %% Легенда
17:  l=mylegend({'sin x';'cos x'},...
18:             {'$\sin x$';$\cos x$});
19:  
20:  %% Дополнительный текст на графике
21:  text(0.5,-0.5,'integral here',...
22:       'UserData','matlabfrag:$\displaystyle \int\limits_0^{2\pi}\sin x\,dx = 0$');
23:  
24:  text(3,-0.5,'\gamma = \alpha/\zeta',...
25:      'UserData','matlabfrag:$\displaystyle \gamma=\frac{\alpha}{\zeta}$'); 
Недостаток этого способа в том, что придётся набирать больше текста. Кроме того, картинка, как её покажет Матлаб, вообще говоря, будет отличаться от той, которую вы увидите в ЛаТеХе.

Зато такой способ гораздо более гибок. Он позволяет вставлять в текст подписей команды, определённые в ЛаТеХ документе, о которых Матлаб ничего не знает. Например:

01:  text(0.5,-0.5,'integral here',...
02:   'UserData','matlabfrag:\myint see eq.(\ref{eq:1})');
использует команду \myint, а кроме того, ссылается на уравнение из основного текста.

Обратите внимание на то, как добавляется UserData к легенде: здесь для облегчения процесса использована функция mylegend(легенда,латех_вариант). Она принимает два аргумента, оба cell array. Первый — легенды для Матлаба, второй — для ЛаТеХа.

01:  function l=mylegend(lgnds,usrdta_in)
02:  % функция для создания легенд с ЛаТеХ-вариантами
03:  % пример вызова: l=mylegend({'sin(x)';'cos(x)'},{'$\sin x$';'$\cos x$'})
04:  % возвращает указатель на легенду
05:    l=legend(lgnds);
06:  
07:    if nargin>1 % если переданы UserData
08:       usrdta=lgnds;
09:       for i=1:min(length(usrdta),length(usrdta_in))
10:      usrdta{i} = usrdta_in{i};
11:       end
12:      
13:       lchild=get(l,'children');
14:       i_max=length(usrdta);
15:    
16:       for i=1:i_max
17:           i_child=3*i_max-(i-1)*3 ;
18:           set(lchild(i_child),'Userdata',sprintf('matlabfrag:%s',usrdta{i}));
19:       end
20:    end
21:  end

Дело в том, как Матлаб хранит текстовое содержимое легенд: если легенды две, то их текст будет сохранен в 6-м и 3-м элементах "детей легенды". Если легенды три, то в 9-м, 6-м и 3-м. И так далее.

Файл mylegend.m может быть найдена в архиве с примерами.

Деталь вторая: текстовые эффекты

Функция matlabfrag() настолько сообразительна, что автоматически подхватит эффекты, такие как вращение текста, центрирование, цвет, размер и т.п. Например, такой код

01:  %% example 3
02:  %% Text effects
03:  text(2.5,-0.5,{'Rotated';'text'},'Rotation',90);
04:  
05:  text(0.5,-0.5,{'Colored';'centered';'italic';'text'},...
06:      'Color','r',...
07:      'HorizontalAlignment','center',...
08:      'FontAngle','italic');
09:  
10:  text(1,-0.5,{'Big Text:';'16pt'},'FontSize',16)
даст эффект, очевидный из картинки ниже.

Обратите внимание, что для набора текста в несколько строк использованны cell arrays, вроде {'строка один';'строка два'}. Этот трюк работает не только для функции text(), но и для, например, подписей на осях:

01:  xlabel({'$t$, s'; 'time to goal'}); 
02:  ylabel({'$l$, m'; 'distance to goal'});

Деталь третья: поддержка русского языка

С русским тоже никаких проблем: просто, набираем подписи и текст на русском. Только не забываем в ЛаТеХ-документ вставить в преамбулу

01:  \usepackage[utf8]{inputenc}
02:  \usepackage[T2A]{fontenc}
03:  \usepackage[russian]{babel}

Результат:

Деталь четвертая: подписи к меткам на осях

Иногда хочется заполучить у меток на осях не числа типа 3.14, а что-то посимпатичнее, вроде числа "пи". Делается это просто:

01:  %% example 4
02:  ...
03:  %% подписи у меток, aka tick marks
04:  set(gca,'XLim',[0 pi],'XTick',[0 pi/2 pi],...
05:       'XTickLabel',{'$0$','$\pi/2$','$\pi$'});

Всё остальное — как прежде. Результат:

Деталь пятая: необязательные аргументы matlabfrag()

Функция matlabfrag(), помимо обязательного имени файла, принимает ещё несколько опций: handle, epspad, renderer и dpi. Например,

01:  matlabfrag('figs/myfig','handle',h,'epspad',[10 10 10 10])
сохранит в файлы figs/myfig.tex и figs/myfig.eps не активную в данный момент картинку, а ту, на которую указывает h; кроме того, добавит по 10px со всех сторон. Про renderer и dpi можно почитать в документации.

Деталь шестая: необязательные аргументы \psfragfig{}

Прежде всего, поведением pstool можно управлять задав опции при загрузке пакета. Одну из них, которая принудительно перекодирует все картинки, мы уже обсуждали: process=all.

Иногда метки, выдающиеся далеко за пределы графика, оказываются "обрезанными". Предотвратить такое поведение можно задав опцию crop=pdfcrop.

Если возникают непонятные проблемы со вставкой картинок, можно задать опцию mode=errorstop, чтобы процесс комиляции останавливался при возникновении ошибки.

На этом список опций не исчерпывается: за подробностями всегда можно обратиться к документации.

Все эти опции можно задавать не только при загрузке пакета, но и после, а именно:

  1. с помощью команды \pstoolsetup{}; опция будет применена с момента её объявления
  2. в качестве необязательных аргументов к \psfragfig{}; при этом опция будет применена только к текущей картинке; например
    01:  \psfragfig[crop=pdfcrop]{figs/myfig}
    

Деталь седьмая: лезем в код matlabfrag()

Одним (пожалуй, единственным) из недостатков matlabfrag() является то, что всегда надо указывать явно размер шрифта (посмотрите на строки 6 и 7 самого первого примера, см. также ниже), чтобы он совпадал с размером шрифта в ЛаТеХе. Тогда как гораздо более удобным, по мнению автора этих строк, поведением было бы следующее: (1) если размер шрифта не указан, то просто используется установленный ЛаТеХом; (2) если же мы указываем в Матлабе размер шрифта явно, через FontSize, то и в ЛаТеХе надо этот размер насильно применить.

К сожалению, в "ванильной" версии matlabfrag() такая возможность отсутствует. Однако в версии, которую можно найти в файле с примерами к этому посту, я взял на себя смелость и изменил код этой функции соответствующим образом. Т.е., если вы используете эту "хакнутую" версию, то указывать

01:  %  Размер шрифта такой же как в ЛаТеХ-документе
02:  set(0,'DefaultAxesFontSize',12);
03:  set(0,'DefaultTextFontSize',12);
не нужно.

Деталь восьмая и последняя: хочу другой шрифт

До настоящего момента мы стремились использовать на графиках шрифт того же начертания, что и в основном тексте. Однако "в узких кругах существует мнение", что хотя в основном тексте лучше использовать шрифт с насечками (serif font), на рисунках надо отдать предпочтение шрифту без насечек (san serif font). Выражаясь языком понятным пользователям Ворда, "в тексте: Times New Roman, на рисунках: Arial". Якобы, такое разделение привлекает внимание к рисункам и выделяет их в массе текста.

Хотя эстетическая ценность такого решения весьма сомнительна, в "улучшенной" версии matlabfrag.m реализована такая возможность. В преамбулу ЛаТеХ-документа помещаем

01:  \usepackage{sansmath}
02:  \providecommand{\MATLABFont}{\sffamily\sansmath}
и наслаждаемся результатами. Заметьте, что сами рисунки для этого "перерисовывать" не надо. Результат с и без \MATLABFont приведён ниже. Обратите внимание, что греческие буквы недоступны в начертании "без насечек".


В принципе, выше были рассмотрены все основные шаги и опции для сохранения графиков и их импорта в ЛаТеХ. Интересующиеся более подробно деталями процесса могут ознакомиться с документацией к matlabfrag и pstool.

Заключение и выводы

Итак, подведём итоги. Описанный метод позволяет при сравнительно малых затратах времени добиться более чем удовлетворительных результатов: векторных графиков с надписями, выполненными ЛаТеХом. Это позволяет не только добиться гармоничного соответствия между шрифтами на рисунке и в тексте, но и использовать на рисунке формулы и ссылки на уравнения, другие рисунки и т.д.

В случае Матлаба, необходимая функциональность доступна через matlabfrag(). Использование пакета pstool позволяет существенно упростить процесс импорта сгенерированных таким образом eps-файлов в pdfLaTeX.

Хотя мы рассмотрели данный рецепт на примере Матлаба, аналогичные методы могут быть использованы и с другими программами. Например, MathPSfrag является аналогом mathlabfrag() для мат-пакета Mathematica. Для Gnuplot использование set terminal latex и экспорт через pstool также позволяют добиться сходного результата.

Здесь мы рассмотрели экспорт графиков функций из MATLAB, однако схожий трюк применим и к рисункам и схемам созданным, например, в Inkscape. Об этом в одном из следующих постов.

Все примеры из данного поста доступны для скачивания по адресу tinyurl.com/amorua-matlabfrag.

Зеркала на случай сбоязеркало1, зеркало2

Читать далее

Отложенная отправка электропочты: scheduled email



10 коммент.
Сегодня первое апреля, и автору хотелось немного отдохнуть.

Чего мне не хватает в интерфейсе Gmail, на фоне всех этих бесполезных свистулек и бубенчиков, так это отправки электропочты по расписанию. Например, у Васи Пупкина день рождения в субботу, а я в субботу колесю на своём Бентли велосипеде по всяким Флайшиттаунам. Хорошо бы запрячь Gmail отправить письмо в заданный день - сделали же они Scheduled Posts в Blogger.

После долгих блужданий нашёлся небольшой сайт LetterMeLater, который делает как раз это: отправляем на него письмо, в нём указываем срок, и всё. Оно приходит в точно назначенный день и час!

Читать далее