Журнал LinuxFormat - перейти на главную

LXF79:MetaPost

Материал из Linuxformat
(Различия между версиями)
Перейти к: навигация, поиск
(Новая: ''Даже жизнь можно отобразить в виде графика функции от времени. '''Евгений Балдин''' расскажет, как выра...)
 
м ({{Цикл/MetaPost}})
 
(не показаны 3 промежуточные версии 3 участников)
Строка 1: Строка 1:
 +
{{Цикл/MetaPost}}
 
''Даже жизнь можно отобразить в виде графика функции от времени. '''Евгений Балдин''' расскажет, как выразить это на языке Metapost.''
 
''Даже жизнь можно отобразить в виде графика функции от времени. '''Евгений Балдин''' расскажет, как выразить это на языке Metapost.''
  
Строка 12: Строка 13:
 
* создать сетку и поставить метки на осях,
 
* создать сетку и поставить метки на осях,
 
* изобразить функцию.
 
* изобразить функцию.
 +
 +
[[Изображение:Img 79 109 1.jpg|thumb|Иллюстрация для объяснения понятия дифференцирования]]
  
 
В этом смысле кодирование графика ничем не отличается от кодирования рисунка – нужно лишь уметь рисовать стрелки и линии. Однако это годится только для простых графиков. Графики в MetaPost Для серьёзной работы с графиками в MetaPost есть довольно продвинутый пакет graph.mp. Этот пакет написан «отцом» MetaPost Джоном Хобби, и к нему прилагается подробная документация, которую можно найти в стандартной поставке LaTeX в виде файла mpgraph.pdf. Если вы планируете воспользоваться этим пакетом, то прежде изучите этот текст.
 
В этом смысле кодирование графика ничем не отличается от кодирования рисунка – нужно лишь уметь рисовать стрелки и линии. Однако это годится только для простых графиков. Графики в MetaPost Для серьёзной работы с графиками в MetaPost есть довольно продвинутый пакет graph.mp. Этот пакет написан «отцом» MetaPost Джоном Хобби, и к нему прилагается подробная документация, которую можно найти в стандартной поставке LaTeX в виде файла mpgraph.pdf. Если вы планируете воспользоваться этим пакетом, то прежде изучите этот текст.
 
  %Файл graphics.mp
 
  %Файл graphics.mp
 
  input graph;
 
  input graph;
  %График переменной скорости - тема “дифференцирование”
+
  %График переменной скорости - тема "дифференцирование"
 
  beginfig(2) ;
 
  beginfig(2) ;
 
   numeric u;
 
   numeric u;
Строка 71: Строка 74:
 
Функция «отрисовывается» точно так же, как любая из кривых: создаётся путь, который затем выводится с помощью команды gdraw.
 
Функция «отрисовывается» точно так же, как любая из кривых: создаётся путь, который затем выводится с помощью команды gdraw.
  
Для фиксации диапазона графика используется команда: setrange(“нижний левый угол”,”верхний правый угол”);
+
Для фиксации диапазона графика используется команда: setrange("нижний левый угол","верхний правый угол");
  
 
При вызове этой инструкции все последующие функции работают в указанном диапазоне. Таким образом, используя одно и то же пространство, можно совместить несколько графиков, имеющих различный диапазон аргументов и функций. Шкалу графика можно сделать логарифмической с помощью инструкции setcoord:
 
При вызове этой инструкции все последующие функции работают в указанном диапазоне. Таким образом, используя одно и то же пространство, можно совместить несколько графиков, имеющих различный диапазон аргументов и функций. Шкалу графика можно сделать логарифмической с помощью инструкции setcoord:
Строка 83: Строка 86:
  
 
=== Работа с файлами данных ===
 
=== Работа с файлами данных ===
 +
 +
[[Изображение:Img 79 110 1.jpg|thumb|Число постов на linux.org.ru]]
  
 
С помощью команды gdraw можно читать данные из файла. Если в качестве аргумента передаётся текстовая строка, то gdraw предполагает, что это имя файла.
 
С помощью команды gdraw можно читать данные из файла. Если в качестве аргумента передаётся текстовая строка, то gdraw предполагает, что это имя файла.
Строка 90: Строка 95:
 
   draw begingraph(150u,100u);
 
   draw begingraph(150u,100u);
 
   pickup pencircle scaled 0.2u;
 
   pickup pencircle scaled 0.2u;
   gdraw(“lor-1998.dat”) plot btex \(\circ\) etex;
+
   gdraw("lor-1998.dat") plot btex \(\circ\) etex;
   gdraw(“lor-1999.dat”) plot btex \(\circ\) etex;
+
   gdraw("lor-1999.dat") plot btex \(\circ\) etex;
   gdraw(“lor-2000.dat”);
+
   gdraw("lor-2000.dat");
   gdraw(“lor-2001.dat”);
+
   gdraw("lor-2001.dat");
   gdraw(“lor-2002.dat”);
+
   gdraw("lor-2002.dat");
   gdraw(“lor-2003.dat”) plot btex \(\bullet\) etex;
+
   gdraw("lor-2003.dat") plot btex \(\bullet\) etex;
   gdraw(“lor-2004.dat”);
+
   gdraw("lor-2004.dat");
   gdraw(“lor-2005.dat”);
+
   gdraw("lor-2005.dat");
   gdraw(“lor-2006.dat”);
+
   gdraw("lor-2006.dat");
 
   gdraw (0,100)--(12,100) withpen pencircle scaled 1u dashed evenly scaled 1u withcolor blue;
 
   gdraw (0,100)--(12,100) withpen pencircle scaled 1u dashed evenly scaled 1u withcolor blue;
 
   glabel.top(btex 2000--2002 etex,(9,100)) withcolor blue;
 
   glabel.top(btex 2000--2002 etex,(9,100)) withcolor blue;
Строка 127: Строка 132:
 
   u := 0.8mm;
 
   u := 0.8mm;
 
  draw begingraph(150u,100u);
 
  draw begingraph(150u,100u);
  gdraw “mendeleev.dat” dashed evenly scaled 1u withcolor 0.5white ;
+
  gdraw "mendeleev.dat" dashed evenly scaled 1u withcolor 0.5white ;
  gdata(“mendeleev.dat”, s, glabel(s3,(scantokens s1,scantokens s2));
+
  gdata("mendeleev.dat", s, glabel(s3,(scantokens s1,scantokens s2));
 
   )
 
   )
 
  glabel.lft(btex Дефект массы (МэВ) etex rotated 90,OUT);
 
  glabel.lft(btex Дефект массы (МэВ) etex rotated 90,OUT);
Строка 134: Строка 139:
 
  endgraph;
 
  endgraph;
 
  endfig;
 
  endfig;
то получится простенькая картинка:
+
то получится простенькая картинка.
[[Изображение:Img_79_111_1.jpg]]
+
[[Изображение:Img 79 111 1.jpg|thumb|Дефект массы химических элементов от порядкового номера в периодической таблице Меделеева. Приведены элементы от водорода до железа.]]
 
Переменная s объявляется массивом, в который считывается строка. В качестве разделителя выступает пробел. Запись s1 соответствует s[1] – первому элементу массива. Макрос scantokens «встраивает» значение аргумента в код. В данном случае происходит перевод строки в число. В качестве «действия» в команде gdata может быть набор из нескольких команд.
 
Переменная s объявляется массивом, в который считывается строка. В качестве разделителя выступает пробел. Запись s1 соответствует s[1] – первому элементу массива. Макрос scantokens «встраивает» значение аргумента в код. В данном случае происходит перевод строки в число. В качестве «действия» в команде gdata может быть набор из нескольких команд.
  
Строка 165: Строка 170:
 
  enddef;
 
  enddef;
 
Распределение, представленное на картинке, похоже на убывающую экспоненту. Вот так рисовались «пятёрки»:
 
Распределение, представленное на картинке, похоже на убывающую экспоненту. Вот так рисовались «пятёрки»:
 +
[[Изображение:Img 79 111 2.jpg|thumb|Распределение по баллам, полученным на Открытой олимпиаде по физике в НГУ в 2004 году.]]
 
  %Файл graphics.mp
 
  %Файл graphics.mp
 
  %Оценки
 
  %Оценки
Строка 180: Строка 186:
  
 
Пакет piechartmp.mp относительно молод. Замечательная, можно сказать красочная, документация поставляется в виде файла piechartmp.pdf и примеров.
 
Пакет piechartmp.mp относительно молод. Замечательная, можно сказать красочная, документация поставляется в виде файла piechartmp.pdf и примеров.
 +
 +
[[Изображение:Img 79 111 3.jpg|thumb|Распределение оценок.]]
  
 
Как обычно, за русским языком надо приглядывать. По умолчанию пакет работает только с латиницей.
 
Как обычно, за русским языком надо приглядывать. По умолчанию пакет работает только с латиницей.
Строка 185: Строка 193:
 
  input piechartmp;
 
  input piechartmp;
 
  %Круговые гистограммы
 
  %Круговые гистограммы
  %Открытая Олимпиада “ФФ-51”
+
  %Открытая Олимпиада "ФФ-51"
 
  beginfig(1) ;
 
  beginfig(1) ;
 
   numeric u; u:=1mm;
 
   numeric u; u:=1mm;
 
  %чтобы был русский
 
  %чтобы был русский
  SetupText(1, \input{preheader-base}, \begin{document})
+
  SetupText(1, "\input{preheader-base}", "\begin{document}")
 
  label(btex Открытая олимпиада НГУ-2005 etex,(5u,25u));
 
  label(btex Открытая олимпиада НГУ-2005 etex,(5u,25u));
 
  label(btex распределение оценок ФФ-51 etex,(5u,20u));
 
  label(btex распределение оценок ФФ-51 etex,(5u,20u));
 
  %Чтобы отображался процент
 
  %Чтобы отображался процент
  SetupPercent(this, \%);
+
  SetupPercent(this, " \%");
 
  %Опеределение сегментов
 
  %Опеределение сегментов
  Segment( 15,\small два”, auto);
+
  Segment( 15,"\small два", auto);
  Segment( 24,”три”, auto);
+
  Segment( 24,"три", auto);
  Segment( 16,\large четыре”, auto);
+
  Segment( 16,"\large четыре", auto);
  Segment( 16,\huge пять”, red );
+
  Segment( 16,"\huge пять", red );
 
  %Создание круговой гистограммы
 
  %Создание круговой гистограммы
 
  PieChart(30u, 0.2, 65, 0, 0);
 
  PieChart(30u, 0.2, 65, 0, 0);
Строка 211: Строка 219:
 
* Нарисовать гистограмму. В качестве параметров команде PieChart передаётся размер, высота диаграммы, угол, под которым мы на неё смотрим (трёхмерность), угол поворота вокруг центральной оси и «смещение» сегментов относительно центра.
 
* Нарисовать гистограмму. В качестве параметров команде PieChart передаётся размер, высота диаграммы, угол, под которым мы на неё смотрим (трёхмерность), угол поворота вокруг центральной оси и «смещение» сегментов относительно центра.
 
* Расставить метки. В момент создания каждому сегменту присваивается порядковый номер. Отсчет начинается с единицы. Все изменения в круговой диаграмме делаются глобально. Пакет написан так, чтобы в одном mp-файле было удобно работать ровно с одной диаграммой. Если при описании диаграммы внутри окружения beginfig вы уже что-то определили, то нет необходимости повторять это в последующих окружениях. Этот режим удобен, если нужно создать несколько модификаций одной диаграммы, например, для создания «оверлеев» в презентации. Минусом такого подхода является то, что если в этом же mp-файле хочется создать ещё одну гистограмму, то уже определённые сегменты необходимо спрятать.
 
* Расставить метки. В момент создания каждому сегменту присваивается порядковый номер. Отсчет начинается с единицы. Все изменения в круговой диаграмме делаются глобально. Пакет написан так, чтобы в одном mp-файле было удобно работать ровно с одной диаграммой. Если при описании диаграммы внутри окружения beginfig вы уже что-то определили, то нет необходимости повторять это в последующих окружениях. Этот режим удобен, если нужно создать несколько модификаций одной диаграммы, например, для создания «оверлеев» в презентации. Минусом такого подхода является то, что если в этом же mp-файле хочется создать ещё одну гистограмму, то уже определённые сегменты необходимо спрятать.
 +
[[Изображение:Img 79 112 1.jpg|thumb|Распределение «вещества» в современной вселенной.]]
 +
 
  %Круговые гистограммы
 
  %Круговые гистограммы
 
  %распределение вещества во вселенной
 
  %распределение вещества во вселенной
Строка 221: Строка 231:
 
  SegmentState(4,hidden,this);
 
  SegmentState(4,hidden,this);
 
  %Опеределение новых сегментов
 
  %Опеределение новых сегментов
  Segment( 65,\Large \bf тёмная энергия”,green,\LARGE 65\%--70\%);
+
  Segment( 65,"\Large \bf тёмная энергия",green,"\LARGE 65\%--70\%");
  Segment( 25,\Large \bf тёмная материя”, (1,0,1),\LARGE 25\%);
+
  Segment( 25,"\Large \bf тёмная материя", (1,0,1),"\LARGE 25\%");
  Segment( 0.5,”звёзды”, (1,1,0),\LARGE 0.5\%);
+
  Segment( 0.5,"звёзды", (1,1,0),"\LARGE 0.5\%");
  Segment( 5,”обычное вещество”, red,\LARGE 5\%);
+
  Segment( 5,"обычное вещество", red,"\LARGE 5\%");
  Segment( 1,”нейтрино”, black,\LARGE 0.3\%--3\%);
+
  Segment( 1,"нейтрино", black,"\LARGE 0.3\%--3\%");
 
  %Выдвигаем сегменты из диаграммы
 
  %Выдвигаем сегменты из диаграммы
 
  SegmentState(7,this,0.7);
 
  SegmentState(7,this,0.7);
Строка 304: Строка 314:
  
 
=== gnuplot ===
 
=== gnuplot ===
 +
 +
[[Изображение:Img 79 113 1.jpg|thumb|Интегральная светимость от времени. Данные за полтора года (примерно 130 тысяч точек) обработаны с помощью программы gnuplot.]]
  
 
В случае отображения больших объёмов данных лучше использовать gnuplot. Чтобы gnuplot работал с MetaPost, необходимо определить правильное устройство вывода. Для этого в gnuplot следует передать команду:
 
В случае отображения больших объёмов данных лучше использовать gnuplot. Чтобы gnuplot работал с MetaPost, необходимо определить правильное устройство вывода. Для этого в gnuplot следует передать команду:

Текущая версия на 22:14, 16 мая 2008

Даже жизнь можно отобразить в виде графика функции от времени. Евгений Балдин расскажет, как выразить это на языке Metapost.

Содержание


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

По-хорошему, графики следует создавать в специализированных приложениях. Автоматизация этого процесса достаточно специфична, чтобы реализовывать его с помощью программ, не предназначенных только для этого. Если вам нужны двумерные графики, то никто не справится с этим лучше чем gnuplot. Если вас интересуют гистограммы, то это работа для пакетов анализа paw/cernlib или root. Но если вам хочется разукрасить график, то MetaPost будет для этого очень кстати.

Ничего не мешает нарисовать график самостоятельно. Всё, что для этого нужно:

  • знать диапазон функции и её аргумента,
  • нарисовать оси координат,
  • создать сетку и поставить метки на осях,
  • изобразить функцию.
(thumbnail)
Иллюстрация для объяснения понятия дифференцирования

В этом смысле кодирование графика ничем не отличается от кодирования рисунка – нужно лишь уметь рисовать стрелки и линии. Однако это годится только для простых графиков. Графики в MetaPost Для серьёзной работы с графиками в MetaPost есть довольно продвинутый пакет graph.mp. Этот пакет написан «отцом» MetaPost Джоном Хобби, и к нему прилагается подробная документация, которую можно найти в стандартной поставке LaTeX в виде файла mpgraph.pdf. Если вы планируете воспользоваться этим пакетом, то прежде изучите этот текст.

%Файл graphics.mp
input graph;
%График переменной скорости - тема "дифференцирование"
beginfig(2) ;
 numeric u;
 u = 0.6mm;
 %начало графика
 draw begingraph(12cm,3cm);
  path r;
  numeric e,pi,A,sigma,n,scale,mean,y[],x[];
  e:=2.718;pi:=3.14159;A=50;
  sigma=1.4;n:=100;scale=10;mean=5;
  %создание функции - она использовалась не один раз
  for j:=0 upto n:
   if (j=0):
              x[0]=0;y[0]=0;
   else:
              x[j]:=scale*j/n;
              y[j]:=y[j-1]+A*(e**(-(((scale*j/n-mean)/(1.41*sigma))**2)))*
              (x[j]-x[j-1])/(sqrt(2*pi)*sigma);
   fi
  endfor;
  %здесь нужна функция из отрезков, поэтому step 6
  r:=(0,0)for j:=0 step 6 until (n-1):
    --((2,0)+(x[j],y[j])) endfor ..(12,50)--(15,50);
  %отрисовка функции
  gdraw r withpen pencircle scaled 0.8u;
  %сетка
  autogrid(grid.bot,grid.lft) withcolor .5white;
  %дополнительные метки на оси абсцисс
  otick.bot(btex 2\,\text{с} etex,2);
  otick.bot(btex 12\,\text{с} etex,12);
  %текст и стрелка за пределами графика
  gdrawdblarrow (2,-20)--(12,-20)
           withpen pencircle scaled 0.5u;
  glabel.top(btex \(T=10\,\text{с}\) etex,(7.5,-20));
  gdrawdblarrow (13.5,0)--(13.5,50)
           withpen pencircle scaled 0.5u;
  %текстовые метки внутри графика
  glabel.lft(btex \(S=50\,\text{м}\) etex
         rotated 90, 1/2[(13.5,0),(13.5,50)]);
  glabel.rt(btex \(v(t)=\frac{dx(t)}{dt}\) etex
                scaled 1.3,(0,25));
  glabel(btex \(dx\) etex,(11.1,20)) ;
  glabel(btex \(dt\) etex,(10,9)) ;
  %подписи к осям
  glabel.rt(btex Время (с) etex,(13,-20)) ;
  glabel.lft(btex Расстояние (м) etex rotated 90,OUT) shifted (0cm,0.5cm);
 endgraph;
endfig ;

В graph.mp определено специальное окружение. Между begingraph и endgraph действует своя система координат. Она привязана не к геометрическим размерам картинки, а к диапазону осей графика. То есть точка (0,0) соответствует точке пересечения оси абсцисс и оси ординат графика. Размер создаваемого графика указывается сразу после begingraph.

Вместо стандартных команд draw, fill, label и dotlabel используются gdraw, gfill, glabel и gdotlabel, соответственно. Новые команды работают с учётом координат графика. С их помощью можно построить функцию именно по точкам, не заботясь о сдвигах и тому подобном. Для подписи осей существует специальная точка OUT, которая в зависимости от суффикса команды glabel выносит текст за пределы основной сетки.

Функция «отрисовывается» точно так же, как любая из кривых: создаётся путь, который затем выводится с помощью команды gdraw.

Для фиксации диапазона графика используется команда: setrange("нижний левый угол","верхний правый угол");

При вызове этой инструкции все последующие функции работают в указанном диапазоне. Таким образом, используя одно и то же пространство, можно совместить несколько графиков, имеющих различный диапазон аргументов и функций. Шкалу графика можно сделать логарифмической с помощью инструкции setcoord:

%x- линейная шкала, y - логарифмическая
setcoord(linear,log);

Для создания сетки и меток используется команда autogrid:

%сетка по нижней и левой осям
autogrid(grid.bot,grid.lft) withcolor .5white;
%внешние метки по нижней оси и внутренние метки по правой оси
autogrid(otick.bot,itick.rt);

[править] Работа с файлами данных

(thumbnail)
Число постов на linux.org.ru

С помощью команды gdraw можно читать данные из файла. Если в качестве аргумента передаётся текстовая строка, то gdraw предполагает, что это имя файла.

%Файл graphics.mp
%Число постов на LOR от месяца года  beginfig(4) ;
 u := 0.4mm;
 draw begingraph(150u,100u);
  pickup pencircle scaled 0.2u;
  gdraw("lor-1998.dat") plot btex \(\circ\) etex;
  gdraw("lor-1999.dat") plot btex \(\circ\) etex;
  gdraw("lor-2000.dat");
  gdraw("lor-2001.dat");
  gdraw("lor-2002.dat");
  gdraw("lor-2003.dat") plot btex \(\bullet\) etex;
  gdraw("lor-2004.dat");
  gdraw("lor-2005.dat");
  gdraw("lor-2006.dat");
  gdraw (0,100)--(12,100) withpen pencircle scaled 1u dashed evenly scaled 1u withcolor blue;
  glabel.top(btex 2000--2002 etex,(9,100)) withcolor blue;
  gdraw (0,200)--(12,200) withpen pencircle scaled 1u dashed evenly scaled 1u withcolor red;
  glabel.top(btex 2004--2006 etex,(9,200)) withcolor red;
  glabel.lft(btex число «постов» etex rotated 90,OUT);
  glabel.bot(btex номер месяца в году etex,OUT);
 endgraph;
endfig;

Как и команда draw, gdraw «понимает» инструкции withpen (какое перо использовать), withcolor (цвет линии) и dashed (использовать пунктир). Дополнительно gdraw воспринимает команду plot {picture}. Указанная в инструкции plot картинка выбирается в качестве маркера. На рисунке чёрными маркерами отмечен 2003 год – год, когда произошло удвоение ежемесячного числа новостных постов на LOR (www.linux.org.ru), а белыми маркерами – первый год существования этого ресурса.

По умолчанию предполагается, что входной файл представляет из себя два столбца цифр, разделённых пробелами. Пример файла lor-2006.dat (данные взяты с сайта www.linux.org.ru):

1 175
2 181
3 184

Если данные имеют более сложное представление, чем в упомянутом выше файле, то используется команда gdata. gdata («имя файла», переменная куда считываются данные, действие);

Если на текстовый файл вида:

1 7.289 H
2 2.425 He
--вырезано--
26 -57.710 Mn
27 -60.604 Fe

воздействовать с помощью следующего кода:

%Файл graphics.mp
%дефект масс
beginfig(5) ;
 u := 0.8mm;
draw begingraph(150u,100u);
gdraw "mendeleev.dat" dashed evenly scaled 1u withcolor 0.5white ;
gdata("mendeleev.dat", s, glabel(s3,(scantokens s1,scantokens s2));
 )
glabel.lft(btex Дефект массы (МэВ) etex rotated 90,OUT);
glabel.bot(btex Порядковый номер элемента в таблице etex,OUT);
endgraph;
endfig;

то получится простенькая картинка.

(thumbnail)
Дефект массы химических элементов от порядкового номера в периодической таблице Меделеева. Приведены элементы от водорода до железа.

Переменная s объявляется массивом, в который считывается строка. В качестве разделителя выступает пробел. Запись s1 соответствует s[1] – первому элементу массива. Макрос scantokens «встраивает» значение аргумента в код. В данном случае происходит перевод строки в число. В качестве «действия» в команде gdata может быть набор из нескольких команд.

[править] Гистограммы в MetaPost

Если вы хотите нарисовать гистограмму, то можно воспользоваться следующими макросами:

%Файл graphics.mp
%создает профиль гистограммы из пути
def histpath(expr pairs) =
for i=0 upto length pairs:
 if (i>0):--else:fi((point i of pairs)-
  ((xpart(point 1 of pairs)-
   xpart(point 0 of pairs))/2,0))--
 ((point i of pairs)+
  ((xpart(point 1 of pairs)-
   xpart(point 0 of pairs))/2,0))
endfor
enddef;
%создает замкнутый профиль гистограммы
%для закрашивания
def histpathcycle(expr pairs) =
((xpart(point 0 of pairs),0)-
 ((xpart(point 1 of pairs)-
  xpart(point 0 of pairs))/2,0))
--histpath(pairs)--
((xpart(point infinity of pairs),0)+
 ((xpart(point 1 of pairs)-
  xpart(point 0 of pairs))/2,0))--cycle
enddef;

Распределение, представленное на картинке, похоже на убывающую экспоненту. Вот так рисовались «пятёрки»:

(thumbnail)
Распределение по баллам, полученным на Открытой олимпиаде по физике в НГУ в 2004 году.
%Файл graphics.mp
%Оценки
path five;
five:=(21,2)--(22,5)--(23,1)--(24,0)--(25,1)--(26,1)--(27,1)--(28,3)--(29,0)--(30,0)--(31,0);
%Заполняем гистограмму
gfill histpathcycle(five) withcolor 0.6white;

Для закрашивания контура применяется инструкция gfill – аналог команды fill.

Данные по оценкам получались в результате обработки текстовых файлов со статистикой с помощью простого скрипта на Perl. Время, которое потребовалось на автоматизацию, составило примерно один человеко-день, что многократно меньше времени написания полного отчёта, куда вошли подобные гистограммы, и оформления всех условий и решений Открытой олимпиады и последовавших за ней летних вступительных экзаменов.

Создание своих макросов на MetaPost является стандартным действием. META не страдает избыточностью и поощряет «доводку» окружения под ваши нужды.

[править] Круговые диаграммы

Пакет piechartmp.mp относительно молод. Замечательная, можно сказать красочная, документация поставляется в виде файла piechartmp.pdf и примеров.

(thumbnail)
Распределение оценок.

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

%Файл pie.mp
input piechartmp;
%Круговые гистограммы
%Открытая Олимпиада "ФФ-51"
beginfig(1) ;
 numeric u; u:=1mm;
%чтобы был русский
SetupText(1, "\input{preheader-base}", "\begin{document}")
label(btex Открытая олимпиада НГУ-2005 etex,(5u,25u));
label(btex распределение оценок ФФ-51 etex,(5u,20u));
%Чтобы отображался процент
SetupPercent(this, " \%");
%Опеределение сегментов
Segment( 15,"\small два", auto);
Segment( 24,"три", auto);
Segment( 16,"\large четыре", auto);
Segment( 16,"\huge пять", red );
%Создание круговой гистограммы
PieChart(30u, 0.2, 65, 0, 0);
%метки
Label(0)(percent)(inwards,0) withcolor white;
Label.auto(0)(name)(outwards,0);
endfig;

Алгоритм создания круговой или секторной диаграммы следующий:

  • Если вы хотите воспользоваться автоматической системой размещения меток, то с помощью команды SetupText следует настроить вывод текста. В файле preheader-base.tex должна быть минимальная шапка для документа LaTeX. Если вы хотите использовать русский язык, то там обязательно должны быть строки вида \usepackage[T2A]{fontenc} и \usepackage[koi8-r]{inputenc}. Вместо koi8-r можно поставить свою кодировку.
  • С помощью команды Segment следует определить сегменты. В качестве аргументов команде передаётся число (измеряемая величина), текстовая метка и цвет сегмента (можно указать значение по умолчанию – auto). Можно также ввести четвёртый необязательный строковый параметр, который заменяет измеряемую величину при создании меток. Это решает проблему ограничения на диапазон чисел в MetaPost.
  • Нарисовать гистограмму. В качестве параметров команде PieChart передаётся размер, высота диаграммы, угол, под которым мы на неё смотрим (трёхмерность), угол поворота вокруг центральной оси и «смещение» сегментов относительно центра.
  • Расставить метки. В момент создания каждому сегменту присваивается порядковый номер. Отсчет начинается с единицы. Все изменения в круговой диаграмме делаются глобально. Пакет написан так, чтобы в одном mp-файле было удобно работать ровно с одной диаграммой. Если при описании диаграммы внутри окружения beginfig вы уже что-то определили, то нет необходимости повторять это в последующих окружениях. Этот режим удобен, если нужно создать несколько модификаций одной диаграммы, например, для создания «оверлеев» в презентации. Минусом такого подхода является то, что если в этом же mp-файле хочется создать ещё одну гистограмму, то уже определённые сегменты необходимо спрятать.
(thumbnail)
Распределение «вещества» в современной вселенной.
%Круговые гистограммы
%распределение вещества во вселенной
beginfig(2) ;
numeric u; u:=1mm;
%прячем определённые ранее сегменты
SegmentState(1,hidden,this);
SegmentState(2,hidden,this);
SegmentState(3,hidden,this);
SegmentState(4,hidden,this);
%Опеределение новых сегментов
Segment( 65,"\Large \bf тёмная энергия",green,"\LARGE 65\%--70\%");
Segment( 25,"\Large \bf тёмная материя", (1,0,1),"\LARGE 25\%");
Segment( 0.5,"звёзды", (1,1,0),"\LARGE 0.5\%");
Segment( 5,"обычное вещество", red,"\LARGE 5\%");
Segment( 1,"нейтрино", black,"\LARGE 0.3\%--3\%");
%Выдвигаем сегменты из диаграммы
SegmentState(7,this,0.7);
SegmentState(9,this,0.7);
SegmentState(8,this,0.7);
%Создание круговой гистограммы
PieChart(30u, 0.3, 30, 340, 0);
%метки
Label.auto(0)(name)(outwards,0) ;
Label.auto(5)(value)(inwards,0) shifted (7u,-7u) withcolor white;
Label.auto(6)(value)(inwards,0) shifted (0u,5u) withcolor white;
Label.auto(7)(value)(inwards,(0u,-15u)) withcolor (1,1,0);
Label.auto(8)(value)(inwards,(25u,10u)) withcolor red;
Label.auto(9)(value)(inwards,(20u,20u)) withcolor black;
endfig;

Состояние каждого из сегментов можно задавать с помощью команды SegmentState1.

Состояние сегмента может быть:

  • normal – сегмент становится видимым,
  • invisible – сегмент не рисуется при создании круговой диаграммы (в диаграмме остаётся пустое место),
  • hidden – при создании диаграммы этот сегмент игнорируется.

Радиальный сдвиг сегмента указывается в процентах, где 1 – это 100%, то есть сегмент полностью «выдвинут».

Для установки меток используется команда Label2:

Label понимает те же суффиксы, что и обычная команда label, плюс auto. При установке суффикса auto Label пытается сама угадать, где лучше поставить метку.

В качестве порядкового номера сегмента можно передать 0. В этом случае команда Label применяется ко всем видимым сегментам. Label может принимать в качестве аргумента список порядковых номеров сегментов, разделённый запятыми (например: 5, 7, 9).

Метка может быть простой текстовой строкой или одним из стандартных значений:

  • value – измеряемая величина, которая приписывается сегменту при его создании,
  • percent – процент занимаемой площади,
  • name – имя сегмента, которое приписывается ему при его создании.

Базовая точка представляется в виде пары чисел (x,y), где x – расстояние от вершины сегмента (0 – это вершина, 1 – это противоположный от вершины край), а y – эквивалент полярного угла (0 – край сегмента по часовой стрелки, 1 – край сегмента против часовой стрелки). В пакете определены константы inwards=(0.7,0.7) и outwards=(1.1,0.5). Сдвиг же представлен в терминах всего графика (например, (1cm,0) означает сдвиг на 1 сантиметр вправо).

При желании тип заливки и порядок цветов по умолчанию можно определять самостоятельно. Подробнее об этом рассказано в документации к пакету piechartmp.pdf.

[править] LaTeX рисует с помощью MetaPost

Для рисования графиков можно воспользоваться и возможностями самого LaTeX. Например, с этой обязанностью прекрасно справляется стандартный пакет mfpic. Для «отрисовки» функций с помощью этого пакета достаточно задать саму функцию, а не рисовать по точкам:

%файл graphics-mfpic.tex
%Пример от Сергея В. Знаменского
\documentclass{article}
\usepackage[koi8-r]{inputenc}
\usepackage[russian]{babel}
\usepackage[MetaPost]{mfpic}
%указываем mp-файл куда будет «складываться» код mfpic
\opengraphsfile{graph-mfp}
\begin{document}
%не печатать номер страницы
\pagestyle{empty}
%начинаем создание графика
\mfpic[1][57.2]{-100}{300}{-1.2}{1.2}
%оси координат
\axes
\xmarks{-90,90,180,270}
\ymarks{-1,1}
%рисуем синус точками
\dotted\function{-90,270,4.5}{sind(x)}
%рисуем косинус пунктиром
\dashed\function{-90,270,4.5}{cosd(x)}
%рисуем тангенс сплошной линией
\function{-50,50,10}{tand(x)}
\function{130,230,10}{tand(x)}
%заканчиваем создание графика
\endmfpic
%закрываем mp-файл
\closegraphsfile
\end{document}

Для получения картинки необходимо выполнить следующие действия:

> LaTeX graphics-mfpic.tex
> mpost graph-mfp.mp
> LaTeX graphics-mfpic.tex
> dvips -E graphics-mfpic.dvi -o graphics-mfpic.eps

При компиляции файла graphics-mfpic.tex создаётся graph-mfp.mp, куда пишутся команды на языке META. Если посмотреть на код graph-mfp.mp, то можно увидеть, что там используется макрос function, который позволяет рисовать функции одной командой, без всяких циклов. Как это делается, можно подглядеть в библиотечке grafbase.mp, которая входит в состав пакета mfpic.

Более подробно про пакет mfpic можно узнать из документации которую можно найти в директории $(TEXMF)/texmf-dist/doc/generic/mfpic/, где $(TEXMF) – директория в которую установлен LaTeX (это заведомо верно для дистрибутива TeX Live).

[править] gnuplot

(thumbnail)
Интегральная светимость от времени. Данные за полтора года (примерно 130 тысяч точек) обработаны с помощью программы gnuplot.

В случае отображения больших объёмов данных лучше использовать gnuplot. Чтобы gnuplot работал с MetaPost, необходимо определить правильное устройство вывода. Для этого в gnuplot следует передать команду:

set terminal mp color LaTeX

В этом случае gnuplot будет выводить графики в формате MetaPost. К сожалению, похоже, что вывод в MetaPost давно не поддерживался, поэтому установка кодировки:

set encoding koi8r

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

В случае, если возникнет желание изменить метки, следует обратить внимание на переменную textmag, которая отвечает за размер текста.

[править] Подведём итоги

С помощью MetaPost можно создавать двумерные графики и диаграммы любой сложности. Возможности языка META и стандартные пакеты позволяют сконцентрироваться на смысловой части и не отвлекаться на отдельные элементы оформления.

Персональные инструменты
купить
подписаться
Яндекс.Метрика