<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="ru">
	<id>https://wiki.gis-lab.info/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=KolesovDmitry</id>
	<title>GIS-Lab - Вклад [ru]</title>
	<link rel="self" type="application/atom+xml" href="https://wiki.gis-lab.info/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=KolesovDmitry"/>
	<link rel="alternate" type="text/html" href="https://wiki.gis-lab.info/w/%D0%A1%D0%BB%D1%83%D0%B6%D0%B5%D0%B1%D0%BD%D0%B0%D1%8F:%D0%92%D0%BA%D0%BB%D0%B0%D0%B4/KolesovDmitry"/>
	<updated>2026-04-28T16:07:50Z</updated>
	<subtitle>Вклад</subtitle>
	<generator>MediaWiki 1.39.6</generator>
	<entry>
		<id>https://wiki.gis-lab.info/index.php?title=%D0%98%D1%81%D0%BF%D0%BE%D0%BB%D1%8C%D0%B7%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5_%D0%BA%D0%BE%D0%BD%D1%81%D0%BE%D0%BB%D1%8C%D0%BD%D0%BE%D0%B3%D0%BE_DTclassifier_%D0%B4%D0%BB%D1%8F_%D0%BA%D0%BB%D0%B0%D1%81%D1%81%D0%B8%D1%84%D0%B8%D0%BA%D0%B0%D1%86%D0%B8%D0%B8_%D1%80%D0%B0%D1%81%D1%82%D1%80%D0%BE%D0%B2%D1%8B%D1%85_%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D1%85_%D0%B8_%D0%B0%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0_%D0%B8%D0%B7%D0%BC%D0%B5%D0%BD%D0%B5%D0%BD%D0%B8%D0%B9&amp;diff=24837</id>
		<title>Использование консольного DTclassifier для классификации растровых данных и анализа изменений</title>
		<link rel="alternate" type="text/html" href="https://wiki.gis-lab.info/index.php?title=%D0%98%D1%81%D0%BF%D0%BE%D0%BB%D1%8C%D0%B7%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5_%D0%BA%D0%BE%D0%BD%D1%81%D0%BE%D0%BB%D1%8C%D0%BD%D0%BE%D0%B3%D0%BE_DTclassifier_%D0%B4%D0%BB%D1%8F_%D0%BA%D0%BB%D0%B0%D1%81%D1%81%D0%B8%D1%84%D0%B8%D0%BA%D0%B0%D1%86%D0%B8%D0%B8_%D1%80%D0%B0%D1%81%D1%82%D1%80%D0%BE%D0%B2%D1%8B%D1%85_%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D1%85_%D0%B8_%D0%B0%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0_%D0%B8%D0%B7%D0%BC%D0%B5%D0%BD%D0%B5%D0%BD%D0%B8%D0%B9&amp;diff=24837"/>
		<updated>2016-12-09T10:41:46Z</updated>

		<summary type="html">&lt;p&gt;KolesovDmitry: /* Работа с расширением */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Статья|Черновик}} &lt;br /&gt;
{{Аннотация|Описание и примеры использования консольной версии DTclassifier для классификации растровых данных.}}&lt;br /&gt;
&lt;br /&gt;
'''DT classifier''' - это простой в использовании и эффективный плагин для классификации растровых изображений. &lt;br /&gt;
Декстопная версия расширения входит в дистрибутив [http://nextgis.ru/nextgis-qgis/ NextGIS QGIS].&lt;br /&gt;
Расширение использует метод деревьев решений, реализованный на основе библиотеки [https://github.com/opencv/opencv/wiki OpenCV]. &lt;br /&gt;
Подробнее об установке и работе декстопной версии расширения написано [http://gis-lab.info/qa/dtclassifier.html здесь].&lt;br /&gt;
&lt;br /&gt;
Плагин имеет удобный графический интерфейс, но для некоторых задач, например, &lt;br /&gt;
для встраивания алгоритмов классификации в процесс обработки изображений или для анализа большого количества данных, удобнее использовать консольную версию инструмента. Про нее и пойдет речь в этой статье.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Тестовые данные ====&lt;br /&gt;
&lt;br /&gt;
[https://drive.google.com/file/d/0B-Sx9ICoBa2QZzlCR2tOZEgtWkE/view?usp=sharing Загрузить] архив c данными, использовавшимися при подготовке статьи (4.7Гб).&lt;br /&gt;
&lt;br /&gt;
=== Работа с расширением === &lt;br /&gt;
Синтаксис расширения включает несколько обязательных параметров и ряд дополнительных, &lt;br /&gt;
расширяющих функциональность приложения.&lt;br /&gt;
&lt;br /&gt;
[[Файл:DTconsol_pic2a.jpg|700px|thumb|center]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;classifier.bat&amp;lt;/pre&amp;gt; &lt;br /&gt;
&lt;br /&gt;
- запуск расширения&lt;br /&gt;
&lt;br /&gt;
'''Основные опции'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;--input_rasters&amp;lt;/pre&amp;gt;  &lt;br /&gt;
&lt;br /&gt;
- пути к растровым данным ('''ВАЖНО'''! необходимо указывать полные пути к файлам), разделенные пробелом&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;--presence &amp;lt;/pre&amp;gt; &lt;br /&gt;
&lt;br /&gt;
- полные пути к векторным слоям объектов, содержащие признак, который нужно выделить при анализе, разделенные пробелом. Например, для природных экосистем: облака, водные объекты, рубки или пожары.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;--absence&amp;lt;/pre&amp;gt; &lt;br /&gt;
&lt;br /&gt;
- полные пути к векторным слоям фоновых объектов, т.е. объектам, от которых нужно отделить объекты, содержащие признак.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;--classify&amp;lt;/pre&amp;gt; &lt;br /&gt;
&lt;br /&gt;
путь для сохранения результата классификации&lt;br /&gt;
&lt;br /&gt;
'''Дополнительные опции'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;--decision_tree&amp;lt;/pre&amp;gt; &lt;br /&gt;
&lt;br /&gt;
- использует дерево решений (по умолчанию используется случаный лес, т.е. random forest). ПРИМЕЧАНИЕ: Опыт показывает, что использование Random Forest обычно существенно улучшает результат классификации по сравнению с деревом решений&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;--discrete_classes&amp;lt;/pre&amp;gt; &lt;br /&gt;
&lt;br /&gt;
- Применяется при использовании одиночного дерева (--use_decision_tree). В этом случае, если флаг установлен, исходные данные будут трактоваться как набор дискретных величин (классификационная модель). Если флаг не установлен, то используется регрессионная модель.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;--generalize&amp;lt;/pre&amp;gt; &lt;br /&gt;
&lt;br /&gt;
- размер окна для генерализации (kernel size). «Cглаживание» результатов классификации с настраиваемым размером окна. При включенном сглаживании будет создан не один, а два растра: классифицированный и сглаженный (имя содержит суффикс «_smooth»).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;--save_train_layer &amp;lt;/pre&amp;gt; &lt;br /&gt;
&lt;br /&gt;
- сохраняет слой тренингов, полученный из обучающих данных (полигонов, линий и тд.) в виде точечного шейп-файла с атрибутивной таблицей, включающей значения растров и классы обучающей выборки (1- presence,0 - absence)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;--save_model&amp;lt;/pre&amp;gt; &lt;br /&gt;
&lt;br /&gt;
- сохраняет модель (дерево решений или модель random forest) в файл (.yaml)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;--use_model&amp;lt;/pre&amp;gt; &lt;br /&gt;
&lt;br /&gt;
- использует существующую модель. При этом параметры --presence и --absence игнорируются.&lt;br /&gt;
('''ВАЖНО'''! количество и порядок каналов должен быть таким же как при создании модели, иначе результат будет некорректным)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;--use_train_layer&amp;lt;/pre&amp;gt; &lt;br /&gt;
&lt;br /&gt;
- использует существующий точечный файл (полученный при помощи опции --save_train_layer) для создания модели. При этом игнорируются опции --presence и --absence. Также используется для создания модели без последующей классификации. В этом случае достаточно просто игнорировать опции --classify и --input_rasters&lt;br /&gt;
&lt;br /&gt;
Также приведены примеры синтаксиса командной строки:&lt;br /&gt;
&lt;br /&gt;
Классификация.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
classifier.bat  --input_rasters rast1 [rast2, ...] --presence vect1.shp [vect2, ...] --absence vect1.shp [vect2, ...] --classify result.tiff&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Классификация c с использованием существующей модели.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
classifier.bat  --input_rasters rast1 [rast2, ...] --use_model model.yaml --classify result.tiff&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Создание модели (без классификации).&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
classifier.bat  --input_rasters rast1 [rast2, ...] --presence vect1.shp [vect2, ...] --absence vect1.shp [vect2, ...] --save_model model.yaml &lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Создание модели на основе точечного слоя.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
classifier.bat --use_train_layer train_points.shp --save_model model.yaml &lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Создание точечного слоя тренингов.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
classifier.bat --input_rasters rast1 [rast2, ...] --presence vect1.shp [vect2, ...] --absence vect1.shp [vect2, ...] --save_train_layer train_points.shp &lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''TODO''': Проверить! Если слой тренингов выходит за границы растра, то часть точек за границами создается с ненулевыми значениями (+ errors при выполнении), которые приходится удалять вручную.&lt;br /&gt;
&lt;br /&gt;
=== Примеры использования === &lt;br /&gt;
&lt;br /&gt;
==== Пример 1. Классификация сцен Landsat в batch режиме на основе общего слоя тестовых объектов ====&lt;br /&gt;
&lt;br /&gt;
Для выявления изменения лесного покрова в результате рубок в зимний период используется анализ изменений 2-х и более сцен Landsat. Если территория исследования занимает значительную площадь&lt;br /&gt;
и включает в себя несколько path/row спутника, то удобнее использовать консольную версию для проведения классификации в batch режиме. В данном примере, сцены Landsat за период 2015-2016 гг. &lt;br /&gt;
разбиты по директориям (data/&amp;lt;path/row&amp;gt;) и классификация проводится последовательно для каждого path/row.&lt;br /&gt;
Обучающая выборка (тренинги) состоит из двух шейп-файлов (сut1.shp - рубки, произошедшие за период наблюдения и nochange.shp - не изменившиеся территории). Тренинги находятся в отдельной директории (trainings).&lt;br /&gt;
&lt;br /&gt;
[[Файл:Pic1.jpg|700px|thumb|center|Создание обучающей выборки (тренингов) по снимкам Landsat до (декабрь 2015) и после (январь 2016) вырубки]]&lt;br /&gt;
&lt;br /&gt;
Распакуем и сохраним на диске тестовые данные. В примере используется расположение d:\DT. &lt;br /&gt;
Снимки лежат в d:\DT\data, тренинги в d:\DT\trainings. Командная строка для классификации отдельного path/row:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
classifier.bat --presence d:\DT\trainings\cut1.shp --absence d:\DT\trainings\nochange.shp --input_rasters d:\DT\data\113027\113027_16055.tif d:\DT\data\113027\113027_15020.tif --save_points --save_model d:\DT\data\113027\model.aml --classify d:\DT\data\113027\113027_dtclass.tif --generalize 3&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Здесь следует пояснить, что при создании модели программа использует только те полигоны обучающей выборки которые пересекаются с указанными --input_rasters (если точнее, для всех остальных объектов, значения спектральных каналов будут равны нулю). Полигоны взяты из общего слоя, но для построения модели важны только те которые пересекаются с экстентом указанных в командной строке сцен. Количество каналов (bands) по которым строится модель равно сумме всех каналов сцен перечисленных в --input_rasters. Значения пикселей пересекающие полигоны (также можно использовать линии или точки) обучающей выборки (тренингов), на основе которых и строится модель классификации, можно сохранить в виде точечного слоя (опция  --save_points). Также можно сохранить и саму модель (опция --save_model). Для каждой поддиректории (path/row) модель будет уникальной, поскольку строится только на тех полигонах (из слоя cut1.shp) которые пересекаются со снимком. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Для обработки нескольких path/row можно создать .bat файл, в котором последовательно записать командные строки для обработки всех директорий&lt;br /&gt;
или создать скрипт (например на python):&lt;br /&gt;
&lt;br /&gt;
Пример [https://github.com/IgorGlushkov/DT_classifier_utilities/blob/master/DT_batch_classify.py скрипта] для обработки нескольких сцен &lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
# -*- coding: UTF-8 -*-&lt;br /&gt;
import os&lt;br /&gt;
import glob&lt;br /&gt;
&lt;br /&gt;
# path to data&lt;br /&gt;
datadir='d:\DT\data'&lt;br /&gt;
# path to training&lt;br /&gt;
traindir='d:\DT\\trainings'&lt;br /&gt;
# presence&lt;br /&gt;
presence=os.path.join(traindir,'cut1.shp')&lt;br /&gt;
# absence&lt;br /&gt;
absence=os.path.join(traindir,'nochange.shp')&lt;br /&gt;
#result&lt;br /&gt;
result='d:\DT\\result'&lt;br /&gt;
&lt;br /&gt;
for subdir, dirs, files in os.walk(datadir):&lt;br /&gt;
	scenes=glob.glob(os.path.join(subdir, '*.tif'))&lt;br /&gt;
	if scenes == []:&lt;br /&gt;
	   continue&lt;br /&gt;
	else:&lt;br /&gt;
	   scenes=' '.join(scenes)&lt;br /&gt;
	   output=os.path.join(result, str(os.path.basename(subdir))+'out.tif')&lt;br /&gt;
	   model=os.path.join(result, str(os.path.basename(subdir))+'model.yaml')&lt;br /&gt;
	   train_points=os.path.join(result, str(os.path.basename(subdir))+'train_points.shp')&lt;br /&gt;
	   # command DTclassifier&lt;br /&gt;
	   command= 'classifier.bat --input_rasters %s --save_train_layer %s --save_model %s --presence %s --absence %s --classify %s --generalize 3' % (scenes,train_points,model,presence,absence,output)&lt;br /&gt;
	   #run command&lt;br /&gt;
	   os.system(command)&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Запустим скрипт в OSGeo4W shell:&lt;br /&gt;
&lt;br /&gt;
[[Файл:Runscript.jpg|700px|thumb|center]]&lt;br /&gt;
&lt;br /&gt;
После выполнения операции результаты будут сохранены в директорию d:\DT\result (генерализованые растры имеют суффикс _smooth.tif). Также будут сохранены векторные слои (точки) треннингов (&amp;lt;path/row&amp;gt;train_points.shp) и модели (&amp;lt;path/row&amp;gt;model.yaml).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Результат классификации:&lt;br /&gt;
&lt;br /&gt;
[[Файл:DTconsol_pic4.jpg|700px|thumb|center|Результат анализа изменений по снимкам Landsat слева - общий результат, справа примеры снимков до (декабрь 2015) и после (январь-февраль 2016) нарушения, и результат классификации]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Файл:Pic2res.jpg|700px|thumb|center|Пример выявления выборочной рубки]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Пример 2. Создание объединенной модели классификации ====&lt;br /&gt;
&lt;br /&gt;
ВАЖНО: Этот пример носит скорее демонстрационный характер, поскольку для создания реальной модели входящие данные должны быть [http://gis-lab.info/qa/regress-r.html нормализованы].&lt;br /&gt;
&lt;br /&gt;
Предыдущий пример фактически повторяет функционал декстопной версии, а в данном примере используются две новые функции DTClassifier ----use_train_layer и --use_model, которые позволяют собирать тренировочные данные с отдельно выбранных сцен и на этой основе создавать модель, которую затем можно применить ко всему массиву данных. &lt;br /&gt;
&lt;br /&gt;
Структура входящих данных (число каналов или сцен) должна быть одинаковой для каждого блока данных, в отличие от предыдущего примера, где число снимков / каналов в поддиректории может варьировать, поскольку для каждого path/row создается отдельная модель для классификации. В нашем случае количество каналов для каждого path/row одинаковое (2 снимка по 7 каналов в каждой поддиректории), поэтому в данном примере мы используем сохраненные на предыдущем этапе точечные данные (--save_points) для создания общей для всех сцен модели и последовательно применим ее к каждой поддиректории с данными. &lt;br /&gt;
&lt;br /&gt;
Для этого создадим объединенный слой точек train_points.shp, просто объединив ..113027\out_train_points.shp и ..112027\out_train_points.shp в QGIS. Дополнительно можно убрать нулевые значения&lt;br /&gt;
что выровняет баланс между числом тренировочных точек, содержащих признак, и точками с его отсутствием.&lt;br /&gt;
&lt;br /&gt;
[[Файл:DTconsol pic6.jpeg|700px|thumb|center|Точечный слой треннингов для созданий модели]]&lt;br /&gt;
&lt;br /&gt;
Для отдельной рубки слой выглядит так:&lt;br /&gt;
&lt;br /&gt;
[[Файл:Ex2 trainings1.jpg|700px|thumb|center|Точечный слой треннингов для отдельной рубки (пример)]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Сохраним объединенный слой точек в директорию d:\DT\model\points.shp. Затем создадим модель, используя командную строку:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
classifier.bat --use_train_layer d:\DT\model\points.shp --save_model d:\DT\model\model_all.yaml &lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
И применим ее последовательно к данным, к примеру, используя скрипт (python):&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
# -*- coding: UTF-8 -*-&lt;br /&gt;
import os&lt;br /&gt;
import glob&lt;br /&gt;
&lt;br /&gt;
# path to data&lt;br /&gt;
datadir='d:\DT\data'&lt;br /&gt;
# path to model&lt;br /&gt;
model='d:\DT\model\model_all.yaml'&lt;br /&gt;
#result&lt;br /&gt;
result='d:\DT\\result'&lt;br /&gt;
&lt;br /&gt;
for subdir, dirs, files in os.walk(datadir):&lt;br /&gt;
	scenes=glob.glob(os.path.join(subdir, '*.tif'))&lt;br /&gt;
	if scenes == []:&lt;br /&gt;
	   continue&lt;br /&gt;
	else:&lt;br /&gt;
	   scenes=' '.join(scenes)&lt;br /&gt;
	   output=os.path.join(result, str(os.path.basename(subdir))+'out1.tif')&lt;br /&gt;
	   #command DTclassifier&lt;br /&gt;
	   command= 'classifier.bat --input_rasters %s --use_model %s --classify %s --generalize 3' % (scenes,model,output)&lt;br /&gt;
	   #run command&lt;br /&gt;
	   print command&lt;br /&gt;
	   os.system(command)&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
После завершения, в директории d:\DT\result добавятся результаты классификации (&amp;lt;path/row&amp;gt;out1.tif и &amp;lt;path/row&amp;gt;out1_smooth.tif).&lt;br /&gt;
&lt;br /&gt;
Откроем результат в QGIS:&lt;br /&gt;
&lt;br /&gt;
[[Файл:Ex2 resmodel.jpg|700px|thumb|center|Результат классификации. Сверху-вниз примеры выявления выборочных рубок на снимках Landsat до и после нарушения. Дата снимка - в верхнем левом углу.]]&lt;br /&gt;
&lt;br /&gt;
Цветом показаны результаты классификации на основе объединенной модели (красным) и модели для каждой сцены (синим - модель из предыдущего примера).&lt;br /&gt;
Следует отметить, что результат объединенной модели несколько хуже (меньшая площадь рубок попала в изменения), что скорее всего связано с варьированием яркости между ненормализованными снимками.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Пример 3. Cоздание модели облачности на основе ''исходных'' данных Landsat ====&lt;br /&gt;
&lt;br /&gt;
'''ВАЖНО''': Этот пример также носит скорее демонстрационный характер, поскольку для создания реальной модели каналы лучше сначала перевести в значения излучения на сенсоре ([https://grasswiki.osgeo.org/wiki/Atmospheric_correction toar reflectance]).&lt;br /&gt;
&lt;br /&gt;
Данный пример иллюстрирует возможность встраивания плагина в процесс обработки данных, например создание масок облачности (или любой другой классификации) для нескольких сцен, на основе общего слоя треннингов.&lt;br /&gt;
В директории DT\cloud_data находится три &amp;quot;исходных&amp;quot; сцены Landsat (..tar.gz - архивы), а в DT\cloud_trainings обучающие слои облаков (cloud.shp) и необлачных участков (nocloud.shp). В данном примере слои получены случайной выборкой из классифицированного до этого (другими методами) растра, но также можно использовать любые другие способы создания тестовых объектов. &lt;br /&gt;
Попробуем максимально автоматизировать процесс обработки и получения масок облачности для данных сцен.&lt;br /&gt;
&lt;br /&gt;
Для этого воспользуемся возможностями python, целиком скрипт доступен [https://github.com/IgorGlushkov/DT_classifier_utilities/blob/master/DT_cloud_model.py здесь].&lt;br /&gt;
&lt;br /&gt;
Разобьем обработку на несколько этапов:&lt;br /&gt;
&lt;br /&gt;
'''Определение путей к данным и тренингам и импорт необходимых библиотек.'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
# -*- coding: UTF-8 -*-&lt;br /&gt;
import os&lt;br /&gt;
import glob&lt;br /&gt;
import tarfile&lt;br /&gt;
&lt;br /&gt;
# path to data&lt;br /&gt;
datadir='d:\DT\cloud_data'&lt;br /&gt;
# path to training&lt;br /&gt;
traindir='d:\DT\cloud_trainings'&lt;br /&gt;
# presence&lt;br /&gt;
presence=os.path.join(traindir,'cloud.shp')&lt;br /&gt;
# absence&lt;br /&gt;
absence=os.path.join(traindir,'nocloud.shp')&lt;br /&gt;
#merge points&lt;br /&gt;
merge_train_points='cloud_train_points.shp'&lt;br /&gt;
#model&lt;br /&gt;
model='d:\DT\model\model_cloud.yaml'&lt;br /&gt;
#result&lt;br /&gt;
result='d:\DT\\result'&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Распаковка и удаление ненужных каналов.'''&lt;br /&gt;
&lt;br /&gt;
В данном примере я просто удалил панхроматические и BQA каналы, но конечно можно использовать и другие опции (и код), чтобы сохранить эти данные для других задач.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
#unzip in separate folders&lt;br /&gt;
scenes = glob.glob(os.path.join(datadir, '*gz'))&lt;br /&gt;
for scene in scenes:&lt;br /&gt;
    try:&lt;br /&gt;
		a = tarfile.open(scene)&lt;br /&gt;
		scene_name = scene.split('.')[0]&lt;br /&gt;
		a.extractall(path=os.path.join(datadir,scene_name))&lt;br /&gt;
		a.close()&lt;br /&gt;
    except IOError:&lt;br /&gt;
        False&lt;br /&gt;
		&lt;br /&gt;
#remove BQA bands&lt;br /&gt;
for subdir, dirs, files in os.walk(datadir):&lt;br /&gt;
	bands=glob.glob(os.path.join(subdir, '*BQA.TIF'))&lt;br /&gt;
	if bands == []:&lt;br /&gt;
	   continue&lt;br /&gt;
	else:&lt;br /&gt;
	   command= 'rm %s' % (bands[0])&lt;br /&gt;
	   print command&lt;br /&gt;
	   os.system(command)&lt;br /&gt;
	   &lt;br /&gt;
#remove panchromatic bands&lt;br /&gt;
for subdir, dirs, files in os.walk(datadir):&lt;br /&gt;
	bands=glob.glob(os.path.join(subdir, '*B8.TIF'))&lt;br /&gt;
	if bands == []:&lt;br /&gt;
	   continue&lt;br /&gt;
	else:&lt;br /&gt;
	   command= 'rm %s' % (bands[0])&lt;br /&gt;
	   print command&lt;br /&gt;
	   os.system(command) &lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Создание общего точечного слоя тренингов.'''&lt;br /&gt;
&lt;br /&gt;
Здесь следует отметит, что создание обучающего слоя тренингов - ключевой момент, который определяет качество получаемой модели и классификации. Для данного примера важно, чтобы тренинги с облаками не располагались в области перекрытия снимков, поскольку в этом случае возникнут дублирующиеся точки с разными значениями класса объекта, но с одинаковыми значениями излучения в каналах снимка.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Также следует учитывать, что DT classifier собирает данные со всех тренингов последовательно для каждого снимка, что приводит к появлению большого числа нулевых значений там, где тренинги выходят за границы снимка, поэтому при объединении задана функция &amp;quot;использовать только ненулевые значения каналов (в данном примере -where Band_1 &amp;gt; 0)&amp;quot;. При использовании большего числа снимков необходимо будет учитывать и дату каждой отдельной сцены при создании тренингов, но в данном простом примере используются только неперекрывающиеся участки облачности. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
#create train points from selected scenes&lt;br /&gt;
for subdir, dirs, files in os.walk(datadir):&lt;br /&gt;
	bands=glob.glob(os.path.join(subdir, '*.TIF'))&lt;br /&gt;
	if bands == []:&lt;br /&gt;
	   continue&lt;br /&gt;
	else:&lt;br /&gt;
	   bands=' '.join(bands)&lt;br /&gt;
	   train_points=os.path.join(traindir, str(os.path.basename(subdir))+'train_points.shp')&lt;br /&gt;
	   command= 'classifier.bat --input_rasters %s --save_train_layer %s --presence %s --absence %s' % (bands,train_points,presence,absence)&lt;br /&gt;
	   print command&lt;br /&gt;
	   os.system(command)&lt;br /&gt;
&lt;br /&gt;
#merge trainings with null values removing using ogr2ogr&lt;br /&gt;
commandlist=[]&lt;br /&gt;
driver='ESRI Shapefile'&lt;br /&gt;
trainings=glob.glob(os.path.join(traindir, '*train_points.shp'))&lt;br /&gt;
for training in trainings:&lt;br /&gt;
	if commandlist == []:&lt;br /&gt;
	   merge_train=os.path.join(traindir, merge_train_points)&lt;br /&gt;
	   command='ogr2ogr -f \&amp;quot;%s\&amp;quot; %s %s -where \&amp;quot;Band_1 &amp;gt; 0\&amp;quot;' % (driver,merge_train,training)&lt;br /&gt;
	   merge_name = merge_train_points.split('.')[0]&lt;br /&gt;
	   command1='ogr2ogr -f \&amp;quot;%s\&amp;quot; -update -append  %s %s -nln %s -where \&amp;quot;Band_1 &amp;gt; 0\&amp;quot;' % (driver,merge_train,training,merge_name)&lt;br /&gt;
	   commandlist.append(command)&lt;br /&gt;
	   commandlist.append(command1)&lt;br /&gt;
	else:&lt;br /&gt;
	   merge_train=os.path.join(traindir, merge_train_points)&lt;br /&gt;
	   #remove ext&lt;br /&gt;
	   merge_name = merge_train_points.split('.')[0]&lt;br /&gt;
	   command='ogr2ogr -f \&amp;quot;%s\&amp;quot; -update -append  %s %s -nln %s -where \&amp;quot;Band_1 &amp;gt; 0\&amp;quot;' % (driver,merge_train,training,merge_name)&lt;br /&gt;
	   commandlist.append(command)&lt;br /&gt;
&lt;br /&gt;
#run merge shp &lt;br /&gt;
#f = open('%s\com.txt' % (traindir), 'w')&lt;br /&gt;
for command in commandlist:&lt;br /&gt;
	#f.write(command+'\n')&lt;br /&gt;
	os.system(command)&lt;br /&gt;
#f.close()&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
В результате - создан точечный слой d:\DT\cloud_trainings\cloud_train_points.shp.&lt;br /&gt;
&lt;br /&gt;
[[Файл:Ex3 trainigs fin.jpg|700px|thumb|center|Точечный слой треннингов на облачность]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Создание модели и классификация.'''&lt;br /&gt;
&lt;br /&gt;
Заключительный этап - создание модели из объединенного слоя тренингов и классификация.&lt;br /&gt;
Результаты сохранены в директории ..DT\result в двух файлах для каждого снимка, &amp;lt;имя исходного архива&amp;gt;..out_cloud.tif и ..out_cloud_smooth.tif (генерализованный)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
#create model&lt;br /&gt;
if os.path.isfile(os.path.join(traindir,merge_train_points)):&lt;br /&gt;
   try:&lt;br /&gt;
      merge_train=os.path.join(traindir,merge_train_points)&lt;br /&gt;
      command='classifier.bat --use_train_layer %s --save_model %s' % (merge_train,model)&lt;br /&gt;
      os.system(command)&lt;br /&gt;
   except IOError:&lt;br /&gt;
      False&lt;br /&gt;
&lt;br /&gt;
#classify&lt;br /&gt;
for subdir, dirs, files in os.walk(datadir):&lt;br /&gt;
	bands=glob.glob(os.path.join(subdir, '*.TIF'))&lt;br /&gt;
	if bands == []:&lt;br /&gt;
	   continue&lt;br /&gt;
	else:&lt;br /&gt;
	   bands=' '.join(bands)&lt;br /&gt;
	   output=os.path.join(result, str(os.path.basename(subdir))+'out_cloud.tif')&lt;br /&gt;
	   command= 'classifier.bat --input_rasters %s --use_model %s --classify %s --generalize 3' % (bands,model,output)&lt;br /&gt;
	   print command&lt;br /&gt;
	   os.system(command)&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Результат автоматической обработки:&lt;br /&gt;
&lt;br /&gt;
[[Файл:Ex3 result fin.jpg|700px|thumb|center|Результат классификации - маска облаков (синим), справа примеры снимка с результатом классификации (справа внизу) и без (справа вверху)]]&lt;br /&gt;
&lt;br /&gt;
В качестве заключения можно сказать, что автоматизация задач обработки и классификации данных ДЗЗ развивается стремительными темпами, и хотя по-прежнему остается прерогативой крупных команд и организаций,&lt;br /&gt;
методы полу-автоматической и автоматической обработки становятся доступны и для более широкого круга пользователей. &lt;br /&gt;
&lt;br /&gt;
Данное расширение, благодаря простоте и относительно высокой производительности, позволит развивать свои проекты в области ДЗЗ не только профессиональным разработчикам, но и исследователям, только начинающим использовать языки программирования в своей работе.&lt;/div&gt;</summary>
		<author><name>KolesovDmitry</name></author>
	</entry>
	<entry>
		<id>https://wiki.gis-lab.info/index.php?title=%D0%9C%D0%BE%D0%B4%D1%83%D0%BB%D1%8C_r.series.filter_%D0%93%D0%98%D0%A1_GRASS&amp;diff=23496</id>
		<title>Модуль r.series.filter ГИС GRASS</title>
		<link rel="alternate" type="text/html" href="https://wiki.gis-lab.info/index.php?title=%D0%9C%D0%BE%D0%B4%D1%83%D0%BB%D1%8C_r.series.filter_%D0%93%D0%98%D0%A1_GRASS&amp;diff=23496"/>
		<updated>2015-12-23T19:40:11Z</updated>

		<summary type="html">&lt;p&gt;KolesovDmitry: /* Фильтрация вегетационных индексов */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Статья|Черновик}}&lt;br /&gt;
&lt;br /&gt;
{{NextGIS}}&lt;br /&gt;
&lt;br /&gt;
== Назначение модуля ==&lt;br /&gt;
Модуль r.series.filter -- это модуль для геоинформационной системы GRASS, предназначенный для обработки временных рядов растровых данных, в первую очередь вегетационных индексов. Модуль производит очистку от шумов временных рядов с использованием различных фильтров (медианый фильтр, [https://en.wikipedia.org/wiki/Savitzky%E2%80%93Golay_filter фильтр Савицкого-Голея]). Модуль может использоваться для очистки от шумов временных рядов произвольной природы, однако одной из важных особенностей модуля является поддерка фильтрации данных вегетационных индексов. Для обработки таких рядов модуль реализует процедуру фильтрации, предложенную в статье &amp;quot;Chen J. et al. A simple method for reconstructing a high-quality NDVI time-series data set based on the Savitzky–Golay filter //Remote sensing of Environment. – 2004. – Т. 91. – №. 3. – С. 332-344.&amp;quot;. Основная идея этого фильтра опирается на то, что шумы в значениях вегетационных индексов обычно индуцируются условиями съемки и атмосферными явлениями, которые занижают зачения индекса. В очень упрощенном виде можно сказать, что предлагаемая в указанной статье методика производит отбраковку низких значений индекса и производит фильтрацию по верхним значениям анализируемого временного ряда.&lt;br /&gt;
&lt;br /&gt;
== Установка ==&lt;br /&gt;
Модуль был написан на языке Python и предназначен для работы в GRASS GIS седьмой версии. В модуле используются библиотека [http://docs.scipy.org/doc/scipy/reference/signal.html scipy.signal], входящая в состав пакета [http://www.scipy.org/about.html SciPy]. Поэтому перед началом работы в интерпретатор Python, используемый в GRASS, следует установить SciPy.&lt;br /&gt;
&lt;br /&gt;
После установки SciPy появится возможность установить сам модуль r.series.filter. Данный модуль доступен в репозитории модулей GRASS ADDONS, поэтому его установка производится автоматически, если использовать модуль g.extension (вызываемый из графического интерфейса пользователя или командной строки). Например, можно использовать следущюую команду:&lt;br /&gt;
 g.extension r.series.filter&lt;br /&gt;
В результате модуль будет автоматически скачан из репозитория и установлен.&lt;br /&gt;
&lt;br /&gt;
== Особенности работы и примеры ==&lt;br /&gt;
&lt;br /&gt;
=== Параметры модуля и их назначение ===&lt;br /&gt;
Модуль находится в состоянии разработки, это означает, что в него будут добавляться новые возможности. На момент написания статьи модуль использует следующие параметры и ключи (показаны наиболее важные):&lt;br /&gt;
&lt;br /&gt;
 r.series.filter [-cu] input=string[,string,...] result_prefix=string&lt;br /&gt;
   [method=string] [winsize=value] [order=value] [opt_points=value]&lt;br /&gt;
   [diff_penalty=value] [deriv_penalty=value] [iterations=value]&lt;br /&gt;
 Flags:&lt;br /&gt;
   -c   Try to find optimal parameters for filtering&lt;br /&gt;
   -u   Fit the result curve by upper boundary&lt;br /&gt;
 Parameters:&lt;br /&gt;
          input   Raster names of equally spaced time series.&lt;br /&gt;
  result_prefix   Prefix for raster names of filtered X(t)&lt;br /&gt;
         method   Used method&lt;br /&gt;
                  default: savgol&lt;br /&gt;
        winsize   Length of running window for the filter&lt;br /&gt;
                  default: 9&lt;br /&gt;
          order   Order of the Savitzky-Golay filter&lt;br /&gt;
                  default: 2&lt;br /&gt;
     opt_points   Count of random points used for parameter optimization&lt;br /&gt;
                  default: 50&lt;br /&gt;
   diff_penalty   Penalty for difference between original and filtered signals&lt;br /&gt;
                  default: 1.0&lt;br /&gt;
  deriv_penalty   Penalty for big derivates of the filtered signal&lt;br /&gt;
                  default: 1.0&lt;br /&gt;
     iterations   Number of iterations&lt;br /&gt;
                  default: 1&lt;br /&gt;
&lt;br /&gt;
==== Параметры общего назначения ====&lt;br /&gt;
Два параметра input и result_prefix отвечают за перечень входных и выходных растров. Модуль ожидает, что на вход ему будет передан список растров, перечисленных через запятую в порядке возрастания (или убывания) времени. Например:&lt;br /&gt;
  input=ndvi1,ndvi2,ndvi3,ndvi4,....&lt;br /&gt;
При этом временной ряд должен быть равноотстоящим, т.е. растры представляют собой измерения какой-либо величины (или состояния территории), сделанные через равные промежутки времени. Но на практике не всегда возможно иметь дело с равноотстоящими рядами, часть каких-либо измерений может отсутсвовать по объетивным причинам. В таком случае следует вставить пустой растр, состоящий из значений NULL (нет данных), который легко сгенерировать, воспользовавшись растровым калькулятором:&lt;br /&gt;
 r.mapcalc expression=&amp;quot;dummy = null()&amp;quot;&lt;br /&gt;
В самих растрах так же могут быть области, с отсутсвующими в них данными, такие участки не требуют специальной предварительной обработки.&lt;br /&gt;
&lt;br /&gt;
Перед началом расчетов такие пропущенные значения будут предварительно заполнены данными, полученными линейной интерполяцией (во времени, пространственная интерполяция не используется).&lt;br /&gt;
&lt;br /&gt;
Результаты будут записаны в новые растры, названия которых начинаются с указанного result_prefix. Например, в случае, если result_prefix=&amp;quot;res.&amp;quot;, будут получены растры: res.ndvi1,res.ndvi2,res.ndvi3,res.ndvi4,....&lt;br /&gt;
&lt;br /&gt;
Таким образом команда со значениями, заданными по умолчанию может выглядеть следующим образом:&lt;br /&gt;
 r.series.filter input=ndvi1,ndvi2,ndvi3,ndvi4,.... result_prefix=&amp;quot;res.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
==== Методы фильтрации ====&lt;br /&gt;
&lt;br /&gt;
На момент написания статьи в модуле реализовано два метода фильтрации:&lt;br /&gt;
* медианный фильтр (параметр method=median);&lt;br /&gt;
* фильтр Савицкого-Голея (method=savgol).&lt;br /&gt;
&lt;br /&gt;
Каждый из этих фильтров работает в скользящем окне и рассчитывает прогнозируемое значение исследуемой величины для центральной точки окна. Поэтому модуль использует еще один параметр winsize, задающий ширину скользящего окна. Этот параметр должен быть нечетным числом.&lt;br /&gt;
&lt;br /&gt;
Кроме того у метода Савцикого-Голея есть еще один параметр -- порядок полинома (order), который используется при аппроксимации временного ряда внутри скользящего окна.&lt;br /&gt;
&lt;br /&gt;
Естественно, что ширина окна и порядок полинома должны быть таковы, что позволят рассчитать коэффициенты полинома. В случае, если порядок полиома превышает допустимый для данной величины окна, будет выведено сообщение об ошибке.&lt;br /&gt;
&lt;br /&gt;
Например, для использования фильтра Савицкого-Голея с порядком полинома, равным трем, и шириной окна 17 отсчетов, нужно использовать следующую команду:&lt;br /&gt;
 r.series.filter input=.... result_prefix=... method=savgol order=3 wunsiz=17&lt;br /&gt;
&lt;br /&gt;
Иногда есть смысл применить последовательно сразу несколько итераций фильтрации (особенно это актуально для медианного фильтра): сначала произвести фильтрацию исходных данных, затем применить этот же фильтр к результам фильтрации и т.д. Поэтому пользователь может уаказать параметр iterations, отвечающий за число итераций, например:&lt;br /&gt;
 r.series.filter input=.... result_prefix=... method=median iterations=5 winsize=21&lt;br /&gt;
&lt;br /&gt;
==== Подбор оптимальных значений параметров ====&lt;br /&gt;
Часто бывает сложно понять, какие значения параметров являются &amp;quot;хорошими&amp;quot; для конкретного набора растров. &lt;br /&gt;
&lt;br /&gt;
Понятно, что эти величины зависят как и от форм анализируемых кривых, так и от целей исследователя, но в довольно обшем случае можно сказать, что качество подгонки может выражаться в виде некоторой функции от точности и &amp;quot;гладкости&amp;quot; результирующей кривой. Точность рассчитать легко как средний модуль разности между исходной кривой и результирующей, а гладкость можно оценить средним модулем разности между соседними значениями результирующей кривой. К сожалению, обычно бывает так, что гладкая и &amp;quot;красивая&amp;quot; кривая является слишком грубой и неточной, и наоборот -- точная кривая обычно повторяет все флуктуации в данных, в том числе и случайные шумы. Поэтому пользователь должен решить, что ему более важно, точность или гладкость.&lt;br /&gt;
&lt;br /&gt;
На этом строится процедура подбора параметров фильтрации: пользователь задает два числа -- штрафы за неточность и негладкость результирующей кривой (параметры модуля diff_penalty и deriv_penalty). Эти штрафы показывают, насколько пользователю важна точность в ущерб гладкости. Затем запускается процедура подбора параметров, работающая следующим образом:&lt;br /&gt;
# Выбираются начальные значения параметра ширины окна для медианного фильра (ширины окна и порядка полинома для фильтра Савицкого-Голея).&lt;br /&gt;
# Выбирается opt_points случайных пикселей.&lt;br /&gt;
# Для выбранных пикселей производится фильтрация с заданными параметрами.&lt;br /&gt;
# Для каждого выбранного пикселя вычилсяется E - средний модуль разности между исходной кривой и результирующей, а также D - средний модуль разности между соседними значениями результирующей кривой.&lt;br /&gt;
# Для каждого пикселя находится взвешенная сумма штрафов: diff_penalty * E + deriv_penalty * D, а затем расчитывается суммарный штраф по всем пикселям. Этот суммарный штраф является оценкой качества подгонки кривых для заданных параметров фильтра.&lt;br /&gt;
&lt;br /&gt;
Затем запускается процедура поиска таких параметров, при которых суммарный штраф будет минимальным. После нахождения таких параметров производится фильтрация всего временного растрового ряда.&lt;br /&gt;
&lt;br /&gt;
Процедура подбора параметров включается флагом &amp;quot;-c&amp;quot;, например:&lt;br /&gt;
 r.series.filter -с input=.... result_prefix=... method=median&lt;br /&gt;
&lt;br /&gt;
==== Фильтрация вегетационных индексов ====&lt;br /&gt;
Как отмечалось выше,  в статье &amp;quot;Chen J. et al. A simple method for reconstructing a high-quality NDVI time-series data set based on the Savitzky–Golay filter //Remote sensing of Environment. – 2004. – Т. 91. – №. 3. – С. 332-344.&amp;quot; предлагается метод фильтрации временных рядов вегетационных индексов, исходя из предположения, что атмосферные явления обычно занижают значения индексов. В исходной статье медод предлагался для фильра Савицкого-Голея, но с таким же успехом его можно применять и к другим фильтрам. Поэтому в модуле r.series.filter пользователь может включить флагом &amp;quot;-u&amp;quot; данную модификацию фильтра:&lt;br /&gt;
 r.series.filter -u input=.... result_prefix=... method=median winsize=15&lt;br /&gt;
Предлагаемый в статье метод является итерационным, он действует на постепенно уменьшающихся величинах ширины скользящего окна, поэтому параметр winsize в данном случае будет означать начальную ширину окна.&lt;br /&gt;
&lt;br /&gt;
Более подробно об функционировании фильтра см. в указанной выше статье.&lt;br /&gt;
&lt;br /&gt;
=== Примеры ===&lt;/div&gt;</summary>
		<author><name>KolesovDmitry</name></author>
	</entry>
	<entry>
		<id>https://wiki.gis-lab.info/index.php?title=%D0%9C%D0%BE%D0%B4%D1%83%D0%BB%D1%8C_r.series.filter_%D0%93%D0%98%D0%A1_GRASS&amp;diff=23453</id>
		<title>Модуль r.series.filter ГИС GRASS</title>
		<link rel="alternate" type="text/html" href="https://wiki.gis-lab.info/index.php?title=%D0%9C%D0%BE%D0%B4%D1%83%D0%BB%D1%8C_r.series.filter_%D0%93%D0%98%D0%A1_GRASS&amp;diff=23453"/>
		<updated>2015-12-21T21:33:38Z</updated>

		<summary type="html">&lt;p&gt;KolesovDmitry: /* Фильтрация вегетационных индексов */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Статья|Черновик}}&lt;br /&gt;
&lt;br /&gt;
{{NextGIS}}&lt;br /&gt;
&lt;br /&gt;
== Назначение модуля ==&lt;br /&gt;
Модуль r.series.filter -- это модуль для геоинформационной системы GRASS, предназначенный для обработки временных рядов растровых данных, в первую очередь вегетационных индексов. Модуль производит очистку от шумов временных рядов с использованием различных фильтров (медианый фильтр, [https://en.wikipedia.org/wiki/Savitzky%E2%80%93Golay_filter фильтр Савицкого-Голея]). Модуль может использоваться для очистки от шумов временных рядов произвольной природы, однако одной из важных особенностей модуля является поддерка фильтрации данных вегетационных индексов. Для обработки таких рядов модуль реализует процедуру фильтрации, предложенную в статье &amp;quot;Chen J. et al. A simple method for reconstructing a high-quality NDVI time-series data set based on the Savitzky–Golay filter //Remote sensing of Environment. – 2004. – Т. 91. – №. 3. – С. 332-344.&amp;quot;. Основная идея этого фильтра опирается на то, что шумы в значениях вегетационных индексов обычно индуцируются условиями съемки и атмосферными явлениями, которые занижают зачения индекса. В очень упрощенном виде можно сказать, что предлагаемая в указанной статье методика производит отбраковку низких значений индекса и производит фильтрацию по верхним значениям анализируемого временного ряда.&lt;br /&gt;
&lt;br /&gt;
== Установка ==&lt;br /&gt;
Модуль был написан на языке Python и предназначен для работы в GRASS GIS седьмой версии. В модуле используются библиотека [http://docs.scipy.org/doc/scipy/reference/signal.html scipy.signal], входящая в состав пакета [http://www.scipy.org/about.html SciPy]. Поэтому перед началом работы в интерпретатор Python, используемый в GRASS, следует установить SciPy.&lt;br /&gt;
&lt;br /&gt;
После установки SciPy появится возможность установить сам модуль r.series.filter. Данный модуль доступен в репозитории модулей GRASS ADDONS, поэтому его установка производится автоматически, если использовать модуль g.extension (вызываемый из графического интерфейса пользователя или командной строки). Например, можно использовать следущюую команду:&lt;br /&gt;
 g.extension r.series.filter&lt;br /&gt;
В результате модуль будет автоматически скачан из репозитория и установлен.&lt;br /&gt;
&lt;br /&gt;
== Особенности работы и примеры ==&lt;br /&gt;
&lt;br /&gt;
=== Параметры модуля и их назначение ===&lt;br /&gt;
Модуль находится в состоянии разработки, это означает, что в него будут добавляться новые возможности. На момент написания статьи модуль использует следующие параметры и ключи (показаны наиболее важные):&lt;br /&gt;
&lt;br /&gt;
 r.series.filter [-cu] input=string[,string,...] result_prefix=string&lt;br /&gt;
   [method=string] [winsize=value] [order=value] [opt_points=value]&lt;br /&gt;
   [diff_penalty=value] [deriv_penalty=value] [iterations=value]&lt;br /&gt;
 Flags:&lt;br /&gt;
   -c   Try to find optimal parameters for filtering&lt;br /&gt;
   -u   Fit the result curve by upper boundary&lt;br /&gt;
 Parameters:&lt;br /&gt;
          input   Raster names of equally spaced time series.&lt;br /&gt;
  result_prefix   Prefix for raster names of filtered X(t)&lt;br /&gt;
         method   Used method&lt;br /&gt;
                  default: savgol&lt;br /&gt;
        winsize   Length of running window for the filter&lt;br /&gt;
                  default: 9&lt;br /&gt;
          order   Order of the Savitzky-Golay filter&lt;br /&gt;
                  default: 2&lt;br /&gt;
     opt_points   Count of random points used for parameter optimization&lt;br /&gt;
                  default: 50&lt;br /&gt;
   diff_penalty   Penalty for difference between original and filtered signals&lt;br /&gt;
                  default: 1.0&lt;br /&gt;
  deriv_penalty   Penalty for big derivates of the filtered signal&lt;br /&gt;
                  default: 1.0&lt;br /&gt;
     iterations   Number of iterations&lt;br /&gt;
                  default: 1&lt;br /&gt;
&lt;br /&gt;
==== Параметры общего назначения ====&lt;br /&gt;
Два параметра input и result_prefix отвечают за перечень входных и выходных растров. Модуль ожидает, что на вход ему будет передан список растров, перечисленных через запятую в порядке возрастания (или убывания) времени. Например:&lt;br /&gt;
  input=ndvi1,ndvi2,ndvi3,ndvi4,....&lt;br /&gt;
При этом временной ряд должен быть равноотстоящим, т.е. растры представляют собой измерения какой-либо величины (или состояния территории), сделанные через равные промежутки времени. Но на практике не всегда возможно иметь дело с равноотстоящими рядами, часть каких-либо измерений может отсутсвовать по объетивным причинам. В таком случае следует вставить пустой растр, состоящий из значений NULL (нет данных), который легко сгенерировать, воспользовавшись растровым калькулятором:&lt;br /&gt;
 r.mapcalc expression=&amp;quot;dummy = null()&amp;quot;&lt;br /&gt;
В самих растрах так же могут быть области, с отсутсвующими в них данными, такие участки не требуют специальной предварительной обработки.&lt;br /&gt;
&lt;br /&gt;
Перед началом расчетов такие пропущенные значения будут предварительно заполнены данными, полученными линейной интерполяцией (во времени, пространственная интерполяция не используется).&lt;br /&gt;
&lt;br /&gt;
Результаты будут записаны в новые растры, названия которых начинаются с указанного result_prefix. Например, в случае, если result_prefix=&amp;quot;res.&amp;quot;, будут получены растры: res.ndvi1,res.ndvi2,res.ndvi3,res.ndvi4,....&lt;br /&gt;
&lt;br /&gt;
Таким образом команда со значениями, заданными по умолчанию может выглядеть следующим образом:&lt;br /&gt;
 r.series.filter input=ndvi1,ndvi2,ndvi3,ndvi4,.... result_prefix=&amp;quot;res.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
==== Методы фильтрации ====&lt;br /&gt;
&lt;br /&gt;
На момент написания статьи в модуле реализовано два метода фильтрации:&lt;br /&gt;
* медианный фильтр (параметр method=median);&lt;br /&gt;
* фильтр Савицкого-Голея (method=savgol).&lt;br /&gt;
&lt;br /&gt;
Каждый из этих фильтров работает в скользящем окне и рассчитывает прогнозируемое значение исследуемой величины для центральной точки окна. Поэтому модуль использует еще один параметр winsize, задающий ширину скользящего окна. Этот параметр должен быть нечетным числом.&lt;br /&gt;
&lt;br /&gt;
Кроме того у метода Савцикого-Голея есть еще один параметр -- порядок полинома (order), который используется при аппроксимации временного ряда внутри скользящего окна.&lt;br /&gt;
&lt;br /&gt;
Естественно, что ширина окна и порядок полинома должны быть таковы, что позволят рассчитать коэффициенты полинома. В случае, если порядок полиома превышает допустимый для данной величины окна, будет выведено сообщение об ошибке.&lt;br /&gt;
&lt;br /&gt;
Например, для использования фильтра Савицкого-Голея с порядком полинома, равным трем, и шириной окна 17 отсчетов, нужно использовать следующую команду:&lt;br /&gt;
 r.series.filter input=.... result_prefix=... method=savgol order=3 wunsiz=17&lt;br /&gt;
&lt;br /&gt;
Иногда есть смысл применить последовательно сразу несколько итераций фильтрации (особенно это актуально для медианного фильтра): сначала произвести фильтрацию исходных данных, затем применить этот же фильтр к результам фильтрации и т.д. Поэтому пользователь может уаказать параметр iterations, отвечающий за число итераций, например:&lt;br /&gt;
 r.series.filter input=.... result_prefix=... method=median iterations=5 winsize=21&lt;br /&gt;
&lt;br /&gt;
==== Подбор оптимальных значений параметров ====&lt;br /&gt;
Часто бывает сложно понять, какие значения параметров являются &amp;quot;хорошими&amp;quot; для конкретного набора растров. &lt;br /&gt;
&lt;br /&gt;
Понятно, что эти величины зависят как и от форм анализируемых кривых, так и от целей исследователя, но в довольно обшем случае можно сказать, что качество подгонки может выражаться в виде некоторой функции от точности и &amp;quot;гладкости&amp;quot; результирующей кривой. Точность рассчитать легко как средний модуль разности между исходной кривой и результирующей, а гладкость можно оценить средним модулем разности между соседними значениями результирующей кривой. К сожалению, обычно бывает так, что гладкая и &amp;quot;красивая&amp;quot; кривая является слишком грубой и неточной, и наоборот -- точная кривая обычно повторяет все флуктуации в данных, в том числе и случайные шумы. Поэтому пользователь должен решить, что ему более важно, точность или гладкость.&lt;br /&gt;
&lt;br /&gt;
На этом строится процедура подбора параметров фильтрации: пользователь задает два числа -- штрафы за неточность и негладкость результирующей кривой (параметры модуля diff_penalty и deriv_penalty). Эти штрафы показывают, насколько пользователю важна точность в ущерб гладкости. Затем запускается процедура подбора параметров, работающая следующим образом:&lt;br /&gt;
# Выбираются начальные значения параметра ширины окна для медианного фильра (ширины окна и порядка полинома для фильтра Савицкого-Голея).&lt;br /&gt;
# Выбирается opt_points случайных пикселей.&lt;br /&gt;
# Для выбранных пикселей производится фильтрация с заданными параметрами.&lt;br /&gt;
# Для каждого выбранного пикселя вычилсяется E - средний модуль разности между исходной кривой и результирующей, а также D - средний модуль разности между соседними значениями результирующей кривой.&lt;br /&gt;
# Для каждого пикселя находится взвешенная сумма штрафов: diff_penalty * E + deriv_penalty * D, а затем расчитывается суммарный штраф по всем пикселям. Этот суммарный штраф является оценкой качества подгонки кривых для заданных параметров фильтра.&lt;br /&gt;
&lt;br /&gt;
Затем запускается процедура поиска таких параметров, при которых суммарный штраф будет минимальным. После нахождения таких параметров производится фильтрация всего временного растрового ряда.&lt;br /&gt;
&lt;br /&gt;
Процедура подбора параметров включается флагом &amp;quot;-c&amp;quot;, например:&lt;br /&gt;
 r.series.filter -с input=.... result_prefix=... method=median&lt;br /&gt;
&lt;br /&gt;
==== Фильтрация вегетационных индексов ====&lt;br /&gt;
Как отмечалось выше,  в статье &amp;quot;Chen J. et al. A simple method for reconstructing a high-quality NDVI time-series data set based on the Savitzky–Golay filter //Remote sensing of Environment. – 2004. – Т. 91. – №. 3. – С. 332-344.&amp;quot; предлагается метод фильтрации временных рядов вегетационных индексов, исходя из предположения, что атмосферные явления обычно занижают значения индексов. В исходной статье медод предлагался для фильра Савицкого-Голея, но с таким же успехом его можно применять и к другим фильтрам. Поэтому в модуле r.series.filter пользователь может включить флагом &amp;quot;-u&amp;quot; данную модификацию фильтра:&lt;br /&gt;
 r.series.filter -с input=.... result_prefix=... method=median winsize=15&lt;br /&gt;
Предлагаемый в статье метод является итерационным, он действует на постепенно уменьшающихся величинах ширины скользящего окна, поэтому параметр winsize в данном случае будет означать начальную ширину окна.&lt;br /&gt;
&lt;br /&gt;
Более подробно об функционировании фильтра см. в указанной выше статье.&lt;br /&gt;
&lt;br /&gt;
=== Примеры ===&lt;/div&gt;</summary>
		<author><name>KolesovDmitry</name></author>
	</entry>
	<entry>
		<id>https://wiki.gis-lab.info/index.php?title=%D0%9C%D0%BE%D0%B4%D1%83%D0%BB%D1%8C_r.series.filter_%D0%93%D0%98%D0%A1_GRASS&amp;diff=23452</id>
		<title>Модуль r.series.filter ГИС GRASS</title>
		<link rel="alternate" type="text/html" href="https://wiki.gis-lab.info/index.php?title=%D0%9C%D0%BE%D0%B4%D1%83%D0%BB%D1%8C_r.series.filter_%D0%93%D0%98%D0%A1_GRASS&amp;diff=23452"/>
		<updated>2015-12-21T21:28:59Z</updated>

		<summary type="html">&lt;p&gt;KolesovDmitry: /* Фильтрация вегетационных индексов */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Статья|Черновик}}&lt;br /&gt;
&lt;br /&gt;
{{NextGIS}}&lt;br /&gt;
&lt;br /&gt;
== Назначение модуля ==&lt;br /&gt;
Модуль r.series.filter -- это модуль для геоинформационной системы GRASS, предназначенный для обработки временных рядов растровых данных, в первую очередь вегетационных индексов. Модуль производит очистку от шумов временных рядов с использованием различных фильтров (медианый фильтр, [https://en.wikipedia.org/wiki/Savitzky%E2%80%93Golay_filter фильтр Савицкого-Голея]). Модуль может использоваться для очистки от шумов временных рядов произвольной природы, однако одной из важных особенностей модуля является поддерка фильтрации данных вегетационных индексов. Для обработки таких рядов модуль реализует процедуру фильтрации, предложенную в статье &amp;quot;Chen J. et al. A simple method for reconstructing a high-quality NDVI time-series data set based on the Savitzky–Golay filter //Remote sensing of Environment. – 2004. – Т. 91. – №. 3. – С. 332-344.&amp;quot;. Основная идея этого фильтра опирается на то, что шумы в значениях вегетационных индексов обычно индуцируются условиями съемки и атмосферными явлениями, которые занижают зачения индекса. В очень упрощенном виде можно сказать, что предлагаемая в указанной статье методика производит отбраковку низких значений индекса и производит фильтрацию по верхним значениям анализируемого временного ряда.&lt;br /&gt;
&lt;br /&gt;
== Установка ==&lt;br /&gt;
Модуль был написан на языке Python и предназначен для работы в GRASS GIS седьмой версии. В модуле используются библиотека [http://docs.scipy.org/doc/scipy/reference/signal.html scipy.signal], входящая в состав пакета [http://www.scipy.org/about.html SciPy]. Поэтому перед началом работы в интерпретатор Python, используемый в GRASS, следует установить SciPy.&lt;br /&gt;
&lt;br /&gt;
После установки SciPy появится возможность установить сам модуль r.series.filter. Данный модуль доступен в репозитории модулей GRASS ADDONS, поэтому его установка производится автоматически, если использовать модуль g.extension (вызываемый из графического интерфейса пользователя или командной строки). Например, можно использовать следущюую команду:&lt;br /&gt;
 g.extension r.series.filter&lt;br /&gt;
В результате модуль будет автоматически скачан из репозитория и установлен.&lt;br /&gt;
&lt;br /&gt;
== Особенности работы и примеры ==&lt;br /&gt;
&lt;br /&gt;
=== Параметры модуля и их назначение ===&lt;br /&gt;
Модуль находится в состоянии разработки, это означает, что в него будут добавляться новые возможности. На момент написания статьи модуль использует следующие параметры и ключи (показаны наиболее важные):&lt;br /&gt;
&lt;br /&gt;
 r.series.filter [-cu] input=string[,string,...] result_prefix=string&lt;br /&gt;
   [method=string] [winsize=value] [order=value] [opt_points=value]&lt;br /&gt;
   [diff_penalty=value] [deriv_penalty=value] [iterations=value]&lt;br /&gt;
 Flags:&lt;br /&gt;
   -c   Try to find optimal parameters for filtering&lt;br /&gt;
   -u   Fit the result curve by upper boundary&lt;br /&gt;
 Parameters:&lt;br /&gt;
          input   Raster names of equally spaced time series.&lt;br /&gt;
  result_prefix   Prefix for raster names of filtered X(t)&lt;br /&gt;
         method   Used method&lt;br /&gt;
                  default: savgol&lt;br /&gt;
        winsize   Length of running window for the filter&lt;br /&gt;
                  default: 9&lt;br /&gt;
          order   Order of the Savitzky-Golay filter&lt;br /&gt;
                  default: 2&lt;br /&gt;
     opt_points   Count of random points used for parameter optimization&lt;br /&gt;
                  default: 50&lt;br /&gt;
   diff_penalty   Penalty for difference between original and filtered signals&lt;br /&gt;
                  default: 1.0&lt;br /&gt;
  deriv_penalty   Penalty for big derivates of the filtered signal&lt;br /&gt;
                  default: 1.0&lt;br /&gt;
     iterations   Number of iterations&lt;br /&gt;
                  default: 1&lt;br /&gt;
&lt;br /&gt;
==== Параметры общего назначения ====&lt;br /&gt;
Два параметра input и result_prefix отвечают за перечень входных и выходных растров. Модуль ожидает, что на вход ему будет передан список растров, перечисленных через запятую в порядке возрастания (или убывания) времени. Например:&lt;br /&gt;
  input=ndvi1,ndvi2,ndvi3,ndvi4,....&lt;br /&gt;
При этом временной ряд должен быть равноотстоящим, т.е. растры представляют собой измерения какой-либо величины (или состояния территории), сделанные через равные промежутки времени. Но на практике не всегда возможно иметь дело с равноотстоящими рядами, часть каких-либо измерений может отсутсвовать по объетивным причинам. В таком случае следует вставить пустой растр, состоящий из значений NULL (нет данных), который легко сгенерировать, воспользовавшись растровым калькулятором:&lt;br /&gt;
 r.mapcalc expression=&amp;quot;dummy = null()&amp;quot;&lt;br /&gt;
В самих растрах так же могут быть области, с отсутсвующими в них данными, такие участки не требуют специальной предварительной обработки.&lt;br /&gt;
&lt;br /&gt;
Перед началом расчетов такие пропущенные значения будут предварительно заполнены данными, полученными линейной интерполяцией (во времени, пространственная интерполяция не используется).&lt;br /&gt;
&lt;br /&gt;
Результаты будут записаны в новые растры, названия которых начинаются с указанного result_prefix. Например, в случае, если result_prefix=&amp;quot;res.&amp;quot;, будут получены растры: res.ndvi1,res.ndvi2,res.ndvi3,res.ndvi4,....&lt;br /&gt;
&lt;br /&gt;
Таким образом команда со значениями, заданными по умолчанию может выглядеть следующим образом:&lt;br /&gt;
 r.series.filter input=ndvi1,ndvi2,ndvi3,ndvi4,.... result_prefix=&amp;quot;res.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
==== Методы фильтрации ====&lt;br /&gt;
&lt;br /&gt;
На момент написания статьи в модуле реализовано два метода фильтрации:&lt;br /&gt;
* медианный фильтр (параметр method=median);&lt;br /&gt;
* фильтр Савицкого-Голея (method=savgol).&lt;br /&gt;
&lt;br /&gt;
Каждый из этих фильтров работает в скользящем окне и рассчитывает прогнозируемое значение исследуемой величины для центральной точки окна. Поэтому модуль использует еще один параметр winsize, задающий ширину скользящего окна. Этот параметр должен быть нечетным числом.&lt;br /&gt;
&lt;br /&gt;
Кроме того у метода Савцикого-Голея есть еще один параметр -- порядок полинома (order), который используется при аппроксимации временного ряда внутри скользящего окна.&lt;br /&gt;
&lt;br /&gt;
Естественно, что ширина окна и порядок полинома должны быть таковы, что позволят рассчитать коэффициенты полинома. В случае, если порядок полиома превышает допустимый для данной величины окна, будет выведено сообщение об ошибке.&lt;br /&gt;
&lt;br /&gt;
Например, для использования фильтра Савицкого-Голея с порядком полинома, равным трем, и шириной окна 17 отсчетов, нужно использовать следующую команду:&lt;br /&gt;
 r.series.filter input=.... result_prefix=... method=savgol order=3 wunsiz=17&lt;br /&gt;
&lt;br /&gt;
Иногда есть смысл применить последовательно сразу несколько итераций фильтрации (особенно это актуально для медианного фильтра): сначала произвести фильтрацию исходных данных, затем применить этот же фильтр к результам фильтрации и т.д. Поэтому пользователь может уаказать параметр iterations, отвечающий за число итераций, например:&lt;br /&gt;
 r.series.filter input=.... result_prefix=... method=median iterations=5 winsize=21&lt;br /&gt;
&lt;br /&gt;
==== Подбор оптимальных значений параметров ====&lt;br /&gt;
Часто бывает сложно понять, какие значения параметров являются &amp;quot;хорошими&amp;quot; для конкретного набора растров. &lt;br /&gt;
&lt;br /&gt;
Понятно, что эти величины зависят как и от форм анализируемых кривых, так и от целей исследователя, но в довольно обшем случае можно сказать, что качество подгонки может выражаться в виде некоторой функции от точности и &amp;quot;гладкости&amp;quot; результирующей кривой. Точность рассчитать легко как средний модуль разности между исходной кривой и результирующей, а гладкость можно оценить средним модулем разности между соседними значениями результирующей кривой. К сожалению, обычно бывает так, что гладкая и &amp;quot;красивая&amp;quot; кривая является слишком грубой и неточной, и наоборот -- точная кривая обычно повторяет все флуктуации в данных, в том числе и случайные шумы. Поэтому пользователь должен решить, что ему более важно, точность или гладкость.&lt;br /&gt;
&lt;br /&gt;
На этом строится процедура подбора параметров фильтрации: пользователь задает два числа -- штрафы за неточность и негладкость результирующей кривой (параметры модуля diff_penalty и deriv_penalty). Эти штрафы показывают, насколько пользователю важна точность в ущерб гладкости. Затем запускается процедура подбора параметров, работающая следующим образом:&lt;br /&gt;
# Выбираются начальные значения параметра ширины окна для медианного фильра (ширины окна и порядка полинома для фильтра Савицкого-Голея).&lt;br /&gt;
# Выбирается opt_points случайных пикселей.&lt;br /&gt;
# Для выбранных пикселей производится фильтрация с заданными параметрами.&lt;br /&gt;
# Для каждого выбранного пикселя вычилсяется E - средний модуль разности между исходной кривой и результирующей, а также D - средний модуль разности между соседними значениями результирующей кривой.&lt;br /&gt;
# Для каждого пикселя находится взвешенная сумма штрафов: diff_penalty * E + deriv_penalty * D, а затем расчитывается суммарный штраф по всем пикселям. Этот суммарный штраф является оценкой качества подгонки кривых для заданных параметров фильтра.&lt;br /&gt;
&lt;br /&gt;
Затем запускается процедура поиска таких параметров, при которых суммарный штраф будет минимальным. После нахождения таких параметров производится фильтрация всего временного растрового ряда.&lt;br /&gt;
&lt;br /&gt;
Процедура подбора параметров включается флагом &amp;quot;-c&amp;quot;, например:&lt;br /&gt;
 r.series.filter -с input=.... result_prefix=... method=median&lt;br /&gt;
&lt;br /&gt;
==== Фильтрация вегетационных индексов ====&lt;br /&gt;
Как отмечалось выше,  в статье &amp;quot;Chen J. et al. A simple method for reconstructing a high-quality NDVI time-series data set based on the Savitzky–Golay filter //Remote sensing of Environment. – 2004. – Т. 91. – №. 3. – С. 332-344.&amp;quot; предлагается метод фильтрации временных рядов вегетационных индексов, исходя из предположения, что атмосферные явления обычно занижают значения индексов. В исходной статье медод предлагался для фильра Савицкого-Голея, но с таким же успехом его можно применять и к другим фильтрам. Поэтому в модуле r.series.filter пользователь может включить флагом &amp;quot;-u&amp;quot; данную модификацию фильтра:&lt;br /&gt;
 r.series.filter -с input=.... result_prefix=... method=median winsize=15&lt;br /&gt;
Предлагаемый в статье метод является итерационным, он действует на постепенно уменьшающихся величинах ширины скользящего окна, поэтому параметр winsize в данном случае будет означать начальную ширину окна.&lt;br /&gt;
&lt;br /&gt;
Более подробно об функционировании фильтр см. в указанной выше статье.&lt;br /&gt;
&lt;br /&gt;
=== Примеры ===&lt;/div&gt;</summary>
		<author><name>KolesovDmitry</name></author>
	</entry>
	<entry>
		<id>https://wiki.gis-lab.info/index.php?title=%D0%9C%D0%BE%D0%B4%D1%83%D0%BB%D1%8C_r.series.filter_%D0%93%D0%98%D0%A1_GRASS&amp;diff=23451</id>
		<title>Модуль r.series.filter ГИС GRASS</title>
		<link rel="alternate" type="text/html" href="https://wiki.gis-lab.info/index.php?title=%D0%9C%D0%BE%D0%B4%D1%83%D0%BB%D1%8C_r.series.filter_%D0%93%D0%98%D0%A1_GRASS&amp;diff=23451"/>
		<updated>2015-12-21T21:28:27Z</updated>

		<summary type="html">&lt;p&gt;KolesovDmitry: /* Фильтрация вегетационных индексов */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Статья|Черновик}}&lt;br /&gt;
&lt;br /&gt;
{{NextGIS}}&lt;br /&gt;
&lt;br /&gt;
== Назначение модуля ==&lt;br /&gt;
Модуль r.series.filter -- это модуль для геоинформационной системы GRASS, предназначенный для обработки временных рядов растровых данных, в первую очередь вегетационных индексов. Модуль производит очистку от шумов временных рядов с использованием различных фильтров (медианый фильтр, [https://en.wikipedia.org/wiki/Savitzky%E2%80%93Golay_filter фильтр Савицкого-Голея]). Модуль может использоваться для очистки от шумов временных рядов произвольной природы, однако одной из важных особенностей модуля является поддерка фильтрации данных вегетационных индексов. Для обработки таких рядов модуль реализует процедуру фильтрации, предложенную в статье &amp;quot;Chen J. et al. A simple method for reconstructing a high-quality NDVI time-series data set based on the Savitzky–Golay filter //Remote sensing of Environment. – 2004. – Т. 91. – №. 3. – С. 332-344.&amp;quot;. Основная идея этого фильтра опирается на то, что шумы в значениях вегетационных индексов обычно индуцируются условиями съемки и атмосферными явлениями, которые занижают зачения индекса. В очень упрощенном виде можно сказать, что предлагаемая в указанной статье методика производит отбраковку низких значений индекса и производит фильтрацию по верхним значениям анализируемого временного ряда.&lt;br /&gt;
&lt;br /&gt;
== Установка ==&lt;br /&gt;
Модуль был написан на языке Python и предназначен для работы в GRASS GIS седьмой версии. В модуле используются библиотека [http://docs.scipy.org/doc/scipy/reference/signal.html scipy.signal], входящая в состав пакета [http://www.scipy.org/about.html SciPy]. Поэтому перед началом работы в интерпретатор Python, используемый в GRASS, следует установить SciPy.&lt;br /&gt;
&lt;br /&gt;
После установки SciPy появится возможность установить сам модуль r.series.filter. Данный модуль доступен в репозитории модулей GRASS ADDONS, поэтому его установка производится автоматически, если использовать модуль g.extension (вызываемый из графического интерфейса пользователя или командной строки). Например, можно использовать следущюую команду:&lt;br /&gt;
 g.extension r.series.filter&lt;br /&gt;
В результате модуль будет автоматически скачан из репозитория и установлен.&lt;br /&gt;
&lt;br /&gt;
== Особенности работы и примеры ==&lt;br /&gt;
&lt;br /&gt;
=== Параметры модуля и их назначение ===&lt;br /&gt;
Модуль находится в состоянии разработки, это означает, что в него будут добавляться новые возможности. На момент написания статьи модуль использует следующие параметры и ключи (показаны наиболее важные):&lt;br /&gt;
&lt;br /&gt;
 r.series.filter [-cu] input=string[,string,...] result_prefix=string&lt;br /&gt;
   [method=string] [winsize=value] [order=value] [opt_points=value]&lt;br /&gt;
   [diff_penalty=value] [deriv_penalty=value] [iterations=value]&lt;br /&gt;
 Flags:&lt;br /&gt;
   -c   Try to find optimal parameters for filtering&lt;br /&gt;
   -u   Fit the result curve by upper boundary&lt;br /&gt;
 Parameters:&lt;br /&gt;
          input   Raster names of equally spaced time series.&lt;br /&gt;
  result_prefix   Prefix for raster names of filtered X(t)&lt;br /&gt;
         method   Used method&lt;br /&gt;
                  default: savgol&lt;br /&gt;
        winsize   Length of running window for the filter&lt;br /&gt;
                  default: 9&lt;br /&gt;
          order   Order of the Savitzky-Golay filter&lt;br /&gt;
                  default: 2&lt;br /&gt;
     opt_points   Count of random points used for parameter optimization&lt;br /&gt;
                  default: 50&lt;br /&gt;
   diff_penalty   Penalty for difference between original and filtered signals&lt;br /&gt;
                  default: 1.0&lt;br /&gt;
  deriv_penalty   Penalty for big derivates of the filtered signal&lt;br /&gt;
                  default: 1.0&lt;br /&gt;
     iterations   Number of iterations&lt;br /&gt;
                  default: 1&lt;br /&gt;
&lt;br /&gt;
==== Параметры общего назначения ====&lt;br /&gt;
Два параметра input и result_prefix отвечают за перечень входных и выходных растров. Модуль ожидает, что на вход ему будет передан список растров, перечисленных через запятую в порядке возрастания (или убывания) времени. Например:&lt;br /&gt;
  input=ndvi1,ndvi2,ndvi3,ndvi4,....&lt;br /&gt;
При этом временной ряд должен быть равноотстоящим, т.е. растры представляют собой измерения какой-либо величины (или состояния территории), сделанные через равные промежутки времени. Но на практике не всегда возможно иметь дело с равноотстоящими рядами, часть каких-либо измерений может отсутсвовать по объетивным причинам. В таком случае следует вставить пустой растр, состоящий из значений NULL (нет данных), который легко сгенерировать, воспользовавшись растровым калькулятором:&lt;br /&gt;
 r.mapcalc expression=&amp;quot;dummy = null()&amp;quot;&lt;br /&gt;
В самих растрах так же могут быть области, с отсутсвующими в них данными, такие участки не требуют специальной предварительной обработки.&lt;br /&gt;
&lt;br /&gt;
Перед началом расчетов такие пропущенные значения будут предварительно заполнены данными, полученными линейной интерполяцией (во времени, пространственная интерполяция не используется).&lt;br /&gt;
&lt;br /&gt;
Результаты будут записаны в новые растры, названия которых начинаются с указанного result_prefix. Например, в случае, если result_prefix=&amp;quot;res.&amp;quot;, будут получены растры: res.ndvi1,res.ndvi2,res.ndvi3,res.ndvi4,....&lt;br /&gt;
&lt;br /&gt;
Таким образом команда со значениями, заданными по умолчанию может выглядеть следующим образом:&lt;br /&gt;
 r.series.filter input=ndvi1,ndvi2,ndvi3,ndvi4,.... result_prefix=&amp;quot;res.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
==== Методы фильтрации ====&lt;br /&gt;
&lt;br /&gt;
На момент написания статьи в модуле реализовано два метода фильтрации:&lt;br /&gt;
* медианный фильтр (параметр method=median);&lt;br /&gt;
* фильтр Савицкого-Голея (method=savgol).&lt;br /&gt;
&lt;br /&gt;
Каждый из этих фильтров работает в скользящем окне и рассчитывает прогнозируемое значение исследуемой величины для центральной точки окна. Поэтому модуль использует еще один параметр winsize, задающий ширину скользящего окна. Этот параметр должен быть нечетным числом.&lt;br /&gt;
&lt;br /&gt;
Кроме того у метода Савцикого-Голея есть еще один параметр -- порядок полинома (order), который используется при аппроксимации временного ряда внутри скользящего окна.&lt;br /&gt;
&lt;br /&gt;
Естественно, что ширина окна и порядок полинома должны быть таковы, что позволят рассчитать коэффициенты полинома. В случае, если порядок полиома превышает допустимый для данной величины окна, будет выведено сообщение об ошибке.&lt;br /&gt;
&lt;br /&gt;
Например, для использования фильтра Савицкого-Голея с порядком полинома, равным трем, и шириной окна 17 отсчетов, нужно использовать следующую команду:&lt;br /&gt;
 r.series.filter input=.... result_prefix=... method=savgol order=3 wunsiz=17&lt;br /&gt;
&lt;br /&gt;
Иногда есть смысл применить последовательно сразу несколько итераций фильтрации (особенно это актуально для медианного фильтра): сначала произвести фильтрацию исходных данных, затем применить этот же фильтр к результам фильтрации и т.д. Поэтому пользователь может уаказать параметр iterations, отвечающий за число итераций, например:&lt;br /&gt;
 r.series.filter input=.... result_prefix=... method=median iterations=5 winsize=21&lt;br /&gt;
&lt;br /&gt;
==== Подбор оптимальных значений параметров ====&lt;br /&gt;
Часто бывает сложно понять, какие значения параметров являются &amp;quot;хорошими&amp;quot; для конкретного набора растров. &lt;br /&gt;
&lt;br /&gt;
Понятно, что эти величины зависят как и от форм анализируемых кривых, так и от целей исследователя, но в довольно обшем случае можно сказать, что качество подгонки может выражаться в виде некоторой функции от точности и &amp;quot;гладкости&amp;quot; результирующей кривой. Точность рассчитать легко как средний модуль разности между исходной кривой и результирующей, а гладкость можно оценить средним модулем разности между соседними значениями результирующей кривой. К сожалению, обычно бывает так, что гладкая и &amp;quot;красивая&amp;quot; кривая является слишком грубой и неточной, и наоборот -- точная кривая обычно повторяет все флуктуации в данных, в том числе и случайные шумы. Поэтому пользователь должен решить, что ему более важно, точность или гладкость.&lt;br /&gt;
&lt;br /&gt;
На этом строится процедура подбора параметров фильтрации: пользователь задает два числа -- штрафы за неточность и негладкость результирующей кривой (параметры модуля diff_penalty и deriv_penalty). Эти штрафы показывают, насколько пользователю важна точность в ущерб гладкости. Затем запускается процедура подбора параметров, работающая следующим образом:&lt;br /&gt;
# Выбираются начальные значения параметра ширины окна для медианного фильра (ширины окна и порядка полинома для фильтра Савицкого-Голея).&lt;br /&gt;
# Выбирается opt_points случайных пикселей.&lt;br /&gt;
# Для выбранных пикселей производится фильтрация с заданными параметрами.&lt;br /&gt;
# Для каждого выбранного пикселя вычилсяется E - средний модуль разности между исходной кривой и результирующей, а также D - средний модуль разности между соседними значениями результирующей кривой.&lt;br /&gt;
# Для каждого пикселя находится взвешенная сумма штрафов: diff_penalty * E + deriv_penalty * D, а затем расчитывается суммарный штраф по всем пикселям. Этот суммарный штраф является оценкой качества подгонки кривых для заданных параметров фильтра.&lt;br /&gt;
&lt;br /&gt;
Затем запускается процедура поиска таких параметров, при которых суммарный штраф будет минимальным. После нахождения таких параметров производится фильтрация всего временного растрового ряда.&lt;br /&gt;
&lt;br /&gt;
Процедура подбора параметров включается флагом &amp;quot;-c&amp;quot;, например:&lt;br /&gt;
 r.series.filter -с input=.... result_prefix=... method=median&lt;br /&gt;
&lt;br /&gt;
==== Фильтрация вегетационных индексов ====&lt;br /&gt;
Как отмечалось выше,  в статье &amp;quot;Chen J. et al. A simple method for reconstructing a high-quality NDVI time-series data set based on the Savitzky–Golay filter //Remote sensing of Environment. – 2004. – Т. 91. – №. 3. – С. 332-344.&amp;quot; предлагается метод фильтрации временных рядов вегетационных индексов, исходя из предположения, что атмосферные явления обычно занижают значения индексов. В исходной статье медод предлагался для фильра Савицкого-Голея, но с таким же успехом его можно применять и к другим фильтрам. Поэтому в модуле r.series.filter пользователь может включить флагом &amp;quot;-u&amp;quot; данную модификацию фильтра:&lt;br /&gt;
 r.series.filter -с input=.... result_prefix=... method=median winsize=15&lt;br /&gt;
Предлагаемый в статье метод является итерационным, он действует на постепенно уменьшающихся величинах ширины скользящего окна, поэтому параметр winsize в данном случае будет означать начальную ширину окна.&lt;br /&gt;
&lt;br /&gt;
Более подробно об функционировании фильтр см. в указанной выше статье.&lt;/div&gt;</summary>
		<author><name>KolesovDmitry</name></author>
	</entry>
	<entry>
		<id>https://wiki.gis-lab.info/index.php?title=%D0%9C%D0%BE%D0%B4%D1%83%D0%BB%D1%8C_r.series.filter_%D0%93%D0%98%D0%A1_GRASS&amp;diff=23450</id>
		<title>Модуль r.series.filter ГИС GRASS</title>
		<link rel="alternate" type="text/html" href="https://wiki.gis-lab.info/index.php?title=%D0%9C%D0%BE%D0%B4%D1%83%D0%BB%D1%8C_r.series.filter_%D0%93%D0%98%D0%A1_GRASS&amp;diff=23450"/>
		<updated>2015-12-21T21:26:40Z</updated>

		<summary type="html">&lt;p&gt;KolesovDmitry: /* Методы фильтрации */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Статья|Черновик}}&lt;br /&gt;
&lt;br /&gt;
{{NextGIS}}&lt;br /&gt;
&lt;br /&gt;
== Назначение модуля ==&lt;br /&gt;
Модуль r.series.filter -- это модуль для геоинформационной системы GRASS, предназначенный для обработки временных рядов растровых данных, в первую очередь вегетационных индексов. Модуль производит очистку от шумов временных рядов с использованием различных фильтров (медианый фильтр, [https://en.wikipedia.org/wiki/Savitzky%E2%80%93Golay_filter фильтр Савицкого-Голея]). Модуль может использоваться для очистки от шумов временных рядов произвольной природы, однако одной из важных особенностей модуля является поддерка фильтрации данных вегетационных индексов. Для обработки таких рядов модуль реализует процедуру фильтрации, предложенную в статье &amp;quot;Chen J. et al. A simple method for reconstructing a high-quality NDVI time-series data set based on the Savitzky–Golay filter //Remote sensing of Environment. – 2004. – Т. 91. – №. 3. – С. 332-344.&amp;quot;. Основная идея этого фильтра опирается на то, что шумы в значениях вегетационных индексов обычно индуцируются условиями съемки и атмосферными явлениями, которые занижают зачения индекса. В очень упрощенном виде можно сказать, что предлагаемая в указанной статье методика производит отбраковку низких значений индекса и производит фильтрацию по верхним значениям анализируемого временного ряда.&lt;br /&gt;
&lt;br /&gt;
== Установка ==&lt;br /&gt;
Модуль был написан на языке Python и предназначен для работы в GRASS GIS седьмой версии. В модуле используются библиотека [http://docs.scipy.org/doc/scipy/reference/signal.html scipy.signal], входящая в состав пакета [http://www.scipy.org/about.html SciPy]. Поэтому перед началом работы в интерпретатор Python, используемый в GRASS, следует установить SciPy.&lt;br /&gt;
&lt;br /&gt;
После установки SciPy появится возможность установить сам модуль r.series.filter. Данный модуль доступен в репозитории модулей GRASS ADDONS, поэтому его установка производится автоматически, если использовать модуль g.extension (вызываемый из графического интерфейса пользователя или командной строки). Например, можно использовать следущюую команду:&lt;br /&gt;
 g.extension r.series.filter&lt;br /&gt;
В результате модуль будет автоматически скачан из репозитория и установлен.&lt;br /&gt;
&lt;br /&gt;
== Особенности работы и примеры ==&lt;br /&gt;
&lt;br /&gt;
=== Параметры модуля и их назначение ===&lt;br /&gt;
Модуль находится в состоянии разработки, это означает, что в него будут добавляться новые возможности. На момент написания статьи модуль использует следующие параметры и ключи (показаны наиболее важные):&lt;br /&gt;
&lt;br /&gt;
 r.series.filter [-cu] input=string[,string,...] result_prefix=string&lt;br /&gt;
   [method=string] [winsize=value] [order=value] [opt_points=value]&lt;br /&gt;
   [diff_penalty=value] [deriv_penalty=value] [iterations=value]&lt;br /&gt;
 Flags:&lt;br /&gt;
   -c   Try to find optimal parameters for filtering&lt;br /&gt;
   -u   Fit the result curve by upper boundary&lt;br /&gt;
 Parameters:&lt;br /&gt;
          input   Raster names of equally spaced time series.&lt;br /&gt;
  result_prefix   Prefix for raster names of filtered X(t)&lt;br /&gt;
         method   Used method&lt;br /&gt;
                  default: savgol&lt;br /&gt;
        winsize   Length of running window for the filter&lt;br /&gt;
                  default: 9&lt;br /&gt;
          order   Order of the Savitzky-Golay filter&lt;br /&gt;
                  default: 2&lt;br /&gt;
     opt_points   Count of random points used for parameter optimization&lt;br /&gt;
                  default: 50&lt;br /&gt;
   diff_penalty   Penalty for difference between original and filtered signals&lt;br /&gt;
                  default: 1.0&lt;br /&gt;
  deriv_penalty   Penalty for big derivates of the filtered signal&lt;br /&gt;
                  default: 1.0&lt;br /&gt;
     iterations   Number of iterations&lt;br /&gt;
                  default: 1&lt;br /&gt;
&lt;br /&gt;
==== Параметры общего назначения ====&lt;br /&gt;
Два параметра input и result_prefix отвечают за перечень входных и выходных растров. Модуль ожидает, что на вход ему будет передан список растров, перечисленных через запятую в порядке возрастания (или убывания) времени. Например:&lt;br /&gt;
  input=ndvi1,ndvi2,ndvi3,ndvi4,....&lt;br /&gt;
При этом временной ряд должен быть равноотстоящим, т.е. растры представляют собой измерения какой-либо величины (или состояния территории), сделанные через равные промежутки времени. Но на практике не всегда возможно иметь дело с равноотстоящими рядами, часть каких-либо измерений может отсутсвовать по объетивным причинам. В таком случае следует вставить пустой растр, состоящий из значений NULL (нет данных), который легко сгенерировать, воспользовавшись растровым калькулятором:&lt;br /&gt;
 r.mapcalc expression=&amp;quot;dummy = null()&amp;quot;&lt;br /&gt;
В самих растрах так же могут быть области, с отсутсвующими в них данными, такие участки не требуют специальной предварительной обработки.&lt;br /&gt;
&lt;br /&gt;
Перед началом расчетов такие пропущенные значения будут предварительно заполнены данными, полученными линейной интерполяцией (во времени, пространственная интерполяция не используется).&lt;br /&gt;
&lt;br /&gt;
Результаты будут записаны в новые растры, названия которых начинаются с указанного result_prefix. Например, в случае, если result_prefix=&amp;quot;res.&amp;quot;, будут получены растры: res.ndvi1,res.ndvi2,res.ndvi3,res.ndvi4,....&lt;br /&gt;
&lt;br /&gt;
Таким образом команда со значениями, заданными по умолчанию может выглядеть следующим образом:&lt;br /&gt;
 r.series.filter input=ndvi1,ndvi2,ndvi3,ndvi4,.... result_prefix=&amp;quot;res.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
==== Методы фильтрации ====&lt;br /&gt;
&lt;br /&gt;
На момент написания статьи в модуле реализовано два метода фильтрации:&lt;br /&gt;
* медианный фильтр (параметр method=median);&lt;br /&gt;
* фильтр Савицкого-Голея (method=savgol).&lt;br /&gt;
&lt;br /&gt;
Каждый из этих фильтров работает в скользящем окне и рассчитывает прогнозируемое значение исследуемой величины для центральной точки окна. Поэтому модуль использует еще один параметр winsize, задающий ширину скользящего окна. Этот параметр должен быть нечетным числом.&lt;br /&gt;
&lt;br /&gt;
Кроме того у метода Савцикого-Голея есть еще один параметр -- порядок полинома (order), который используется при аппроксимации временного ряда внутри скользящего окна.&lt;br /&gt;
&lt;br /&gt;
Естественно, что ширина окна и порядок полинома должны быть таковы, что позволят рассчитать коэффициенты полинома. В случае, если порядок полиома превышает допустимый для данной величины окна, будет выведено сообщение об ошибке.&lt;br /&gt;
&lt;br /&gt;
Например, для использования фильтра Савицкого-Голея с порядком полинома, равным трем, и шириной окна 17 отсчетов, нужно использовать следующую команду:&lt;br /&gt;
 r.series.filter input=.... result_prefix=... method=savgol order=3 wunsiz=17&lt;br /&gt;
&lt;br /&gt;
Иногда есть смысл применить последовательно сразу несколько итераций фильтрации (особенно это актуально для медианного фильтра): сначала произвести фильтрацию исходных данных, затем применить этот же фильтр к результам фильтрации и т.д. Поэтому пользователь может уаказать параметр iterations, отвечающий за число итераций, например:&lt;br /&gt;
 r.series.filter input=.... result_prefix=... method=median iterations=5 winsize=21&lt;br /&gt;
&lt;br /&gt;
==== Подбор оптимальных значений параметров ====&lt;br /&gt;
Часто бывает сложно понять, какие значения параметров являются &amp;quot;хорошими&amp;quot; для конкретного набора растров. &lt;br /&gt;
&lt;br /&gt;
Понятно, что эти величины зависят как и от форм анализируемых кривых, так и от целей исследователя, но в довольно обшем случае можно сказать, что качество подгонки может выражаться в виде некоторой функции от точности и &amp;quot;гладкости&amp;quot; результирующей кривой. Точность рассчитать легко как средний модуль разности между исходной кривой и результирующей, а гладкость можно оценить средним модулем разности между соседними значениями результирующей кривой. К сожалению, обычно бывает так, что гладкая и &amp;quot;красивая&amp;quot; кривая является слишком грубой и неточной, и наоборот -- точная кривая обычно повторяет все флуктуации в данных, в том числе и случайные шумы. Поэтому пользователь должен решить, что ему более важно, точность или гладкость.&lt;br /&gt;
&lt;br /&gt;
На этом строится процедура подбора параметров фильтрации: пользователь задает два числа -- штрафы за неточность и негладкость результирующей кривой (параметры модуля diff_penalty и deriv_penalty). Эти штрафы показывают, насколько пользователю важна точность в ущерб гладкости. Затем запускается процедура подбора параметров, работающая следующим образом:&lt;br /&gt;
# Выбираются начальные значения параметра ширины окна для медианного фильра (ширины окна и порядка полинома для фильтра Савицкого-Голея).&lt;br /&gt;
# Выбирается opt_points случайных пикселей.&lt;br /&gt;
# Для выбранных пикселей производится фильтрация с заданными параметрами.&lt;br /&gt;
# Для каждого выбранного пикселя вычилсяется E - средний модуль разности между исходной кривой и результирующей, а также D - средний модуль разности между соседними значениями результирующей кривой.&lt;br /&gt;
# Для каждого пикселя находится взвешенная сумма штрафов: diff_penalty * E + deriv_penalty * D, а затем расчитывается суммарный штраф по всем пикселям. Этот суммарный штраф является оценкой качества подгонки кривых для заданных параметров фильтра.&lt;br /&gt;
&lt;br /&gt;
Затем запускается процедура поиска таких параметров, при которых суммарный штраф будет минимальным. После нахождения таких параметров производится фильтрация всего временного растрового ряда.&lt;br /&gt;
&lt;br /&gt;
Процедура подбора параметров включается флагом &amp;quot;-c&amp;quot;, например:&lt;br /&gt;
 r.series.filter -с input=.... result_prefix=... method=median&lt;br /&gt;
&lt;br /&gt;
==== Фильтрация вегетационных индексов ====&lt;br /&gt;
Как отмечалось выше,  в статье &amp;quot;Chen J. et al. A simple method for reconstructing a high-quality NDVI time-series data set based on the Savitzky–Golay filter //Remote sensing of Environment. – 2004. – Т. 91. – №. 3. – С. 332-344.&amp;quot; предлагается метод фильтрации временных рядов вегетационных индексов, исходя из предположения, что атмосферные явления обычно занижают значения индексов. В исходной статье медод предлагался для фильра Савицкого-Голея, но с таким же успехом его можно применять и к другим фильтрам. Поэтому в модуле r.series.filter пользователь может включить флагом &amp;quot;-u&amp;quot; данную модификацию фильтра:&lt;br /&gt;
 r.series.filter -с input=.... result_prefix=... method=median winsize=15&lt;br /&gt;
Предлагаемый в статье метод является итерационным, он действует на постепенно уменьшающихся величинах ширины скользящего окна.&lt;/div&gt;</summary>
		<author><name>KolesovDmitry</name></author>
	</entry>
	<entry>
		<id>https://wiki.gis-lab.info/index.php?title=%D0%9C%D0%BE%D0%B4%D1%83%D0%BB%D1%8C_r.series.filter_%D0%93%D0%98%D0%A1_GRASS&amp;diff=23449</id>
		<title>Модуль r.series.filter ГИС GRASS</title>
		<link rel="alternate" type="text/html" href="https://wiki.gis-lab.info/index.php?title=%D0%9C%D0%BE%D0%B4%D1%83%D0%BB%D1%8C_r.series.filter_%D0%93%D0%98%D0%A1_GRASS&amp;diff=23449"/>
		<updated>2015-12-21T21:18:37Z</updated>

		<summary type="html">&lt;p&gt;KolesovDmitry: /* Фильтрация вегетационных индексов */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Статья|Черновик}}&lt;br /&gt;
&lt;br /&gt;
{{NextGIS}}&lt;br /&gt;
&lt;br /&gt;
== Назначение модуля ==&lt;br /&gt;
Модуль r.series.filter -- это модуль для геоинформационной системы GRASS, предназначенный для обработки временных рядов растровых данных, в первую очередь вегетационных индексов. Модуль производит очистку от шумов временных рядов с использованием различных фильтров (медианый фильтр, [https://en.wikipedia.org/wiki/Savitzky%E2%80%93Golay_filter фильтр Савицкого-Голея]). Модуль может использоваться для очистки от шумов временных рядов произвольной природы, однако одной из важных особенностей модуля является поддерка фильтрации данных вегетационных индексов. Для обработки таких рядов модуль реализует процедуру фильтрации, предложенную в статье &amp;quot;Chen J. et al. A simple method for reconstructing a high-quality NDVI time-series data set based on the Savitzky–Golay filter //Remote sensing of Environment. – 2004. – Т. 91. – №. 3. – С. 332-344.&amp;quot;. Основная идея этого фильтра опирается на то, что шумы в значениях вегетационных индексов обычно индуцируются условиями съемки и атмосферными явлениями, которые занижают зачения индекса. В очень упрощенном виде можно сказать, что предлагаемая в указанной статье методика производит отбраковку низких значений индекса и производит фильтрацию по верхним значениям анализируемого временного ряда.&lt;br /&gt;
&lt;br /&gt;
== Установка ==&lt;br /&gt;
Модуль был написан на языке Python и предназначен для работы в GRASS GIS седьмой версии. В модуле используются библиотека [http://docs.scipy.org/doc/scipy/reference/signal.html scipy.signal], входящая в состав пакета [http://www.scipy.org/about.html SciPy]. Поэтому перед началом работы в интерпретатор Python, используемый в GRASS, следует установить SciPy.&lt;br /&gt;
&lt;br /&gt;
После установки SciPy появится возможность установить сам модуль r.series.filter. Данный модуль доступен в репозитории модулей GRASS ADDONS, поэтому его установка производится автоматически, если использовать модуль g.extension (вызываемый из графического интерфейса пользователя или командной строки). Например, можно использовать следущюую команду:&lt;br /&gt;
 g.extension r.series.filter&lt;br /&gt;
В результате модуль будет автоматически скачан из репозитория и установлен.&lt;br /&gt;
&lt;br /&gt;
== Особенности работы и примеры ==&lt;br /&gt;
&lt;br /&gt;
=== Параметры модуля и их назначение ===&lt;br /&gt;
Модуль находится в состоянии разработки, это означает, что в него будут добавляться новые возможности. На момент написания статьи модуль использует следующие параметры и ключи (показаны наиболее важные):&lt;br /&gt;
&lt;br /&gt;
 r.series.filter [-cu] input=string[,string,...] result_prefix=string&lt;br /&gt;
   [method=string] [winsize=value] [order=value] [opt_points=value]&lt;br /&gt;
   [diff_penalty=value] [deriv_penalty=value] [iterations=value]&lt;br /&gt;
 Flags:&lt;br /&gt;
   -c   Try to find optimal parameters for filtering&lt;br /&gt;
   -u   Fit the result curve by upper boundary&lt;br /&gt;
 Parameters:&lt;br /&gt;
          input   Raster names of equally spaced time series.&lt;br /&gt;
  result_prefix   Prefix for raster names of filtered X(t)&lt;br /&gt;
         method   Used method&lt;br /&gt;
                  default: savgol&lt;br /&gt;
        winsize   Length of running window for the filter&lt;br /&gt;
                  default: 9&lt;br /&gt;
          order   Order of the Savitzky-Golay filter&lt;br /&gt;
                  default: 2&lt;br /&gt;
     opt_points   Count of random points used for parameter optimization&lt;br /&gt;
                  default: 50&lt;br /&gt;
   diff_penalty   Penalty for difference between original and filtered signals&lt;br /&gt;
                  default: 1.0&lt;br /&gt;
  deriv_penalty   Penalty for big derivates of the filtered signal&lt;br /&gt;
                  default: 1.0&lt;br /&gt;
     iterations   Number of iterations&lt;br /&gt;
                  default: 1&lt;br /&gt;
&lt;br /&gt;
==== Параметры общего назначения ====&lt;br /&gt;
Два параметра input и result_prefix отвечают за перечень входных и выходных растров. Модуль ожидает, что на вход ему будет передан список растров, перечисленных через запятую в порядке возрастания (или убывания) времени. Например:&lt;br /&gt;
  input=ndvi1,ndvi2,ndvi3,ndvi4,....&lt;br /&gt;
При этом временной ряд должен быть равноотстоящим, т.е. растры представляют собой измерения какой-либо величины (или состояния территории), сделанные через равные промежутки времени. Но на практике не всегда возможно иметь дело с равноотстоящими рядами, часть каких-либо измерений может отсутсвовать по объетивным причинам. В таком случае следует вставить пустой растр, состоящий из значений NULL (нет данных), который легко сгенерировать, воспользовавшись растровым калькулятором:&lt;br /&gt;
 r.mapcalc expression=&amp;quot;dummy = null()&amp;quot;&lt;br /&gt;
В самих растрах так же могут быть области, с отсутсвующими в них данными, такие участки не требуют специальной предварительной обработки.&lt;br /&gt;
&lt;br /&gt;
Перед началом расчетов такие пропущенные значения будут предварительно заполнены данными, полученными линейной интерполяцией (во времени, пространственная интерполяция не используется).&lt;br /&gt;
&lt;br /&gt;
Результаты будут записаны в новые растры, названия которых начинаются с указанного result_prefix. Например, в случае, если result_prefix=&amp;quot;res.&amp;quot;, будут получены растры: res.ndvi1,res.ndvi2,res.ndvi3,res.ndvi4,....&lt;br /&gt;
&lt;br /&gt;
Таким образом команда со значениями, заданными по умолчанию может выглядеть следующим образом:&lt;br /&gt;
 r.series.filter input=ndvi1,ndvi2,ndvi3,ndvi4,.... result_prefix=&amp;quot;res.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
==== Методы фильтрации ====&lt;br /&gt;
&lt;br /&gt;
На момент написания статьи в модуле реализовано два метода фильтрации:&lt;br /&gt;
* медианный фильтр (параметр method=median);&lt;br /&gt;
* фильтр Савицкого-Голея (method=savgol).&lt;br /&gt;
&lt;br /&gt;
Каждый из этих фильтров работает в скользящем окне и рассчитывает прогнозируемое значение исследуемой величины для центральной точки окна. Поэтому модуль использует еще один параметр winsize, задающий ширину скользящего окна. Этот параметр должен быть нечетным числом.&lt;br /&gt;
&lt;br /&gt;
Кроме того у метода Савцикого-Голея есть еще один параметр -- порядок полинома (order), который используется при аппроксимации временного ряда внутри скользящего окна.&lt;br /&gt;
&lt;br /&gt;
Естественно, что ширина окна и порядок полинома должны быть таковы, что позволят рассчитать коэффициенты полинома. В случае, если порядок полиома превышает допустимый для данной величины окна, будет выведено сообщение об ошибке.&lt;br /&gt;
&lt;br /&gt;
Например, для использования фильтра Савицкого-Голея с порядком полинома, равным трем, и шириной окна 17 отсчетов, нужно использовать следующую команду:&lt;br /&gt;
 r.series.filter input=.... result_prefix=... method=savgol order=3 wunsiz=17&lt;br /&gt;
&lt;br /&gt;
==== Подбор оптимальных значений параметров ====&lt;br /&gt;
Часто бывает сложно понять, какие значения параметров являются &amp;quot;хорошими&amp;quot; для конкретного набора растров. &lt;br /&gt;
&lt;br /&gt;
Понятно, что эти величины зависят как и от форм анализируемых кривых, так и от целей исследователя, но в довольно обшем случае можно сказать, что качество подгонки может выражаться в виде некоторой функции от точности и &amp;quot;гладкости&amp;quot; результирующей кривой. Точность рассчитать легко как средний модуль разности между исходной кривой и результирующей, а гладкость можно оценить средним модулем разности между соседними значениями результирующей кривой. К сожалению, обычно бывает так, что гладкая и &amp;quot;красивая&amp;quot; кривая является слишком грубой и неточной, и наоборот -- точная кривая обычно повторяет все флуктуации в данных, в том числе и случайные шумы. Поэтому пользователь должен решить, что ему более важно, точность или гладкость.&lt;br /&gt;
&lt;br /&gt;
На этом строится процедура подбора параметров фильтрации: пользователь задает два числа -- штрафы за неточность и негладкость результирующей кривой (параметры модуля diff_penalty и deriv_penalty). Эти штрафы показывают, насколько пользователю важна точность в ущерб гладкости. Затем запускается процедура подбора параметров, работающая следующим образом:&lt;br /&gt;
# Выбираются начальные значения параметра ширины окна для медианного фильра (ширины окна и порядка полинома для фильтра Савицкого-Голея).&lt;br /&gt;
# Выбирается opt_points случайных пикселей.&lt;br /&gt;
# Для выбранных пикселей производится фильтрация с заданными параметрами.&lt;br /&gt;
# Для каждого выбранного пикселя вычилсяется E - средний модуль разности между исходной кривой и результирующей, а также D - средний модуль разности между соседними значениями результирующей кривой.&lt;br /&gt;
# Для каждого пикселя находится взвешенная сумма штрафов: diff_penalty * E + deriv_penalty * D, а затем расчитывается суммарный штраф по всем пикселям. Этот суммарный штраф является оценкой качества подгонки кривых для заданных параметров фильтра.&lt;br /&gt;
&lt;br /&gt;
Затем запускается процедура поиска таких параметров, при которых суммарный штраф будет минимальным. После нахождения таких параметров производится фильтрация всего временного растрового ряда.&lt;br /&gt;
&lt;br /&gt;
Процедура подбора параметров включается флагом &amp;quot;-c&amp;quot;, например:&lt;br /&gt;
 r.series.filter -с input=.... result_prefix=... method=median&lt;br /&gt;
&lt;br /&gt;
==== Фильтрация вегетационных индексов ====&lt;br /&gt;
Как отмечалось выше,  в статье &amp;quot;Chen J. et al. A simple method for reconstructing a high-quality NDVI time-series data set based on the Savitzky–Golay filter //Remote sensing of Environment. – 2004. – Т. 91. – №. 3. – С. 332-344.&amp;quot; предлагается метод фильтрации временных рядов вегетационных индексов, исходя из предположения, что атмосферные явления обычно занижают значения индексов. В исходной статье медод предлагался для фильра Савицкого-Голея, но с таким же успехом его можно применять и к другим фильтрам. Поэтому в модуле r.series.filter пользователь может включить флагом &amp;quot;-u&amp;quot; данную модификацию фильтра:&lt;br /&gt;
 r.series.filter -с input=.... result_prefix=... method=median winsize=15&lt;br /&gt;
Предлагаемый в статье метод является итерационным, он действует на постепенно уменьшающихся величинах ширины скользящего окна.&lt;/div&gt;</summary>
		<author><name>KolesovDmitry</name></author>
	</entry>
	<entry>
		<id>https://wiki.gis-lab.info/index.php?title=%D0%9C%D0%BE%D0%B4%D1%83%D0%BB%D1%8C_r.series.filter_%D0%93%D0%98%D0%A1_GRASS&amp;diff=23448</id>
		<title>Модуль r.series.filter ГИС GRASS</title>
		<link rel="alternate" type="text/html" href="https://wiki.gis-lab.info/index.php?title=%D0%9C%D0%BE%D0%B4%D1%83%D0%BB%D1%8C_r.series.filter_%D0%93%D0%98%D0%A1_GRASS&amp;diff=23448"/>
		<updated>2015-12-21T21:10:59Z</updated>

		<summary type="html">&lt;p&gt;KolesovDmitry: /* Подбор оптимальных значений параметров */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Статья|Черновик}}&lt;br /&gt;
&lt;br /&gt;
{{NextGIS}}&lt;br /&gt;
&lt;br /&gt;
== Назначение модуля ==&lt;br /&gt;
Модуль r.series.filter -- это модуль для геоинформационной системы GRASS, предназначенный для обработки временных рядов растровых данных, в первую очередь вегетационных индексов. Модуль производит очистку от шумов временных рядов с использованием различных фильтров (медианый фильтр, [https://en.wikipedia.org/wiki/Savitzky%E2%80%93Golay_filter фильтр Савицкого-Голея]). Модуль может использоваться для очистки от шумов временных рядов произвольной природы, однако одной из важных особенностей модуля является поддерка фильтрации данных вегетационных индексов. Для обработки таких рядов модуль реализует процедуру фильтрации, предложенную в статье &amp;quot;Chen J. et al. A simple method for reconstructing a high-quality NDVI time-series data set based on the Savitzky–Golay filter //Remote sensing of Environment. – 2004. – Т. 91. – №. 3. – С. 332-344.&amp;quot;. Основная идея этого фильтра опирается на то, что шумы в значениях вегетационных индексов обычно индуцируются условиями съемки и атмосферными явлениями, которые занижают зачения индекса. В очень упрощенном виде можно сказать, что предлагаемая в указанной статье методика производит отбраковку низких значений индекса и производит фильтрацию по верхним значениям анализируемого временного ряда.&lt;br /&gt;
&lt;br /&gt;
== Установка ==&lt;br /&gt;
Модуль был написан на языке Python и предназначен для работы в GRASS GIS седьмой версии. В модуле используются библиотека [http://docs.scipy.org/doc/scipy/reference/signal.html scipy.signal], входящая в состав пакета [http://www.scipy.org/about.html SciPy]. Поэтому перед началом работы в интерпретатор Python, используемый в GRASS, следует установить SciPy.&lt;br /&gt;
&lt;br /&gt;
После установки SciPy появится возможность установить сам модуль r.series.filter. Данный модуль доступен в репозитории модулей GRASS ADDONS, поэтому его установка производится автоматически, если использовать модуль g.extension (вызываемый из графического интерфейса пользователя или командной строки). Например, можно использовать следущюую команду:&lt;br /&gt;
 g.extension r.series.filter&lt;br /&gt;
В результате модуль будет автоматически скачан из репозитория и установлен.&lt;br /&gt;
&lt;br /&gt;
== Особенности работы и примеры ==&lt;br /&gt;
&lt;br /&gt;
=== Параметры модуля и их назначение ===&lt;br /&gt;
Модуль находится в состоянии разработки, это означает, что в него будут добавляться новые возможности. На момент написания статьи модуль использует следующие параметры и ключи (показаны наиболее важные):&lt;br /&gt;
&lt;br /&gt;
 r.series.filter [-cu] input=string[,string,...] result_prefix=string&lt;br /&gt;
   [method=string] [winsize=value] [order=value] [opt_points=value]&lt;br /&gt;
   [diff_penalty=value] [deriv_penalty=value] [iterations=value]&lt;br /&gt;
 Flags:&lt;br /&gt;
   -c   Try to find optimal parameters for filtering&lt;br /&gt;
   -u   Fit the result curve by upper boundary&lt;br /&gt;
 Parameters:&lt;br /&gt;
          input   Raster names of equally spaced time series.&lt;br /&gt;
  result_prefix   Prefix for raster names of filtered X(t)&lt;br /&gt;
         method   Used method&lt;br /&gt;
                  default: savgol&lt;br /&gt;
        winsize   Length of running window for the filter&lt;br /&gt;
                  default: 9&lt;br /&gt;
          order   Order of the Savitzky-Golay filter&lt;br /&gt;
                  default: 2&lt;br /&gt;
     opt_points   Count of random points used for parameter optimization&lt;br /&gt;
                  default: 50&lt;br /&gt;
   diff_penalty   Penalty for difference between original and filtered signals&lt;br /&gt;
                  default: 1.0&lt;br /&gt;
  deriv_penalty   Penalty for big derivates of the filtered signal&lt;br /&gt;
                  default: 1.0&lt;br /&gt;
     iterations   Number of iterations&lt;br /&gt;
                  default: 1&lt;br /&gt;
&lt;br /&gt;
==== Параметры общего назначения ====&lt;br /&gt;
Два параметра input и result_prefix отвечают за перечень входных и выходных растров. Модуль ожидает, что на вход ему будет передан список растров, перечисленных через запятую в порядке возрастания (или убывания) времени. Например:&lt;br /&gt;
  input=ndvi1,ndvi2,ndvi3,ndvi4,....&lt;br /&gt;
При этом временной ряд должен быть равноотстоящим, т.е. растры представляют собой измерения какой-либо величины (или состояния территории), сделанные через равные промежутки времени. Но на практике не всегда возможно иметь дело с равноотстоящими рядами, часть каких-либо измерений может отсутсвовать по объетивным причинам. В таком случае следует вставить пустой растр, состоящий из значений NULL (нет данных), который легко сгенерировать, воспользовавшись растровым калькулятором:&lt;br /&gt;
 r.mapcalc expression=&amp;quot;dummy = null()&amp;quot;&lt;br /&gt;
В самих растрах так же могут быть области, с отсутсвующими в них данными, такие участки не требуют специальной предварительной обработки.&lt;br /&gt;
&lt;br /&gt;
Перед началом расчетов такие пропущенные значения будут предварительно заполнены данными, полученными линейной интерполяцией (во времени, пространственная интерполяция не используется).&lt;br /&gt;
&lt;br /&gt;
Результаты будут записаны в новые растры, названия которых начинаются с указанного result_prefix. Например, в случае, если result_prefix=&amp;quot;res.&amp;quot;, будут получены растры: res.ndvi1,res.ndvi2,res.ndvi3,res.ndvi4,....&lt;br /&gt;
&lt;br /&gt;
Таким образом команда со значениями, заданными по умолчанию может выглядеть следующим образом:&lt;br /&gt;
 r.series.filter input=ndvi1,ndvi2,ndvi3,ndvi4,.... result_prefix=&amp;quot;res.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
==== Методы фильтрации ====&lt;br /&gt;
&lt;br /&gt;
На момент написания статьи в модуле реализовано два метода фильтрации:&lt;br /&gt;
* медианный фильтр (параметр method=median);&lt;br /&gt;
* фильтр Савицкого-Голея (method=savgol).&lt;br /&gt;
&lt;br /&gt;
Каждый из этих фильтров работает в скользящем окне и рассчитывает прогнозируемое значение исследуемой величины для центральной точки окна. Поэтому модуль использует еще один параметр winsize, задающий ширину скользящего окна. Этот параметр должен быть нечетным числом.&lt;br /&gt;
&lt;br /&gt;
Кроме того у метода Савцикого-Голея есть еще один параметр -- порядок полинома (order), который используется при аппроксимации временного ряда внутри скользящего окна.&lt;br /&gt;
&lt;br /&gt;
Естественно, что ширина окна и порядок полинома должны быть таковы, что позволят рассчитать коэффициенты полинома. В случае, если порядок полиома превышает допустимый для данной величины окна, будет выведено сообщение об ошибке.&lt;br /&gt;
&lt;br /&gt;
Например, для использования фильтра Савицкого-Голея с порядком полинома, равным трем, и шириной окна 17 отсчетов, нужно использовать следующую команду:&lt;br /&gt;
 r.series.filter input=.... result_prefix=... method=savgol order=3 wunsiz=17&lt;br /&gt;
&lt;br /&gt;
==== Подбор оптимальных значений параметров ====&lt;br /&gt;
Часто бывает сложно понять, какие значения параметров являются &amp;quot;хорошими&amp;quot; для конкретного набора растров. &lt;br /&gt;
&lt;br /&gt;
Понятно, что эти величины зависят как и от форм анализируемых кривых, так и от целей исследователя, но в довольно обшем случае можно сказать, что качество подгонки может выражаться в виде некоторой функции от точности и &amp;quot;гладкости&amp;quot; результирующей кривой. Точность рассчитать легко как средний модуль разности между исходной кривой и результирующей, а гладкость можно оценить средним модулем разности между соседними значениями результирующей кривой. К сожалению, обычно бывает так, что гладкая и &amp;quot;красивая&amp;quot; кривая является слишком грубой и неточной, и наоборот -- точная кривая обычно повторяет все флуктуации в данных, в том числе и случайные шумы. Поэтому пользователь должен решить, что ему более важно, точность или гладкость.&lt;br /&gt;
&lt;br /&gt;
На этом строится процедура подбора параметров фильтрации: пользователь задает два числа -- штрафы за неточность и негладкость результирующей кривой (параметры модуля diff_penalty и deriv_penalty). Эти штрафы показывают, насколько пользователю важна точность в ущерб гладкости. Затем запускается процедура подбора параметров, работающая следующим образом:&lt;br /&gt;
# Выбираются начальные значения параметра ширины окна для медианного фильра (ширины окна и порядка полинома для фильтра Савицкого-Голея).&lt;br /&gt;
# Выбирается opt_points случайных пикселей.&lt;br /&gt;
# Для выбранных пикселей производится фильтрация с заданными параметрами.&lt;br /&gt;
# Для каждого выбранного пикселя вычилсяется E - средний модуль разности между исходной кривой и результирующей, а также D - средний модуль разности между соседними значениями результирующей кривой.&lt;br /&gt;
# Для каждого пикселя находится взвешенная сумма штрафов: diff_penalty * E + deriv_penalty * D, а затем расчитывается суммарный штраф по всем пикселям. Этот суммарный штраф является оценкой качества подгонки кривых для заданных параметров фильтра.&lt;br /&gt;
&lt;br /&gt;
Затем запускается процедура поиска таких параметров, при которых суммарный штраф будет минимальным. После нахождения таких параметров производится фильтрация всего временного растрового ряда.&lt;br /&gt;
&lt;br /&gt;
Процедура подбора параметров включается флагом &amp;quot;-c&amp;quot;, например:&lt;br /&gt;
 r.series.filter -с input=.... result_prefix=... method=median&lt;br /&gt;
&lt;br /&gt;
==== Фильтрация вегетационных индексов ====&lt;/div&gt;</summary>
		<author><name>KolesovDmitry</name></author>
	</entry>
	<entry>
		<id>https://wiki.gis-lab.info/index.php?title=%D0%9C%D0%BE%D0%B4%D1%83%D0%BB%D1%8C_r.series.filter_%D0%93%D0%98%D0%A1_GRASS&amp;diff=23447</id>
		<title>Модуль r.series.filter ГИС GRASS</title>
		<link rel="alternate" type="text/html" href="https://wiki.gis-lab.info/index.php?title=%D0%9C%D0%BE%D0%B4%D1%83%D0%BB%D1%8C_r.series.filter_%D0%93%D0%98%D0%A1_GRASS&amp;diff=23447"/>
		<updated>2015-12-21T21:10:08Z</updated>

		<summary type="html">&lt;p&gt;KolesovDmitry: /* Подбор оптимальных значений параметров */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Статья|Черновик}}&lt;br /&gt;
&lt;br /&gt;
{{NextGIS}}&lt;br /&gt;
&lt;br /&gt;
== Назначение модуля ==&lt;br /&gt;
Модуль r.series.filter -- это модуль для геоинформационной системы GRASS, предназначенный для обработки временных рядов растровых данных, в первую очередь вегетационных индексов. Модуль производит очистку от шумов временных рядов с использованием различных фильтров (медианый фильтр, [https://en.wikipedia.org/wiki/Savitzky%E2%80%93Golay_filter фильтр Савицкого-Голея]). Модуль может использоваться для очистки от шумов временных рядов произвольной природы, однако одной из важных особенностей модуля является поддерка фильтрации данных вегетационных индексов. Для обработки таких рядов модуль реализует процедуру фильтрации, предложенную в статье &amp;quot;Chen J. et al. A simple method for reconstructing a high-quality NDVI time-series data set based on the Savitzky–Golay filter //Remote sensing of Environment. – 2004. – Т. 91. – №. 3. – С. 332-344.&amp;quot;. Основная идея этого фильтра опирается на то, что шумы в значениях вегетационных индексов обычно индуцируются условиями съемки и атмосферными явлениями, которые занижают зачения индекса. В очень упрощенном виде можно сказать, что предлагаемая в указанной статье методика производит отбраковку низких значений индекса и производит фильтрацию по верхним значениям анализируемого временного ряда.&lt;br /&gt;
&lt;br /&gt;
== Установка ==&lt;br /&gt;
Модуль был написан на языке Python и предназначен для работы в GRASS GIS седьмой версии. В модуле используются библиотека [http://docs.scipy.org/doc/scipy/reference/signal.html scipy.signal], входящая в состав пакета [http://www.scipy.org/about.html SciPy]. Поэтому перед началом работы в интерпретатор Python, используемый в GRASS, следует установить SciPy.&lt;br /&gt;
&lt;br /&gt;
После установки SciPy появится возможность установить сам модуль r.series.filter. Данный модуль доступен в репозитории модулей GRASS ADDONS, поэтому его установка производится автоматически, если использовать модуль g.extension (вызываемый из графического интерфейса пользователя или командной строки). Например, можно использовать следущюую команду:&lt;br /&gt;
 g.extension r.series.filter&lt;br /&gt;
В результате модуль будет автоматически скачан из репозитория и установлен.&lt;br /&gt;
&lt;br /&gt;
== Особенности работы и примеры ==&lt;br /&gt;
&lt;br /&gt;
=== Параметры модуля и их назначение ===&lt;br /&gt;
Модуль находится в состоянии разработки, это означает, что в него будут добавляться новые возможности. На момент написания статьи модуль использует следующие параметры и ключи (показаны наиболее важные):&lt;br /&gt;
&lt;br /&gt;
 r.series.filter [-cu] input=string[,string,...] result_prefix=string&lt;br /&gt;
   [method=string] [winsize=value] [order=value] [opt_points=value]&lt;br /&gt;
   [diff_penalty=value] [deriv_penalty=value] [iterations=value]&lt;br /&gt;
 Flags:&lt;br /&gt;
   -c   Try to find optimal parameters for filtering&lt;br /&gt;
   -u   Fit the result curve by upper boundary&lt;br /&gt;
 Parameters:&lt;br /&gt;
          input   Raster names of equally spaced time series.&lt;br /&gt;
  result_prefix   Prefix for raster names of filtered X(t)&lt;br /&gt;
         method   Used method&lt;br /&gt;
                  default: savgol&lt;br /&gt;
        winsize   Length of running window for the filter&lt;br /&gt;
                  default: 9&lt;br /&gt;
          order   Order of the Savitzky-Golay filter&lt;br /&gt;
                  default: 2&lt;br /&gt;
     opt_points   Count of random points used for parameter optimization&lt;br /&gt;
                  default: 50&lt;br /&gt;
   diff_penalty   Penalty for difference between original and filtered signals&lt;br /&gt;
                  default: 1.0&lt;br /&gt;
  deriv_penalty   Penalty for big derivates of the filtered signal&lt;br /&gt;
                  default: 1.0&lt;br /&gt;
     iterations   Number of iterations&lt;br /&gt;
                  default: 1&lt;br /&gt;
&lt;br /&gt;
==== Параметры общего назначения ====&lt;br /&gt;
Два параметра input и result_prefix отвечают за перечень входных и выходных растров. Модуль ожидает, что на вход ему будет передан список растров, перечисленных через запятую в порядке возрастания (или убывания) времени. Например:&lt;br /&gt;
  input=ndvi1,ndvi2,ndvi3,ndvi4,....&lt;br /&gt;
При этом временной ряд должен быть равноотстоящим, т.е. растры представляют собой измерения какой-либо величины (или состояния территории), сделанные через равные промежутки времени. Но на практике не всегда возможно иметь дело с равноотстоящими рядами, часть каких-либо измерений может отсутсвовать по объетивным причинам. В таком случае следует вставить пустой растр, состоящий из значений NULL (нет данных), который легко сгенерировать, воспользовавшись растровым калькулятором:&lt;br /&gt;
 r.mapcalc expression=&amp;quot;dummy = null()&amp;quot;&lt;br /&gt;
В самих растрах так же могут быть области, с отсутсвующими в них данными, такие участки не требуют специальной предварительной обработки.&lt;br /&gt;
&lt;br /&gt;
Перед началом расчетов такие пропущенные значения будут предварительно заполнены данными, полученными линейной интерполяцией (во времени, пространственная интерполяция не используется).&lt;br /&gt;
&lt;br /&gt;
Результаты будут записаны в новые растры, названия которых начинаются с указанного result_prefix. Например, в случае, если result_prefix=&amp;quot;res.&amp;quot;, будут получены растры: res.ndvi1,res.ndvi2,res.ndvi3,res.ndvi4,....&lt;br /&gt;
&lt;br /&gt;
Таким образом команда со значениями, заданными по умолчанию может выглядеть следующим образом:&lt;br /&gt;
 r.series.filter input=ndvi1,ndvi2,ndvi3,ndvi4,.... result_prefix=&amp;quot;res.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
==== Методы фильтрации ====&lt;br /&gt;
&lt;br /&gt;
На момент написания статьи в модуле реализовано два метода фильтрации:&lt;br /&gt;
* медианный фильтр (параметр method=median);&lt;br /&gt;
* фильтр Савицкого-Голея (method=savgol).&lt;br /&gt;
&lt;br /&gt;
Каждый из этих фильтров работает в скользящем окне и рассчитывает прогнозируемое значение исследуемой величины для центральной точки окна. Поэтому модуль использует еще один параметр winsize, задающий ширину скользящего окна. Этот параметр должен быть нечетным числом.&lt;br /&gt;
&lt;br /&gt;
Кроме того у метода Савцикого-Голея есть еще один параметр -- порядок полинома (order), который используется при аппроксимации временного ряда внутри скользящего окна.&lt;br /&gt;
&lt;br /&gt;
Естественно, что ширина окна и порядок полинома должны быть таковы, что позволят рассчитать коэффициенты полинома. В случае, если порядок полиома превышает допустимый для данной величины окна, будет выведено сообщение об ошибке.&lt;br /&gt;
&lt;br /&gt;
Например, для использования фильтра Савицкого-Голея с порядком полинома, равным трем, и шириной окна 17 отсчетов, нужно использовать следующую команду:&lt;br /&gt;
 r.series.filter input=.... result_prefix=... method=savgol order=3 wunsiz=17&lt;br /&gt;
&lt;br /&gt;
==== Подбор оптимальных значений параметров ====&lt;br /&gt;
Часто бывает сложно понять, какие значения параметров являются &amp;quot;хорошими&amp;quot; для конкретного набора растров. &lt;br /&gt;
&lt;br /&gt;
Понятно, что эти величины зависят как и от форм анализируемых кривых, так и от целей исследователя, но в довольно обшем случае можно сказать, что качество подгонки может выражаться в виде некоторой функции от точности и &amp;quot;гладкости&amp;quot; результирующей кривой. Точность рассчитать легко как средний модуль разности между исходной кривой и результирующей, а гладкость можно оценить средним модулем разности между соседними значениями результирующей кривой. К сожалению, обычно бывает так, что гладкая и &amp;quot;красивая&amp;quot; кривая является слишком грубой и неточной, и наоборот -- точная кривая обычно повторяет все флуктуации в данных, в том числе и случайные шумы. Поэтому пользователь должен решить, что ему более важно, точность или гладкость.&lt;br /&gt;
&lt;br /&gt;
На этом строится процедура подбора параметров фильтрации: пользователь задает два числа -- штрафы за неточность и негладкость результирующей кривой (параметры модуля diff_penalty и deriv_penalty). Эти штрафы показывают, насколько пользователю важна точность в ущерб гладкости. Затем запускается процедура подбора параметров, работающая следующим образом:&lt;br /&gt;
# Выбираются начальные значения параметра ширины окна для медианного фильра (ширины окна и порядка полинома для фильтра Савицкого-Голея).&lt;br /&gt;
# Выбирается opt_points случайных пикселей.&lt;br /&gt;
# Для выбранных пикселей производится фильтрация с заданными параметрами.&lt;br /&gt;
# Для каждого выбранного пикселя вычилсяется E - средний модуль разности между исходной кривой и результирующей, а также D - средний модуль разности между соседними значениями результирующей кривой.&lt;br /&gt;
# Для каждого пикселя находится взвешенная сумма штрафов: diff_penalty * E + deriv_penalty * D, а затем расчитывается суммарный штраф по всем пикселям. Этот суммарный штраф является оценкой качества подгонки кривых для заданных параметров фильтра.&lt;br /&gt;
&lt;br /&gt;
Затем запускается процедура поиска таких параметров, при которых суммарный штраф будет минимальным. После нахождения таких параметров производится фильтрация всего временного растрового ряда.&lt;br /&gt;
&lt;br /&gt;
Процедура подбора параметров включается флагом -c, например:&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
==== Фильтрация вегетационных индексов ====&lt;/div&gt;</summary>
		<author><name>KolesovDmitry</name></author>
	</entry>
	<entry>
		<id>https://wiki.gis-lab.info/index.php?title=%D0%9C%D0%BE%D0%B4%D1%83%D0%BB%D1%8C_r.series.filter_%D0%93%D0%98%D0%A1_GRASS&amp;diff=23446</id>
		<title>Модуль r.series.filter ГИС GRASS</title>
		<link rel="alternate" type="text/html" href="https://wiki.gis-lab.info/index.php?title=%D0%9C%D0%BE%D0%B4%D1%83%D0%BB%D1%8C_r.series.filter_%D0%93%D0%98%D0%A1_GRASS&amp;diff=23446"/>
		<updated>2015-12-21T21:08:08Z</updated>

		<summary type="html">&lt;p&gt;KolesovDmitry: /* Подбор оптимальных значений параметров */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Статья|Черновик}}&lt;br /&gt;
&lt;br /&gt;
{{NextGIS}}&lt;br /&gt;
&lt;br /&gt;
== Назначение модуля ==&lt;br /&gt;
Модуль r.series.filter -- это модуль для геоинформационной системы GRASS, предназначенный для обработки временных рядов растровых данных, в первую очередь вегетационных индексов. Модуль производит очистку от шумов временных рядов с использованием различных фильтров (медианый фильтр, [https://en.wikipedia.org/wiki/Savitzky%E2%80%93Golay_filter фильтр Савицкого-Голея]). Модуль может использоваться для очистки от шумов временных рядов произвольной природы, однако одной из важных особенностей модуля является поддерка фильтрации данных вегетационных индексов. Для обработки таких рядов модуль реализует процедуру фильтрации, предложенную в статье &amp;quot;Chen J. et al. A simple method for reconstructing a high-quality NDVI time-series data set based on the Savitzky–Golay filter //Remote sensing of Environment. – 2004. – Т. 91. – №. 3. – С. 332-344.&amp;quot;. Основная идея этого фильтра опирается на то, что шумы в значениях вегетационных индексов обычно индуцируются условиями съемки и атмосферными явлениями, которые занижают зачения индекса. В очень упрощенном виде можно сказать, что предлагаемая в указанной статье методика производит отбраковку низких значений индекса и производит фильтрацию по верхним значениям анализируемого временного ряда.&lt;br /&gt;
&lt;br /&gt;
== Установка ==&lt;br /&gt;
Модуль был написан на языке Python и предназначен для работы в GRASS GIS седьмой версии. В модуле используются библиотека [http://docs.scipy.org/doc/scipy/reference/signal.html scipy.signal], входящая в состав пакета [http://www.scipy.org/about.html SciPy]. Поэтому перед началом работы в интерпретатор Python, используемый в GRASS, следует установить SciPy.&lt;br /&gt;
&lt;br /&gt;
После установки SciPy появится возможность установить сам модуль r.series.filter. Данный модуль доступен в репозитории модулей GRASS ADDONS, поэтому его установка производится автоматически, если использовать модуль g.extension (вызываемый из графического интерфейса пользователя или командной строки). Например, можно использовать следущюую команду:&lt;br /&gt;
 g.extension r.series.filter&lt;br /&gt;
В результате модуль будет автоматически скачан из репозитория и установлен.&lt;br /&gt;
&lt;br /&gt;
== Особенности работы и примеры ==&lt;br /&gt;
&lt;br /&gt;
=== Параметры модуля и их назначение ===&lt;br /&gt;
Модуль находится в состоянии разработки, это означает, что в него будут добавляться новые возможности. На момент написания статьи модуль использует следующие параметры и ключи (показаны наиболее важные):&lt;br /&gt;
&lt;br /&gt;
 r.series.filter [-cu] input=string[,string,...] result_prefix=string&lt;br /&gt;
   [method=string] [winsize=value] [order=value] [opt_points=value]&lt;br /&gt;
   [diff_penalty=value] [deriv_penalty=value] [iterations=value]&lt;br /&gt;
 Flags:&lt;br /&gt;
   -c   Try to find optimal parameters for filtering&lt;br /&gt;
   -u   Fit the result curve by upper boundary&lt;br /&gt;
 Parameters:&lt;br /&gt;
          input   Raster names of equally spaced time series.&lt;br /&gt;
  result_prefix   Prefix for raster names of filtered X(t)&lt;br /&gt;
         method   Used method&lt;br /&gt;
                  default: savgol&lt;br /&gt;
        winsize   Length of running window for the filter&lt;br /&gt;
                  default: 9&lt;br /&gt;
          order   Order of the Savitzky-Golay filter&lt;br /&gt;
                  default: 2&lt;br /&gt;
     opt_points   Count of random points used for parameter optimization&lt;br /&gt;
                  default: 50&lt;br /&gt;
   diff_penalty   Penalty for difference between original and filtered signals&lt;br /&gt;
                  default: 1.0&lt;br /&gt;
  deriv_penalty   Penalty for big derivates of the filtered signal&lt;br /&gt;
                  default: 1.0&lt;br /&gt;
     iterations   Number of iterations&lt;br /&gt;
                  default: 1&lt;br /&gt;
&lt;br /&gt;
==== Параметры общего назначения ====&lt;br /&gt;
Два параметра input и result_prefix отвечают за перечень входных и выходных растров. Модуль ожидает, что на вход ему будет передан список растров, перечисленных через запятую в порядке возрастания (или убывания) времени. Например:&lt;br /&gt;
  input=ndvi1,ndvi2,ndvi3,ndvi4,....&lt;br /&gt;
При этом временной ряд должен быть равноотстоящим, т.е. растры представляют собой измерения какой-либо величины (или состояния территории), сделанные через равные промежутки времени. Но на практике не всегда возможно иметь дело с равноотстоящими рядами, часть каких-либо измерений может отсутсвовать по объетивным причинам. В таком случае следует вставить пустой растр, состоящий из значений NULL (нет данных), который легко сгенерировать, воспользовавшись растровым калькулятором:&lt;br /&gt;
 r.mapcalc expression=&amp;quot;dummy = null()&amp;quot;&lt;br /&gt;
В самих растрах так же могут быть области, с отсутсвующими в них данными, такие участки не требуют специальной предварительной обработки.&lt;br /&gt;
&lt;br /&gt;
Перед началом расчетов такие пропущенные значения будут предварительно заполнены данными, полученными линейной интерполяцией (во времени, пространственная интерполяция не используется).&lt;br /&gt;
&lt;br /&gt;
Результаты будут записаны в новые растры, названия которых начинаются с указанного result_prefix. Например, в случае, если result_prefix=&amp;quot;res.&amp;quot;, будут получены растры: res.ndvi1,res.ndvi2,res.ndvi3,res.ndvi4,....&lt;br /&gt;
&lt;br /&gt;
Таким образом команда со значениями, заданными по умолчанию может выглядеть следующим образом:&lt;br /&gt;
 r.series.filter input=ndvi1,ndvi2,ndvi3,ndvi4,.... result_prefix=&amp;quot;res.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
==== Методы фильтрации ====&lt;br /&gt;
&lt;br /&gt;
На момент написания статьи в модуле реализовано два метода фильтрации:&lt;br /&gt;
* медианный фильтр (параметр method=median);&lt;br /&gt;
* фильтр Савицкого-Голея (method=savgol).&lt;br /&gt;
&lt;br /&gt;
Каждый из этих фильтров работает в скользящем окне и рассчитывает прогнозируемое значение исследуемой величины для центральной точки окна. Поэтому модуль использует еще один параметр winsize, задающий ширину скользящего окна. Этот параметр должен быть нечетным числом.&lt;br /&gt;
&lt;br /&gt;
Кроме того у метода Савцикого-Голея есть еще один параметр -- порядок полинома (order), который используется при аппроксимации временного ряда внутри скользящего окна.&lt;br /&gt;
&lt;br /&gt;
Естественно, что ширина окна и порядок полинома должны быть таковы, что позволят рассчитать коэффициенты полинома. В случае, если порядок полиома превышает допустимый для данной величины окна, будет выведено сообщение об ошибке.&lt;br /&gt;
&lt;br /&gt;
Например, для использования фильтра Савицкого-Голея с порядком полинома, равным трем, и шириной окна 17 отсчетов, нужно использовать следующую команду:&lt;br /&gt;
 r.series.filter input=.... result_prefix=... method=savgol order=3 wunsiz=17&lt;br /&gt;
&lt;br /&gt;
==== Подбор оптимальных значений параметров ====&lt;br /&gt;
Часто бывает сложно понять, какие значения параметров являются &amp;quot;хорошими&amp;quot; для конкретного набора растров. &lt;br /&gt;
&lt;br /&gt;
Понятно, что эти величины зависят как и от форм анализируемых кривых, так и от целей исследователя, но в довольно обшем случае можно сказать, что качество подгонки может выражаться в виде некоторой функции от точности и &amp;quot;гладкости&amp;quot; результирующей кривой. Точность рассчитать легко как средний модуль разности между исходной кривой и результирующей, а гладкость можно оценить средним модулем разности между соседними значениями результирующей кривой. К сожалению, обычно бывает так, что гладкая и &amp;quot;красивая&amp;quot; кривая является слишком грубой и неточной, и наоборот -- точная кривая обычно повторяет все флуктуации в данных, в том числе и случайные шумы. Поэтому пользователь должен решить, что ему более важно, точность или гладкость.&lt;br /&gt;
&lt;br /&gt;
На этом строится процедура подбора параметров фильтрации: пользователь задает два числа -- штрафы за неточность и негладкость результирующей кривой (параметры модуля diff_penalty и deriv_penalty). Эти штрафы показывают, насколько пользователю важна точность в ущерб гладкости. Затем запускается процедура подбора параметров, работающая следующим образом:&lt;br /&gt;
# Выбираются начальные значения параметра ширины окна для медианного фильра (ширины окна и порядка полинома для фильтра Савицкого-Голея).&lt;br /&gt;
# Выбирается opt_points случайных пикселей.&lt;br /&gt;
# Для выбранных пикселей производится фильтрация с заданными параметрами.&lt;br /&gt;
# Для каждого выбранного пикселя вычилсяется E - средний модуль разности между исходной кривой и результирующей, а также D - средний модуль разности между соседними значениями результирующей кривой.&lt;br /&gt;
# Для каждого пикселя находится взвешенная сумма штрафов: diff_penalty * E + deriv_penalty * D, а затем расчитывается суммарный штраф по всем пикселям. Этот суммарный штраф является оценкой качества подгонки кривых для заданных параметров фильтра.&lt;br /&gt;
&lt;br /&gt;
Затем запускается процедура поиска таких параметров, при которых суммарный штраф будет минимальным. После нахождения таких параметров производится фильтрация всего временного растрового ряда.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Большие значения diff_penalty будут&lt;/div&gt;</summary>
		<author><name>KolesovDmitry</name></author>
	</entry>
	<entry>
		<id>https://wiki.gis-lab.info/index.php?title=%D0%9C%D0%BE%D0%B4%D1%83%D0%BB%D1%8C_r.series.filter_%D0%93%D0%98%D0%A1_GRASS&amp;diff=23445</id>
		<title>Модуль r.series.filter ГИС GRASS</title>
		<link rel="alternate" type="text/html" href="https://wiki.gis-lab.info/index.php?title=%D0%9C%D0%BE%D0%B4%D1%83%D0%BB%D1%8C_r.series.filter_%D0%93%D0%98%D0%A1_GRASS&amp;diff=23445"/>
		<updated>2015-12-21T20:48:33Z</updated>

		<summary type="html">&lt;p&gt;KolesovDmitry: /* Подбор оптимальных значений параметров */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Статья|Черновик}}&lt;br /&gt;
&lt;br /&gt;
{{NextGIS}}&lt;br /&gt;
&lt;br /&gt;
== Назначение модуля ==&lt;br /&gt;
Модуль r.series.filter -- это модуль для геоинформационной системы GRASS, предназначенный для обработки временных рядов растровых данных, в первую очередь вегетационных индексов. Модуль производит очистку от шумов временных рядов с использованием различных фильтров (медианый фильтр, [https://en.wikipedia.org/wiki/Savitzky%E2%80%93Golay_filter фильтр Савицкого-Голея]). Модуль может использоваться для очистки от шумов временных рядов произвольной природы, однако одной из важных особенностей модуля является поддерка фильтрации данных вегетационных индексов. Для обработки таких рядов модуль реализует процедуру фильтрации, предложенную в статье &amp;quot;Chen J. et al. A simple method for reconstructing a high-quality NDVI time-series data set based on the Savitzky–Golay filter //Remote sensing of Environment. – 2004. – Т. 91. – №. 3. – С. 332-344.&amp;quot;. Основная идея этого фильтра опирается на то, что шумы в значениях вегетационных индексов обычно индуцируются условиями съемки и атмосферными явлениями, которые занижают зачения индекса. В очень упрощенном виде можно сказать, что предлагаемая в указанной статье методика производит отбраковку низких значений индекса и производит фильтрацию по верхним значениям анализируемого временного ряда.&lt;br /&gt;
&lt;br /&gt;
== Установка ==&lt;br /&gt;
Модуль был написан на языке Python и предназначен для работы в GRASS GIS седьмой версии. В модуле используются библиотека [http://docs.scipy.org/doc/scipy/reference/signal.html scipy.signal], входящая в состав пакета [http://www.scipy.org/about.html SciPy]. Поэтому перед началом работы в интерпретатор Python, используемый в GRASS, следует установить SciPy.&lt;br /&gt;
&lt;br /&gt;
После установки SciPy появится возможность установить сам модуль r.series.filter. Данный модуль доступен в репозитории модулей GRASS ADDONS, поэтому его установка производится автоматически, если использовать модуль g.extension (вызываемый из графического интерфейса пользователя или командной строки). Например, можно использовать следущюую команду:&lt;br /&gt;
 g.extension r.series.filter&lt;br /&gt;
В результате модуль будет автоматически скачан из репозитория и установлен.&lt;br /&gt;
&lt;br /&gt;
== Особенности работы и примеры ==&lt;br /&gt;
&lt;br /&gt;
=== Параметры модуля и их назначение ===&lt;br /&gt;
Модуль находится в состоянии разработки, это означает, что в него будут добавляться новые возможности. На момент написания статьи модуль использует следующие параметры и ключи (показаны наиболее важные):&lt;br /&gt;
&lt;br /&gt;
 r.series.filter [-cu] input=string[,string,...] result_prefix=string&lt;br /&gt;
   [method=string] [winsize=value] [order=value] [opt_points=value]&lt;br /&gt;
   [diff_penalty=value] [deriv_penalty=value] [iterations=value]&lt;br /&gt;
 Flags:&lt;br /&gt;
   -c   Try to find optimal parameters for filtering&lt;br /&gt;
   -u   Fit the result curve by upper boundary&lt;br /&gt;
 Parameters:&lt;br /&gt;
          input   Raster names of equally spaced time series.&lt;br /&gt;
  result_prefix   Prefix for raster names of filtered X(t)&lt;br /&gt;
         method   Used method&lt;br /&gt;
                  default: savgol&lt;br /&gt;
        winsize   Length of running window for the filter&lt;br /&gt;
                  default: 9&lt;br /&gt;
          order   Order of the Savitzky-Golay filter&lt;br /&gt;
                  default: 2&lt;br /&gt;
     opt_points   Count of random points used for parameter optimization&lt;br /&gt;
                  default: 50&lt;br /&gt;
   diff_penalty   Penalty for difference between original and filtered signals&lt;br /&gt;
                  default: 1.0&lt;br /&gt;
  deriv_penalty   Penalty for big derivates of the filtered signal&lt;br /&gt;
                  default: 1.0&lt;br /&gt;
     iterations   Number of iterations&lt;br /&gt;
                  default: 1&lt;br /&gt;
&lt;br /&gt;
==== Параметры общего назначения ====&lt;br /&gt;
Два параметра input и result_prefix отвечают за перечень входных и выходных растров. Модуль ожидает, что на вход ему будет передан список растров, перечисленных через запятую в порядке возрастания (или убывания) времени. Например:&lt;br /&gt;
  input=ndvi1,ndvi2,ndvi3,ndvi4,....&lt;br /&gt;
При этом временной ряд должен быть равноотстоящим, т.е. растры представляют собой измерения какой-либо величины (или состояния территории), сделанные через равные промежутки времени. Но на практике не всегда возможно иметь дело с равноотстоящими рядами, часть каких-либо измерений может отсутсвовать по объетивным причинам. В таком случае следует вставить пустой растр, состоящий из значений NULL (нет данных), который легко сгенерировать, воспользовавшись растровым калькулятором:&lt;br /&gt;
 r.mapcalc expression=&amp;quot;dummy = null()&amp;quot;&lt;br /&gt;
В самих растрах так же могут быть области, с отсутсвующими в них данными, такие участки не требуют специальной предварительной обработки.&lt;br /&gt;
&lt;br /&gt;
Перед началом расчетов такие пропущенные значения будут предварительно заполнены данными, полученными линейной интерполяцией (во времени, пространственная интерполяция не используется).&lt;br /&gt;
&lt;br /&gt;
Результаты будут записаны в новые растры, названия которых начинаются с указанного result_prefix. Например, в случае, если result_prefix=&amp;quot;res.&amp;quot;, будут получены растры: res.ndvi1,res.ndvi2,res.ndvi3,res.ndvi4,....&lt;br /&gt;
&lt;br /&gt;
Таким образом команда со значениями, заданными по умолчанию может выглядеть следующим образом:&lt;br /&gt;
 r.series.filter input=ndvi1,ndvi2,ndvi3,ndvi4,.... result_prefix=&amp;quot;res.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
==== Методы фильтрации ====&lt;br /&gt;
&lt;br /&gt;
На момент написания статьи в модуле реализовано два метода фильтрации:&lt;br /&gt;
* медианный фильтр (параметр method=median);&lt;br /&gt;
* фильтр Савицкого-Голея (method=savgol).&lt;br /&gt;
&lt;br /&gt;
Каждый из этих фильтров работает в скользящем окне и рассчитывает прогнозируемое значение исследуемой величины для центральной точки окна. Поэтому модуль использует еще один параметр winsize, задающий ширину скользящего окна. Этот параметр должен быть нечетным числом.&lt;br /&gt;
&lt;br /&gt;
Кроме того у метода Савцикого-Голея есть еще один параметр -- порядок полинома (order), который используется при аппроксимации временного ряда внутри скользящего окна.&lt;br /&gt;
&lt;br /&gt;
Естественно, что ширина окна и порядок полинома должны быть таковы, что позволят рассчитать коэффициенты полинома. В случае, если порядок полиома превышает допустимый для данной величины окна, будет выведено сообщение об ошибке.&lt;br /&gt;
&lt;br /&gt;
Например, для использования фильтра Савицкого-Голея с порядком полинома, равным трем, и шириной окна 17 отсчетов, нужно использовать следующую команду:&lt;br /&gt;
 r.series.filter input=.... result_prefix=... method=savgol order=3 wunsiz=17&lt;br /&gt;
&lt;br /&gt;
==== Подбор оптимальных значений параметров ====&lt;br /&gt;
Часто бывает сложно понять, какие значения параметров являются &amp;quot;хорошими&amp;quot; для конкретного набора растров. &lt;br /&gt;
&lt;br /&gt;
Понятно, что эти величины зависят как и от форм анализируемых кривых, так и от целей исследователя, но в довольно обшем случае можно сказать, что качество подгонки может выражаться в виде некоторой функции от точности и &amp;quot;гладкости&amp;quot; результирующей кривой. Точность рассчитать легко как средний модуль разности между исходной кривой и результирующей, а гладкость можно оценить средним модулем разности между соседними значениями результирующей кривой.&lt;br /&gt;
&lt;br /&gt;
На этом строится процедура подбора параметров фильтрации: пользователь задает два числа, которые показывают, насколько ему важна точность относительно гладкости кривой. Э&lt;/div&gt;</summary>
		<author><name>KolesovDmitry</name></author>
	</entry>
	<entry>
		<id>https://wiki.gis-lab.info/index.php?title=%D0%9C%D0%BE%D0%B4%D1%83%D0%BB%D1%8C_r.series.filter_%D0%93%D0%98%D0%A1_GRASS&amp;diff=23444</id>
		<title>Модуль r.series.filter ГИС GRASS</title>
		<link rel="alternate" type="text/html" href="https://wiki.gis-lab.info/index.php?title=%D0%9C%D0%BE%D0%B4%D1%83%D0%BB%D1%8C_r.series.filter_%D0%93%D0%98%D0%A1_GRASS&amp;diff=23444"/>
		<updated>2015-12-21T20:46:00Z</updated>

		<summary type="html">&lt;p&gt;KolesovDmitry: /* Методы фильтрации */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Статья|Черновик}}&lt;br /&gt;
&lt;br /&gt;
{{NextGIS}}&lt;br /&gt;
&lt;br /&gt;
== Назначение модуля ==&lt;br /&gt;
Модуль r.series.filter -- это модуль для геоинформационной системы GRASS, предназначенный для обработки временных рядов растровых данных, в первую очередь вегетационных индексов. Модуль производит очистку от шумов временных рядов с использованием различных фильтров (медианый фильтр, [https://en.wikipedia.org/wiki/Savitzky%E2%80%93Golay_filter фильтр Савицкого-Голея]). Модуль может использоваться для очистки от шумов временных рядов произвольной природы, однако одной из важных особенностей модуля является поддерка фильтрации данных вегетационных индексов. Для обработки таких рядов модуль реализует процедуру фильтрации, предложенную в статье &amp;quot;Chen J. et al. A simple method for reconstructing a high-quality NDVI time-series data set based on the Savitzky–Golay filter //Remote sensing of Environment. – 2004. – Т. 91. – №. 3. – С. 332-344.&amp;quot;. Основная идея этого фильтра опирается на то, что шумы в значениях вегетационных индексов обычно индуцируются условиями съемки и атмосферными явлениями, которые занижают зачения индекса. В очень упрощенном виде можно сказать, что предлагаемая в указанной статье методика производит отбраковку низких значений индекса и производит фильтрацию по верхним значениям анализируемого временного ряда.&lt;br /&gt;
&lt;br /&gt;
== Установка ==&lt;br /&gt;
Модуль был написан на языке Python и предназначен для работы в GRASS GIS седьмой версии. В модуле используются библиотека [http://docs.scipy.org/doc/scipy/reference/signal.html scipy.signal], входящая в состав пакета [http://www.scipy.org/about.html SciPy]. Поэтому перед началом работы в интерпретатор Python, используемый в GRASS, следует установить SciPy.&lt;br /&gt;
&lt;br /&gt;
После установки SciPy появится возможность установить сам модуль r.series.filter. Данный модуль доступен в репозитории модулей GRASS ADDONS, поэтому его установка производится автоматически, если использовать модуль g.extension (вызываемый из графического интерфейса пользователя или командной строки). Например, можно использовать следущюую команду:&lt;br /&gt;
 g.extension r.series.filter&lt;br /&gt;
В результате модуль будет автоматически скачан из репозитория и установлен.&lt;br /&gt;
&lt;br /&gt;
== Особенности работы и примеры ==&lt;br /&gt;
&lt;br /&gt;
=== Параметры модуля и их назначение ===&lt;br /&gt;
Модуль находится в состоянии разработки, это означает, что в него будут добавляться новые возможности. На момент написания статьи модуль использует следующие параметры и ключи (показаны наиболее важные):&lt;br /&gt;
&lt;br /&gt;
 r.series.filter [-cu] input=string[,string,...] result_prefix=string&lt;br /&gt;
   [method=string] [winsize=value] [order=value] [opt_points=value]&lt;br /&gt;
   [diff_penalty=value] [deriv_penalty=value] [iterations=value]&lt;br /&gt;
 Flags:&lt;br /&gt;
   -c   Try to find optimal parameters for filtering&lt;br /&gt;
   -u   Fit the result curve by upper boundary&lt;br /&gt;
 Parameters:&lt;br /&gt;
          input   Raster names of equally spaced time series.&lt;br /&gt;
  result_prefix   Prefix for raster names of filtered X(t)&lt;br /&gt;
         method   Used method&lt;br /&gt;
                  default: savgol&lt;br /&gt;
        winsize   Length of running window for the filter&lt;br /&gt;
                  default: 9&lt;br /&gt;
          order   Order of the Savitzky-Golay filter&lt;br /&gt;
                  default: 2&lt;br /&gt;
     opt_points   Count of random points used for parameter optimization&lt;br /&gt;
                  default: 50&lt;br /&gt;
   diff_penalty   Penalty for difference between original and filtered signals&lt;br /&gt;
                  default: 1.0&lt;br /&gt;
  deriv_penalty   Penalty for big derivates of the filtered signal&lt;br /&gt;
                  default: 1.0&lt;br /&gt;
     iterations   Number of iterations&lt;br /&gt;
                  default: 1&lt;br /&gt;
&lt;br /&gt;
==== Параметры общего назначения ====&lt;br /&gt;
Два параметра input и result_prefix отвечают за перечень входных и выходных растров. Модуль ожидает, что на вход ему будет передан список растров, перечисленных через запятую в порядке возрастания (или убывания) времени. Например:&lt;br /&gt;
  input=ndvi1,ndvi2,ndvi3,ndvi4,....&lt;br /&gt;
При этом временной ряд должен быть равноотстоящим, т.е. растры представляют собой измерения какой-либо величины (или состояния территории), сделанные через равные промежутки времени. Но на практике не всегда возможно иметь дело с равноотстоящими рядами, часть каких-либо измерений может отсутсвовать по объетивным причинам. В таком случае следует вставить пустой растр, состоящий из значений NULL (нет данных), который легко сгенерировать, воспользовавшись растровым калькулятором:&lt;br /&gt;
 r.mapcalc expression=&amp;quot;dummy = null()&amp;quot;&lt;br /&gt;
В самих растрах так же могут быть области, с отсутсвующими в них данными, такие участки не требуют специальной предварительной обработки.&lt;br /&gt;
&lt;br /&gt;
Перед началом расчетов такие пропущенные значения будут предварительно заполнены данными, полученными линейной интерполяцией (во времени, пространственная интерполяция не используется).&lt;br /&gt;
&lt;br /&gt;
Результаты будут записаны в новые растры, названия которых начинаются с указанного result_prefix. Например, в случае, если result_prefix=&amp;quot;res.&amp;quot;, будут получены растры: res.ndvi1,res.ndvi2,res.ndvi3,res.ndvi4,....&lt;br /&gt;
&lt;br /&gt;
Таким образом команда со значениями, заданными по умолчанию может выглядеть следующим образом:&lt;br /&gt;
 r.series.filter input=ndvi1,ndvi2,ndvi3,ndvi4,.... result_prefix=&amp;quot;res.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
==== Методы фильтрации ====&lt;br /&gt;
&lt;br /&gt;
На момент написания статьи в модуле реализовано два метода фильтрации:&lt;br /&gt;
* медианный фильтр (параметр method=median);&lt;br /&gt;
* фильтр Савицкого-Голея (method=savgol).&lt;br /&gt;
&lt;br /&gt;
Каждый из этих фильтров работает в скользящем окне и рассчитывает прогнозируемое значение исследуемой величины для центральной точки окна. Поэтому модуль использует еще один параметр winsize, задающий ширину скользящего окна. Этот параметр должен быть нечетным числом.&lt;br /&gt;
&lt;br /&gt;
Кроме того у метода Савцикого-Голея есть еще один параметр -- порядок полинома (order), который используется при аппроксимации временного ряда внутри скользящего окна.&lt;br /&gt;
&lt;br /&gt;
Естественно, что ширина окна и порядок полинома должны быть таковы, что позволят рассчитать коэффициенты полинома. В случае, если порядок полиома превышает допустимый для данной величины окна, будет выведено сообщение об ошибке.&lt;br /&gt;
&lt;br /&gt;
Например, для использования фильтра Савицкого-Голея с порядком полинома, равным трем, и шириной окна 17 отсчетов, нужно использовать следующую команду:&lt;br /&gt;
 r.series.filter input=.... result_prefix=... method=savgol order=3 wunsiz=17&lt;br /&gt;
&lt;br /&gt;
==== Подбор оптимальных значений параметров ====&lt;br /&gt;
Часто бывает сложно понять, какие значения параметров являются &amp;quot;хорошими&amp;quot; для конкретного набора растров. Понятно, что эти величины зависят как и от форм анализируемых кривых, так и от целей исследователя, но в довольно обшем случае можно сказать, что качество подгонки может выражаться в виде некоторой функции от точности и &amp;quot;гладкости&amp;quot; результирующей кривой. Точность рассчитать легко как средний модуль разности между исходной кривой и результирующей, а гладкость можно оценить средним модулем разности между соседними значениями результирующей кривой.&lt;/div&gt;</summary>
		<author><name>KolesovDmitry</name></author>
	</entry>
	<entry>
		<id>https://wiki.gis-lab.info/index.php?title=%D0%9C%D0%BE%D0%B4%D1%83%D0%BB%D1%8C_r.series.filter_%D0%93%D0%98%D0%A1_GRASS&amp;diff=23443</id>
		<title>Модуль r.series.filter ГИС GRASS</title>
		<link rel="alternate" type="text/html" href="https://wiki.gis-lab.info/index.php?title=%D0%9C%D0%BE%D0%B4%D1%83%D0%BB%D1%8C_r.series.filter_%D0%93%D0%98%D0%A1_GRASS&amp;diff=23443"/>
		<updated>2015-12-21T20:29:11Z</updated>

		<summary type="html">&lt;p&gt;KolesovDmitry: /* Методы фильтрации */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Статья|Черновик}}&lt;br /&gt;
&lt;br /&gt;
{{NextGIS}}&lt;br /&gt;
&lt;br /&gt;
== Назначение модуля ==&lt;br /&gt;
Модуль r.series.filter -- это модуль для геоинформационной системы GRASS, предназначенный для обработки временных рядов растровых данных, в первую очередь вегетационных индексов. Модуль производит очистку от шумов временных рядов с использованием различных фильтров (медианый фильтр, [https://en.wikipedia.org/wiki/Savitzky%E2%80%93Golay_filter фильтр Савицкого-Голея]). Модуль может использоваться для очистки от шумов временных рядов произвольной природы, однако одной из важных особенностей модуля является поддерка фильтрации данных вегетационных индексов. Для обработки таких рядов модуль реализует процедуру фильтрации, предложенную в статье &amp;quot;Chen J. et al. A simple method for reconstructing a high-quality NDVI time-series data set based on the Savitzky–Golay filter //Remote sensing of Environment. – 2004. – Т. 91. – №. 3. – С. 332-344.&amp;quot;. Основная идея этого фильтра опирается на то, что шумы в значениях вегетационных индексов обычно индуцируются условиями съемки и атмосферными явлениями, которые занижают зачения индекса. В очень упрощенном виде можно сказать, что предлагаемая в указанной статье методика производит отбраковку низких значений индекса и производит фильтрацию по верхним значениям анализируемого временного ряда.&lt;br /&gt;
&lt;br /&gt;
== Установка ==&lt;br /&gt;
Модуль был написан на языке Python и предназначен для работы в GRASS GIS седьмой версии. В модуле используются библиотека [http://docs.scipy.org/doc/scipy/reference/signal.html scipy.signal], входящая в состав пакета [http://www.scipy.org/about.html SciPy]. Поэтому перед началом работы в интерпретатор Python, используемый в GRASS, следует установить SciPy.&lt;br /&gt;
&lt;br /&gt;
После установки SciPy появится возможность установить сам модуль r.series.filter. Данный модуль доступен в репозитории модулей GRASS ADDONS, поэтому его установка производится автоматически, если использовать модуль g.extension (вызываемый из графического интерфейса пользователя или командной строки). Например, можно использовать следущюую команду:&lt;br /&gt;
 g.extension r.series.filter&lt;br /&gt;
В результате модуль будет автоматически скачан из репозитория и установлен.&lt;br /&gt;
&lt;br /&gt;
== Особенности работы и примеры ==&lt;br /&gt;
&lt;br /&gt;
=== Параметры модуля и их назначение ===&lt;br /&gt;
Модуль находится в состоянии разработки, это означает, что в него будут добавляться новые возможности. На момент написания статьи модуль использует следующие параметры и ключи (показаны наиболее важные):&lt;br /&gt;
&lt;br /&gt;
 r.series.filter [-cu] input=string[,string,...] result_prefix=string&lt;br /&gt;
   [method=string] [winsize=value] [order=value] [opt_points=value]&lt;br /&gt;
   [diff_penalty=value] [deriv_penalty=value] [iterations=value]&lt;br /&gt;
 Flags:&lt;br /&gt;
   -c   Try to find optimal parameters for filtering&lt;br /&gt;
   -u   Fit the result curve by upper boundary&lt;br /&gt;
 Parameters:&lt;br /&gt;
          input   Raster names of equally spaced time series.&lt;br /&gt;
  result_prefix   Prefix for raster names of filtered X(t)&lt;br /&gt;
         method   Used method&lt;br /&gt;
                  default: savgol&lt;br /&gt;
        winsize   Length of running window for the filter&lt;br /&gt;
                  default: 9&lt;br /&gt;
          order   Order of the Savitzky-Golay filter&lt;br /&gt;
                  default: 2&lt;br /&gt;
     opt_points   Count of random points used for parameter optimization&lt;br /&gt;
                  default: 50&lt;br /&gt;
   diff_penalty   Penalty for difference between original and filtered signals&lt;br /&gt;
                  default: 1.0&lt;br /&gt;
  deriv_penalty   Penalty for big derivates of the filtered signal&lt;br /&gt;
                  default: 1.0&lt;br /&gt;
     iterations   Number of iterations&lt;br /&gt;
                  default: 1&lt;br /&gt;
&lt;br /&gt;
==== Параметры общего назначения ====&lt;br /&gt;
Два параметра input и result_prefix отвечают за перечень входных и выходных растров. Модуль ожидает, что на вход ему будет передан список растров, перечисленных через запятую в порядке возрастания (или убывания) времени. Например:&lt;br /&gt;
  input=ndvi1,ndvi2,ndvi3,ndvi4,....&lt;br /&gt;
При этом временной ряд должен быть равноотстоящим, т.е. растры представляют собой измерения какой-либо величины (или состояния территории), сделанные через равные промежутки времени. Но на практике не всегда возможно иметь дело с равноотстоящими рядами, часть каких-либо измерений может отсутсвовать по объетивным причинам. В таком случае следует вставить пустой растр, состоящий из значений NULL (нет данных), который легко сгенерировать, воспользовавшись растровым калькулятором:&lt;br /&gt;
 r.mapcalc expression=&amp;quot;dummy = null()&amp;quot;&lt;br /&gt;
В самих растрах так же могут быть области, с отсутсвующими в них данными, такие участки не требуют специальной предварительной обработки.&lt;br /&gt;
&lt;br /&gt;
Перед началом расчетов такие пропущенные значения будут предварительно заполнены данными, полученными линейной интерполяцией (во времени, пространственная интерполяция не используется).&lt;br /&gt;
&lt;br /&gt;
Результаты будут записаны в новые растры, названия которых начинаются с указанного result_prefix. Например, в случае, если result_prefix=&amp;quot;res.&amp;quot;, будут получены растры: res.ndvi1,res.ndvi2,res.ndvi3,res.ndvi4,....&lt;br /&gt;
&lt;br /&gt;
Таким образом команда со значениями, заданными по умолчанию может выглядеть следующим образом:&lt;br /&gt;
 r.series.filter input=ndvi1,ndvi2,ndvi3,ndvi4,.... result_prefix=&amp;quot;res.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
==== Методы фильтрации ====&lt;br /&gt;
&lt;br /&gt;
На момент написания статьи в модуле реализовано два метода фильтрации:&lt;br /&gt;
* медианный фильтр (параметр method=median);&lt;br /&gt;
* фильтр Савицкого-Голея (method=savgol).&lt;br /&gt;
&lt;br /&gt;
Каждый из этих фильтров работает в скользящем окне и рассчитывает прогнозируемое значение исследуемой величины для центральной точки окна. Поэтому модуль использует еще один параметр winsize, задающий ширину скользящего окна. Этот параметр должен быть нечетным числом.&lt;br /&gt;
&lt;br /&gt;
Кроме того у метода Савцикого-Голея есть еще один параметр -- порядок полинома (order), который используется при аппроксимации временного ряда внутри скользящего окна.&lt;br /&gt;
&lt;br /&gt;
Естественно, что ширина окна и порядок полинома должны быть таковы, что позволят рассчитать коэффициенты полинома. В случае, если порядок полиома превышает допустимый для данной величины окна, будет выведено сообщение об ошибке.&lt;br /&gt;
&lt;br /&gt;
Например, для использования фильтра Савицкого-Голея с порядком полинома, равным трем, и шириной окна 17 отсчетов, нужно использовать следующую команду:&lt;br /&gt;
 r.series.filter input=.... result_prefix=... method=savgol order=3 wunsiz=17&lt;/div&gt;</summary>
		<author><name>KolesovDmitry</name></author>
	</entry>
	<entry>
		<id>https://wiki.gis-lab.info/index.php?title=%D0%9C%D0%BE%D0%B4%D1%83%D0%BB%D1%8C_r.series.filter_%D0%93%D0%98%D0%A1_GRASS&amp;diff=23441</id>
		<title>Модуль r.series.filter ГИС GRASS</title>
		<link rel="alternate" type="text/html" href="https://wiki.gis-lab.info/index.php?title=%D0%9C%D0%BE%D0%B4%D1%83%D0%BB%D1%8C_r.series.filter_%D0%93%D0%98%D0%A1_GRASS&amp;diff=23441"/>
		<updated>2015-12-21T20:03:27Z</updated>

		<summary type="html">&lt;p&gt;KolesovDmitry: /* Методы фильтрации */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Статья|Черновик}}&lt;br /&gt;
&lt;br /&gt;
== Назначение модуля ==&lt;br /&gt;
Модуль r.series.filter -- это модуль для геоинформационной системы GRASS, предназначенный для обработки временных рядов растровых данных, в первую очередь вегетационных индексов. Модуль производит очистку от шумов временных рядов с использованием различных фильтров (медианый фильтр, [https://en.wikipedia.org/wiki/Savitzky%E2%80%93Golay_filter фильтр Савицкого-Голея]). Модуль может использоваться для очистки от шумов временных рядов произвольной природы, однако одной из важных особенностей модуля является поддерка фильтрации данных вегетационных индексов. Для обработки таких рядов модуль реализует процедуру фильтрации, предложенную в статье &amp;quot;Chen J. et al. A simple method for reconstructing a high-quality NDVI time-series data set based on the Savitzky–Golay filter //Remote sensing of Environment. – 2004. – Т. 91. – №. 3. – С. 332-344.&amp;quot;. Основная идея этого фильтра опирается на то, что шумы в значениях вегетационных индексов обычно индуцируются условиями съемки и атмосферными явлениями, которые занижают зачения индекса. В очень упрощенном виде можно сказать, что предлагаемая в указанной статье методика производит отбраковку низких значений индекса и производит фильтрацию по верхним значениям анализируемого временного ряда.&lt;br /&gt;
&lt;br /&gt;
== Установка ==&lt;br /&gt;
Модуль был написан на языке Python и предназначен для работы в GRASS GIS седьмой версии. В модуле используются библиотека [http://docs.scipy.org/doc/scipy/reference/signal.html scipy.signal], входящая в состав пакета [http://www.scipy.org/about.html SciPy]. Поэтому перед началом работы в интерпретатор Python, используемый в GRASS, следует установить SciPy.&lt;br /&gt;
&lt;br /&gt;
После установки SciPy появится возможность установить сам модуль r.series.filter. Данный модуль доступен в репозитории модулей GRASS ADDONS, поэтому его установка производится автоматически, если использовать модуль g.extension (вызываемый из графического интерфейса пользователя или командной строки). Например, можно использовать следущюую команду:&lt;br /&gt;
 g.extension r.series.filter&lt;br /&gt;
В результате модуль будет автоматически скачан из репозитория и установлен.&lt;br /&gt;
&lt;br /&gt;
== Особенности работы и примеры ==&lt;br /&gt;
&lt;br /&gt;
=== Параметры модуля и их назначение ===&lt;br /&gt;
Модуль находится в состоянии разработки, это означает, что в него будут добавляться новые возможности. На момент написания статьи модуль использует следующие параметры и ключи (показаны наиболее важные):&lt;br /&gt;
&lt;br /&gt;
 r.series.filter [-cu] input=string[,string,...] result_prefix=string&lt;br /&gt;
   [method=string] [winsize=value] [order=value] [opt_points=value]&lt;br /&gt;
   [diff_penalty=value] [deriv_penalty=value] [iterations=value]&lt;br /&gt;
 Flags:&lt;br /&gt;
   -c   Try to find optimal parameters for filtering&lt;br /&gt;
   -u   Fit the result curve by upper boundary&lt;br /&gt;
 Parameters:&lt;br /&gt;
          input   Raster names of equally spaced time series.&lt;br /&gt;
  result_prefix   Prefix for raster names of filtered X(t)&lt;br /&gt;
         method   Used method&lt;br /&gt;
                  default: savgol&lt;br /&gt;
        winsize   Length of running window for the filter&lt;br /&gt;
                  default: 9&lt;br /&gt;
          order   Order of the Savitzky-Golay filter&lt;br /&gt;
                  default: 2&lt;br /&gt;
     opt_points   Count of random points used for parameter optimization&lt;br /&gt;
                  default: 50&lt;br /&gt;
   diff_penalty   Penalty for difference between original and filtered signals&lt;br /&gt;
                  default: 1.0&lt;br /&gt;
  deriv_penalty   Penalty for big derivates of the filtered signal&lt;br /&gt;
                  default: 1.0&lt;br /&gt;
     iterations   Number of iterations&lt;br /&gt;
                  default: 1&lt;br /&gt;
&lt;br /&gt;
==== Параметры общего назначения ====&lt;br /&gt;
Два параметра input и result_prefix отвечают за перечень входных и выходных растров. Модуль ожидает, что на вход ему будет передан список растров, перечисленных через запятую в порядке возрастания (или убывания) времени. Например:&lt;br /&gt;
  input=ndvi1,ndvi2,ndvi3,ndvi4,....&lt;br /&gt;
При этом временной ряд должен быть равноотстоящим, т.е. растры представляют собой измерения какой-либо величины (или состояния территории), сделанные через равные промежутки времени. Но на практике не всегда возможно иметь дело с равноотстоящими рядами, часть каких-либо измерений может отсутсвовать по объетивным причинам. В таком случае следует вставить пустой растр, состоящий из значений NULL (нет данных), который легко сгенерировать, воспользовавшись растровым калькулятором:&lt;br /&gt;
 r.mapcalc expression=&amp;quot;dummy = null()&amp;quot;&lt;br /&gt;
В самих растрах так же могут быть области, с отсутсвующими в них данными, такие участки не требуют специальной предварительной обработки.&lt;br /&gt;
&lt;br /&gt;
Перед началом расчетов такие пропущенные значения будут предварительно заполнены данными, полученными линейной интерполяцией (во времени, пространственная интерполяция не используется).&lt;br /&gt;
&lt;br /&gt;
Результаты будут записаны в новые растры, названия которых начинаются с указанного result_prefix. Например, в случае, если result_prefix=&amp;quot;res.&amp;quot;, будут получены растры: res.ndvi1,res.ndvi2,res.ndvi3,res.ndvi4,....&lt;br /&gt;
&lt;br /&gt;
Таким образом команда со значениями, заданными по умолчанию может выглядеть следующим образом:&lt;br /&gt;
 r.series.filter input=ndvi1,ndvi2,ndvi3,ndvi4,.... result_prefix=&amp;quot;res.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
==== Методы фильтрации ====&lt;br /&gt;
&lt;br /&gt;
На момент написания статьи в модуле реализовано два метода фильтрации:&lt;br /&gt;
* медианный фильтр (параметр method=median);&lt;br /&gt;
* фильтр Савицкого-Голея (method=savgol).&lt;br /&gt;
&lt;br /&gt;
Каждый из этих фильтров работает в скользящем окне и рассчитывает прогнозируемое значение исследуемой величины для центральной точки окна. Поэтому модуль использует еще один параметр winsize, задающий ширину скользящего окна. Этот параметр должен быть нечетным числом.&lt;br /&gt;
&lt;br /&gt;
Кроме того у метода Савцикого-Голея есть еще один параметр -- порядок полинома (order), который используется при аппроксимации временного ряда внутри скользящего окна.&lt;br /&gt;
&lt;br /&gt;
Естественно, что ширина окна и порядок полинома должны быть таковы, что &lt;br /&gt;
&lt;br /&gt;
Например, для использования фильтра Савицкого-Голея с порядком полинома, равным трем и шириной окна 17 отсчетов.&lt;/div&gt;</summary>
		<author><name>KolesovDmitry</name></author>
	</entry>
	<entry>
		<id>https://wiki.gis-lab.info/index.php?title=%D0%9C%D0%BE%D0%B4%D1%83%D0%BB%D1%8C_r.series.filter_%D0%93%D0%98%D0%A1_GRASS&amp;diff=23440</id>
		<title>Модуль r.series.filter ГИС GRASS</title>
		<link rel="alternate" type="text/html" href="https://wiki.gis-lab.info/index.php?title=%D0%9C%D0%BE%D0%B4%D1%83%D0%BB%D1%8C_r.series.filter_%D0%93%D0%98%D0%A1_GRASS&amp;diff=23440"/>
		<updated>2015-12-21T19:20:23Z</updated>

		<summary type="html">&lt;p&gt;KolesovDmitry: /* Метод фильтрации */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Статья|Черновик}}&lt;br /&gt;
&lt;br /&gt;
== Назначение модуля ==&lt;br /&gt;
Модуль r.series.filter -- это модуль для геоинформационной системы GRASS, предназначенный для обработки временных рядов растровых данных, в первую очередь вегетационных индексов. Модуль производит очистку от шумов временных рядов с использованием различных фильтров (медианый фильтр, [https://en.wikipedia.org/wiki/Savitzky%E2%80%93Golay_filter фильтр Савицкого-Голея]). Модуль может использоваться для очистки от шумов временных рядов произвольной природы, однако одной из важных особенностей модуля является поддерка фильтрации данных вегетационных индексов. Для обработки таких рядов модуль реализует процедуру фильтрации, предложенную в статье &amp;quot;Chen J. et al. A simple method for reconstructing a high-quality NDVI time-series data set based on the Savitzky–Golay filter //Remote sensing of Environment. – 2004. – Т. 91. – №. 3. – С. 332-344.&amp;quot;. Основная идея этого фильтра опирается на то, что шумы в значениях вегетационных индексов обычно индуцируются условиями съемки и атмосферными явлениями, которые занижают зачения индекса. В очень упрощенном виде можно сказать, что предлагаемая в указанной статье методика производит отбраковку низких значений индекса и производит фильтрацию по верхним значениям анализируемого временного ряда.&lt;br /&gt;
&lt;br /&gt;
== Установка ==&lt;br /&gt;
Модуль был написан на языке Python и предназначен для работы в GRASS GIS седьмой версии. В модуле используются библиотека [http://docs.scipy.org/doc/scipy/reference/signal.html scipy.signal], входящая в состав пакета [http://www.scipy.org/about.html SciPy]. Поэтому перед началом работы в интерпретатор Python, используемый в GRASS, следует установить SciPy.&lt;br /&gt;
&lt;br /&gt;
После установки SciPy появится возможность установить сам модуль r.series.filter. Данный модуль доступен в репозитории модулей GRASS ADDONS, поэтому его установка производится автоматически, если использовать модуль g.extension (вызываемый из графического интерфейса пользователя или командной строки). Например, можно использовать следущюую команду:&lt;br /&gt;
 g.extension r.series.filter&lt;br /&gt;
В результате модуль будет автоматически скачан из репозитория и установлен.&lt;br /&gt;
&lt;br /&gt;
== Особенности работы и примеры ==&lt;br /&gt;
&lt;br /&gt;
=== Параметры модуля и их назначение ===&lt;br /&gt;
Модуль находится в состоянии разработки, это означает, что в него будут добавляться новые возможности. На момент написания статьи модуль использует следующие параметры и ключи (показаны наиболее важные):&lt;br /&gt;
&lt;br /&gt;
 r.series.filter [-cu] input=string[,string,...] result_prefix=string&lt;br /&gt;
   [method=string] [winsize=value] [order=value] [opt_points=value]&lt;br /&gt;
   [diff_penalty=value] [deriv_penalty=value] [iterations=value]&lt;br /&gt;
 Flags:&lt;br /&gt;
   -c   Try to find optimal parameters for filtering&lt;br /&gt;
   -u   Fit the result curve by upper boundary&lt;br /&gt;
 Parameters:&lt;br /&gt;
          input   Raster names of equally spaced time series.&lt;br /&gt;
  result_prefix   Prefix for raster names of filtered X(t)&lt;br /&gt;
         method   Used method&lt;br /&gt;
                  default: savgol&lt;br /&gt;
        winsize   Length of running window for the filter&lt;br /&gt;
                  default: 9&lt;br /&gt;
          order   Order of the Savitzky-Golay filter&lt;br /&gt;
                  default: 2&lt;br /&gt;
     opt_points   Count of random points used for parameter optimization&lt;br /&gt;
                  default: 50&lt;br /&gt;
   diff_penalty   Penalty for difference between original and filtered signals&lt;br /&gt;
                  default: 1.0&lt;br /&gt;
  deriv_penalty   Penalty for big derivates of the filtered signal&lt;br /&gt;
                  default: 1.0&lt;br /&gt;
     iterations   Number of iterations&lt;br /&gt;
                  default: 1&lt;br /&gt;
&lt;br /&gt;
==== Параметры общего назначения ====&lt;br /&gt;
Два параметра input и result_prefix отвечают за перечень входных и выходных растров. Модуль ожидает, что на вход ему будет передан список растров, перечисленных через запятую в порядке возрастания (или убывания) времени. Например:&lt;br /&gt;
  input=ndvi1,ndvi2,ndvi3,ndvi4,....&lt;br /&gt;
При этом временной ряд должен быть равноотстоящим, т.е. растры представляют собой измерения какой-либо величины (или состояния территории), сделанные через равные промежутки времени. Но на практике не всегда возможно иметь дело с равноотстоящими рядами, часть каких-либо измерений может отсутсвовать по объетивным причинам. В таком случае следует вставить пустой растр, состоящий из значений NULL (нет данных), который легко сгенерировать, воспользовавшись растровым калькулятором:&lt;br /&gt;
 r.mapcalc expression=&amp;quot;dummy = null()&amp;quot;&lt;br /&gt;
В самих растрах так же могут быть области, с отсутсвующими в них данными, такие участки не требуют специальной предварительной обработки.&lt;br /&gt;
&lt;br /&gt;
Перед началом расчетов такие пропущенные значения будут предварительно заполнены данными, полученными линейной интерполяцией (во времени, пространственная интерполяция не используется).&lt;br /&gt;
&lt;br /&gt;
Результаты будут записаны в новые растры, названия которых начинаются с указанного result_prefix. Например, в случае, если result_prefix=&amp;quot;res.&amp;quot;, будут получены растры: res.ndvi1,res.ndvi2,res.ndvi3,res.ndvi4,....&lt;br /&gt;
&lt;br /&gt;
Таким образом команда со значениями, заданными по умолчанию может выглядеть следующим образом:&lt;br /&gt;
 r.series.filter input=ndvi1,ndvi2,ndvi3,ndvi4,.... result_prefix=&amp;quot;res.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
==== Методы фильтрации ====&lt;br /&gt;
&lt;br /&gt;
На момент написания статьи в модуле реализовано два метода фильтрации:&lt;br /&gt;
* медианный фильтр (параметры);&lt;br /&gt;
* фильтр Савицкого-Голея.&lt;br /&gt;
&lt;br /&gt;
Каждый из этих фильтров работает в скользящем окне и рассчитывает прогнозируемое значение исследуемой величины для центральной точки окна.&lt;/div&gt;</summary>
		<author><name>KolesovDmitry</name></author>
	</entry>
	<entry>
		<id>https://wiki.gis-lab.info/index.php?title=%D0%9C%D0%BE%D0%B4%D1%83%D0%BB%D1%8C_r.series.filter_%D0%93%D0%98%D0%A1_GRASS&amp;diff=23439</id>
		<title>Модуль r.series.filter ГИС GRASS</title>
		<link rel="alternate" type="text/html" href="https://wiki.gis-lab.info/index.php?title=%D0%9C%D0%BE%D0%B4%D1%83%D0%BB%D1%8C_r.series.filter_%D0%93%D0%98%D0%A1_GRASS&amp;diff=23439"/>
		<updated>2015-12-21T19:16:24Z</updated>

		<summary type="html">&lt;p&gt;KolesovDmitry: /* Параметры общего назначения */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Статья|Черновик}}&lt;br /&gt;
&lt;br /&gt;
== Назначение модуля ==&lt;br /&gt;
Модуль r.series.filter -- это модуль для геоинформационной системы GRASS, предназначенный для обработки временных рядов растровых данных, в первую очередь вегетационных индексов. Модуль производит очистку от шумов временных рядов с использованием различных фильтров (медианый фильтр, [https://en.wikipedia.org/wiki/Savitzky%E2%80%93Golay_filter фильтр Савицкого-Голея]). Модуль может использоваться для очистки от шумов временных рядов произвольной природы, однако одной из важных особенностей модуля является поддерка фильтрации данных вегетационных индексов. Для обработки таких рядов модуль реализует процедуру фильтрации, предложенную в статье &amp;quot;Chen J. et al. A simple method for reconstructing a high-quality NDVI time-series data set based on the Savitzky–Golay filter //Remote sensing of Environment. – 2004. – Т. 91. – №. 3. – С. 332-344.&amp;quot;. Основная идея этого фильтра опирается на то, что шумы в значениях вегетационных индексов обычно индуцируются условиями съемки и атмосферными явлениями, которые занижают зачения индекса. В очень упрощенном виде можно сказать, что предлагаемая в указанной статье методика производит отбраковку низких значений индекса и производит фильтрацию по верхним значениям анализируемого временного ряда.&lt;br /&gt;
&lt;br /&gt;
== Установка ==&lt;br /&gt;
Модуль был написан на языке Python и предназначен для работы в GRASS GIS седьмой версии. В модуле используются библиотека [http://docs.scipy.org/doc/scipy/reference/signal.html scipy.signal], входящая в состав пакета [http://www.scipy.org/about.html SciPy]. Поэтому перед началом работы в интерпретатор Python, используемый в GRASS, следует установить SciPy.&lt;br /&gt;
&lt;br /&gt;
После установки SciPy появится возможность установить сам модуль r.series.filter. Данный модуль доступен в репозитории модулей GRASS ADDONS, поэтому его установка производится автоматически, если использовать модуль g.extension (вызываемый из графического интерфейса пользователя или командной строки). Например, можно использовать следущюую команду:&lt;br /&gt;
 g.extension r.series.filter&lt;br /&gt;
В результате модуль будет автоматически скачан из репозитория и установлен.&lt;br /&gt;
&lt;br /&gt;
== Особенности работы и примеры ==&lt;br /&gt;
&lt;br /&gt;
=== Параметры модуля и их назначение ===&lt;br /&gt;
Модуль находится в состоянии разработки, это означает, что в него будут добавляться новые возможности. На момент написания статьи модуль использует следующие параметры и ключи (показаны наиболее важные):&lt;br /&gt;
&lt;br /&gt;
 r.series.filter [-cu] input=string[,string,...] result_prefix=string&lt;br /&gt;
   [method=string] [winsize=value] [order=value] [opt_points=value]&lt;br /&gt;
   [diff_penalty=value] [deriv_penalty=value] [iterations=value]&lt;br /&gt;
 Flags:&lt;br /&gt;
   -c   Try to find optimal parameters for filtering&lt;br /&gt;
   -u   Fit the result curve by upper boundary&lt;br /&gt;
 Parameters:&lt;br /&gt;
          input   Raster names of equally spaced time series.&lt;br /&gt;
  result_prefix   Prefix for raster names of filtered X(t)&lt;br /&gt;
         method   Used method&lt;br /&gt;
                  default: savgol&lt;br /&gt;
        winsize   Length of running window for the filter&lt;br /&gt;
                  default: 9&lt;br /&gt;
          order   Order of the Savitzky-Golay filter&lt;br /&gt;
                  default: 2&lt;br /&gt;
     opt_points   Count of random points used for parameter optimization&lt;br /&gt;
                  default: 50&lt;br /&gt;
   diff_penalty   Penalty for difference between original and filtered signals&lt;br /&gt;
                  default: 1.0&lt;br /&gt;
  deriv_penalty   Penalty for big derivates of the filtered signal&lt;br /&gt;
                  default: 1.0&lt;br /&gt;
     iterations   Number of iterations&lt;br /&gt;
                  default: 1&lt;br /&gt;
&lt;br /&gt;
==== Параметры общего назначения ====&lt;br /&gt;
Два параметра input и result_prefix отвечают за перечень входных и выходных растров. Модуль ожидает, что на вход ему будет передан список растров, перечисленных через запятую в порядке возрастания (или убывания) времени. Например:&lt;br /&gt;
  input=ndvi1,ndvi2,ndvi3,ndvi4,....&lt;br /&gt;
При этом временной ряд должен быть равноотстоящим, т.е. растры представляют собой измерения какой-либо величины (или состояния территории), сделанные через равные промежутки времени. Но на практике не всегда возможно иметь дело с равноотстоящими рядами, часть каких-либо измерений может отсутсвовать по объетивным причинам. В таком случае следует вставить пустой растр, состоящий из значений NULL (нет данных), который легко сгенерировать, воспользовавшись растровым калькулятором:&lt;br /&gt;
 r.mapcalc expression=&amp;quot;dummy = null()&amp;quot;&lt;br /&gt;
В самих растрах так же могут быть области, с отсутсвующими в них данными, такие участки не требуют специальной предварительной обработки.&lt;br /&gt;
&lt;br /&gt;
Перед началом расчетов такие пропущенные значения будут предварительно заполнены данными, полученными линейной интерполяцией (во времени, пространственная интерполяция не используется).&lt;br /&gt;
&lt;br /&gt;
Результаты будут записаны в новые растры, названия которых начинаются с указанного result_prefix. Например, в случае, если result_prefix=&amp;quot;res.&amp;quot;, будут получены растры: res.ndvi1,res.ndvi2,res.ndvi3,res.ndvi4,....&lt;br /&gt;
&lt;br /&gt;
Таким образом команда со значениями, заданными по умолчанию может выглядеть следующим образом:&lt;br /&gt;
 r.series.filter input=ndvi1,ndvi2,ndvi3,ndvi4,.... result_prefix=&amp;quot;res.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
==== Метод фильтрации ====&lt;/div&gt;</summary>
		<author><name>KolesovDmitry</name></author>
	</entry>
	<entry>
		<id>https://wiki.gis-lab.info/index.php?title=%D0%9C%D0%BE%D0%B4%D1%83%D0%BB%D1%8C_r.series.filter_%D0%93%D0%98%D0%A1_GRASS&amp;diff=23438</id>
		<title>Модуль r.series.filter ГИС GRASS</title>
		<link rel="alternate" type="text/html" href="https://wiki.gis-lab.info/index.php?title=%D0%9C%D0%BE%D0%B4%D1%83%D0%BB%D1%8C_r.series.filter_%D0%93%D0%98%D0%A1_GRASS&amp;diff=23438"/>
		<updated>2015-12-21T19:16:03Z</updated>

		<summary type="html">&lt;p&gt;KolesovDmitry: /* Параметры общего назначения */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Статья|Черновик}}&lt;br /&gt;
&lt;br /&gt;
== Назначение модуля ==&lt;br /&gt;
Модуль r.series.filter -- это модуль для геоинформационной системы GRASS, предназначенный для обработки временных рядов растровых данных, в первую очередь вегетационных индексов. Модуль производит очистку от шумов временных рядов с использованием различных фильтров (медианый фильтр, [https://en.wikipedia.org/wiki/Savitzky%E2%80%93Golay_filter фильтр Савицкого-Голея]). Модуль может использоваться для очистки от шумов временных рядов произвольной природы, однако одной из важных особенностей модуля является поддерка фильтрации данных вегетационных индексов. Для обработки таких рядов модуль реализует процедуру фильтрации, предложенную в статье &amp;quot;Chen J. et al. A simple method for reconstructing a high-quality NDVI time-series data set based on the Savitzky–Golay filter //Remote sensing of Environment. – 2004. – Т. 91. – №. 3. – С. 332-344.&amp;quot;. Основная идея этого фильтра опирается на то, что шумы в значениях вегетационных индексов обычно индуцируются условиями съемки и атмосферными явлениями, которые занижают зачения индекса. В очень упрощенном виде можно сказать, что предлагаемая в указанной статье методика производит отбраковку низких значений индекса и производит фильтрацию по верхним значениям анализируемого временного ряда.&lt;br /&gt;
&lt;br /&gt;
== Установка ==&lt;br /&gt;
Модуль был написан на языке Python и предназначен для работы в GRASS GIS седьмой версии. В модуле используются библиотека [http://docs.scipy.org/doc/scipy/reference/signal.html scipy.signal], входящая в состав пакета [http://www.scipy.org/about.html SciPy]. Поэтому перед началом работы в интерпретатор Python, используемый в GRASS, следует установить SciPy.&lt;br /&gt;
&lt;br /&gt;
После установки SciPy появится возможность установить сам модуль r.series.filter. Данный модуль доступен в репозитории модулей GRASS ADDONS, поэтому его установка производится автоматически, если использовать модуль g.extension (вызываемый из графического интерфейса пользователя или командной строки). Например, можно использовать следущюую команду:&lt;br /&gt;
 g.extension r.series.filter&lt;br /&gt;
В результате модуль будет автоматически скачан из репозитория и установлен.&lt;br /&gt;
&lt;br /&gt;
== Особенности работы и примеры ==&lt;br /&gt;
&lt;br /&gt;
=== Параметры модуля и их назначение ===&lt;br /&gt;
Модуль находится в состоянии разработки, это означает, что в него будут добавляться новые возможности. На момент написания статьи модуль использует следующие параметры и ключи (показаны наиболее важные):&lt;br /&gt;
&lt;br /&gt;
 r.series.filter [-cu] input=string[,string,...] result_prefix=string&lt;br /&gt;
   [method=string] [winsize=value] [order=value] [opt_points=value]&lt;br /&gt;
   [diff_penalty=value] [deriv_penalty=value] [iterations=value]&lt;br /&gt;
 Flags:&lt;br /&gt;
   -c   Try to find optimal parameters for filtering&lt;br /&gt;
   -u   Fit the result curve by upper boundary&lt;br /&gt;
 Parameters:&lt;br /&gt;
          input   Raster names of equally spaced time series.&lt;br /&gt;
  result_prefix   Prefix for raster names of filtered X(t)&lt;br /&gt;
         method   Used method&lt;br /&gt;
                  default: savgol&lt;br /&gt;
        winsize   Length of running window for the filter&lt;br /&gt;
                  default: 9&lt;br /&gt;
          order   Order of the Savitzky-Golay filter&lt;br /&gt;
                  default: 2&lt;br /&gt;
     opt_points   Count of random points used for parameter optimization&lt;br /&gt;
                  default: 50&lt;br /&gt;
   diff_penalty   Penalty for difference between original and filtered signals&lt;br /&gt;
                  default: 1.0&lt;br /&gt;
  deriv_penalty   Penalty for big derivates of the filtered signal&lt;br /&gt;
                  default: 1.0&lt;br /&gt;
     iterations   Number of iterations&lt;br /&gt;
                  default: 1&lt;br /&gt;
&lt;br /&gt;
==== Параметры общего назначения ====&lt;br /&gt;
Два параметра input и result_prefix отвечают за перечень входных и выходных растров. Модуль ожидает, что на вход ему будет передан список растров, перечисленных через запятую в порядке возрастания (или убывания) времени. Например:&lt;br /&gt;
  input=ndvi1,ndvi2,ndvi3,ndvi4,....&lt;br /&gt;
При этом временной ряд должен быть равноотстоящим, т.е. растры представляют собой измерения какой-либо величины (или состояния территории), сделанные через равные промежутки времени. Но на практике не всегда возможно иметь дело с равноотстоящими рядами, часть каких-либо измерений может отсутсвовать по объетивным причинам. В таком случае следует вставить пустой растр, состоящий из значений NULL (нет данных), который легко сгенерировать, воспользовавшись растровым калькулятором:&lt;br /&gt;
 r.mapcalc expression=&amp;quot;dummy = null()&amp;quot;&lt;br /&gt;
В самих растрах так же могут быть области, с отсутсвующими в них данными, такие участки не требуют специальной предварительной обработки.&lt;br /&gt;
&lt;br /&gt;
Перед началом расчетов такие пропущенные значения будут предварительно заполнены данными, полученными линейной интерполяцией (во времени, пространственная интерполяция не используется).&lt;br /&gt;
&lt;br /&gt;
Результаты будут записаны в новые растры, названия которых начинаются с указанного result_prefix. Например, в случае, если result_prefix=&amp;quot;res.&amp;quot;, будут получены растры: res.ndvi1,res.ndvi2,res.ndvi3,res.ndvi4,....&lt;br /&gt;
&lt;br /&gt;
Таким образом команда со значениями, задаными по умолчанию может выглядеть следующим образом:&lt;br /&gt;
 r.series.filter input=ndvi1,ndvi2,ndvi3,ndvi4,.... result_prefix=&amp;quot;res.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
==== Метод фильтрации ====&lt;/div&gt;</summary>
		<author><name>KolesovDmitry</name></author>
	</entry>
	<entry>
		<id>https://wiki.gis-lab.info/index.php?title=%D0%9C%D0%BE%D0%B4%D1%83%D0%BB%D1%8C_r.series.filter_%D0%93%D0%98%D0%A1_GRASS&amp;diff=23437</id>
		<title>Модуль r.series.filter ГИС GRASS</title>
		<link rel="alternate" type="text/html" href="https://wiki.gis-lab.info/index.php?title=%D0%9C%D0%BE%D0%B4%D1%83%D0%BB%D1%8C_r.series.filter_%D0%93%D0%98%D0%A1_GRASS&amp;diff=23437"/>
		<updated>2015-12-21T18:58:26Z</updated>

		<summary type="html">&lt;p&gt;KolesovDmitry: /* Параметры модуля и их назначение */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Статья|Черновик}}&lt;br /&gt;
&lt;br /&gt;
== Назначение модуля ==&lt;br /&gt;
Модуль r.series.filter -- это модуль для геоинформационной системы GRASS, предназначенный для обработки временных рядов растровых данных, в первую очередь вегетационных индексов. Модуль производит очистку от шумов временных рядов с использованием различных фильтров (медианый фильтр, [https://en.wikipedia.org/wiki/Savitzky%E2%80%93Golay_filter фильтр Савицкого-Голея]). Модуль может использоваться для очистки от шумов временных рядов произвольной природы, однако одной из важных особенностей модуля является поддерка фильтрации данных вегетационных индексов. Для обработки таких рядов модуль реализует процедуру фильтрации, предложенную в статье &amp;quot;Chen J. et al. A simple method for reconstructing a high-quality NDVI time-series data set based on the Savitzky–Golay filter //Remote sensing of Environment. – 2004. – Т. 91. – №. 3. – С. 332-344.&amp;quot;. Основная идея этого фильтра опирается на то, что шумы в значениях вегетационных индексов обычно индуцируются условиями съемки и атмосферными явлениями, которые занижают зачения индекса. В очень упрощенном виде можно сказать, что предлагаемая в указанной статье методика производит отбраковку низких значений индекса и производит фильтрацию по верхним значениям анализируемого временного ряда.&lt;br /&gt;
&lt;br /&gt;
== Установка ==&lt;br /&gt;
Модуль был написан на языке Python и предназначен для работы в GRASS GIS седьмой версии. В модуле используются библиотека [http://docs.scipy.org/doc/scipy/reference/signal.html scipy.signal], входящая в состав пакета [http://www.scipy.org/about.html SciPy]. Поэтому перед началом работы в интерпретатор Python, используемый в GRASS, следует установить SciPy.&lt;br /&gt;
&lt;br /&gt;
После установки SciPy появится возможность установить сам модуль r.series.filter. Данный модуль доступен в репозитории модулей GRASS ADDONS, поэтому его установка производится автоматически, если использовать модуль g.extension (вызываемый из графического интерфейса пользователя или командной строки). Например, можно использовать следущюую команду:&lt;br /&gt;
 g.extension r.series.filter&lt;br /&gt;
В результате модуль будет автоматически скачан из репозитория и установлен.&lt;br /&gt;
&lt;br /&gt;
== Особенности работы и примеры ==&lt;br /&gt;
&lt;br /&gt;
=== Параметры модуля и их назначение ===&lt;br /&gt;
Модуль находится в состоянии разработки, это означает, что в него будут добавляться новые возможности. На момент написания статьи модуль использует следующие параметры и ключи (показаны наиболее важные):&lt;br /&gt;
&lt;br /&gt;
 r.series.filter [-cu] input=string[,string,...] result_prefix=string&lt;br /&gt;
   [method=string] [winsize=value] [order=value] [opt_points=value]&lt;br /&gt;
   [diff_penalty=value] [deriv_penalty=value] [iterations=value]&lt;br /&gt;
 Flags:&lt;br /&gt;
   -c   Try to find optimal parameters for filtering&lt;br /&gt;
   -u   Fit the result curve by upper boundary&lt;br /&gt;
 Parameters:&lt;br /&gt;
          input   Raster names of equally spaced time series.&lt;br /&gt;
  result_prefix   Prefix for raster names of filtered X(t)&lt;br /&gt;
         method   Used method&lt;br /&gt;
                  default: savgol&lt;br /&gt;
        winsize   Length of running window for the filter&lt;br /&gt;
                  default: 9&lt;br /&gt;
          order   Order of the Savitzky-Golay filter&lt;br /&gt;
                  default: 2&lt;br /&gt;
     opt_points   Count of random points used for parameter optimization&lt;br /&gt;
                  default: 50&lt;br /&gt;
   diff_penalty   Penalty for difference between original and filtered signals&lt;br /&gt;
                  default: 1.0&lt;br /&gt;
  deriv_penalty   Penalty for big derivates of the filtered signal&lt;br /&gt;
                  default: 1.0&lt;br /&gt;
     iterations   Number of iterations&lt;br /&gt;
                  default: 1&lt;br /&gt;
&lt;br /&gt;
==== Параметры общего назначения ====&lt;br /&gt;
Два параметра input и result_prefix отвечают за перечень входных и выходных растров. Модуль ожидает, что на вход ему будет передан список растров, перечисленных через запятую в порядке возрастания (или убывания) времени. Например:&lt;br /&gt;
  input=ndvi1,ndvi2,ndvi3,ndvi4,....&lt;br /&gt;
При этом временной ряд должен быть равноотстоящим, т.е. растры представляют собой измерения какой-либо величины (или состояния территории), сделанные через равные промежутки времени. Но на практике не всегда возможно иметь дело с равноотстоящими рядами, часть каких-либо измерений может отсутсвовать по объетивным причинам. В таком случае следует вставить пустой растр, состоящий из значений NULL (нет данных), который легко сгенеерировать, воспользовавшись растровым калькулятором:&lt;br /&gt;
 r.mapcalc &amp;quot;dummy = null()&amp;quot;&lt;br /&gt;
В самих растрах так же могут быть области, с отсутсвующими в них данными, такие участки не требуют специальной предварительной обработки.&lt;br /&gt;
&lt;br /&gt;
Перед началом расчетов такие пропущенные значения будут предварительно заполнены данными, полученными линейной интерполяцией (во времени, пространственная интерполяция не используется).&lt;/div&gt;</summary>
		<author><name>KolesovDmitry</name></author>
	</entry>
	<entry>
		<id>https://wiki.gis-lab.info/index.php?title=%D0%9C%D0%BE%D0%B4%D1%83%D0%BB%D1%8C_r.series.filter_%D0%93%D0%98%D0%A1_GRASS&amp;diff=23436</id>
		<title>Модуль r.series.filter ГИС GRASS</title>
		<link rel="alternate" type="text/html" href="https://wiki.gis-lab.info/index.php?title=%D0%9C%D0%BE%D0%B4%D1%83%D0%BB%D1%8C_r.series.filter_%D0%93%D0%98%D0%A1_GRASS&amp;diff=23436"/>
		<updated>2015-12-21T18:39:34Z</updated>

		<summary type="html">&lt;p&gt;KolesovDmitry: /* Установка */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Статья|Черновик}}&lt;br /&gt;
&lt;br /&gt;
== Назначение модуля ==&lt;br /&gt;
Модуль r.series.filter -- это модуль для геоинформационной системы GRASS, предназначенный для обработки временных рядов растровых данных, в первую очередь вегетационных индексов. Модуль производит очистку от шумов временных рядов с использованием различных фильтров (медианый фильтр, [https://en.wikipedia.org/wiki/Savitzky%E2%80%93Golay_filter фильтр Савицкого-Голея]). Модуль может использоваться для очистки от шумов временных рядов произвольной природы, однако одной из важных особенностей модуля является поддерка фильтрации данных вегетационных индексов. Для обработки таких рядов модуль реализует процедуру фильтрации, предложенную в статье &amp;quot;Chen J. et al. A simple method for reconstructing a high-quality NDVI time-series data set based on the Savitzky–Golay filter //Remote sensing of Environment. – 2004. – Т. 91. – №. 3. – С. 332-344.&amp;quot;. Основная идея этого фильтра опирается на то, что шумы в значениях вегетационных индексов обычно индуцируются условиями съемки и атмосферными явлениями, которые занижают зачения индекса. В очень упрощенном виде можно сказать, что предлагаемая в указанной статье методика производит отбраковку низких значений индекса и производит фильтрацию по верхним значениям анализируемого временного ряда.&lt;br /&gt;
&lt;br /&gt;
== Установка ==&lt;br /&gt;
Модуль был написан на языке Python и предназначен для работы в GRASS GIS седьмой версии. В модуле используются библиотека [http://docs.scipy.org/doc/scipy/reference/signal.html scipy.signal], входящая в состав пакета [http://www.scipy.org/about.html SciPy]. Поэтому перед началом работы в интерпретатор Python, используемый в GRASS, следует установить SciPy.&lt;br /&gt;
&lt;br /&gt;
После установки SciPy появится возможность установить сам модуль r.series.filter. Данный модуль доступен в репозитории модулей GRASS ADDONS, поэтому его установка производится автоматически, если использовать модуль g.extension (вызываемый из графического интерфейса пользователя или командной строки). Например, можно использовать следущюую команду:&lt;br /&gt;
 g.extension r.series.filter&lt;br /&gt;
В результате модуль будет автоматически скачан из репозитория и установлен.&lt;br /&gt;
&lt;br /&gt;
== Особенности работы и примеры ==&lt;br /&gt;
&lt;br /&gt;
=== Параметры модуля и их назначение ===&lt;br /&gt;
Модуль находится в состоянии разработки, это означает, что в него будут добавляться новые возможности. На момент написания статьи модуль использует следующие параметры и ключи (показаны наиболее важные):&lt;br /&gt;
&lt;br /&gt;
 r.series.filter [-cu] input=string[,string,...] result_prefix=string&lt;br /&gt;
   [method=string] [winsize=value] [order=value] [opt_points=value]&lt;br /&gt;
   [diff_penalty=value] [deriv_penalty=value] [iterations=value]&lt;br /&gt;
 Flags:&lt;br /&gt;
   -c   Try to find optimal parameters for filtering&lt;br /&gt;
   -u   Fit the result curve by upper boundary&lt;br /&gt;
 Parameters:&lt;br /&gt;
          input   Raster names of equally spaced time series.&lt;br /&gt;
  result_prefix   Prefix for raster names of filtered X(t)&lt;br /&gt;
         method   Used method&lt;br /&gt;
                  default: savgol&lt;br /&gt;
        winsize   Length of running window for the filter&lt;br /&gt;
                  default: 9&lt;br /&gt;
          order   Order of the Savitzky-Golay filter&lt;br /&gt;
                  default: 2&lt;br /&gt;
     opt_points   Count of random points used for parameter optimization&lt;br /&gt;
                  default: 50&lt;br /&gt;
   diff_penalty   Penalty for difference between original and filtered signals&lt;br /&gt;
                  default: 1.0&lt;br /&gt;
  deriv_penalty   Penalty for big derivates of the filtered signal&lt;br /&gt;
                  default: 1.0&lt;br /&gt;
     iterations   Number of iterations&lt;br /&gt;
                  default: 1&lt;/div&gt;</summary>
		<author><name>KolesovDmitry</name></author>
	</entry>
	<entry>
		<id>https://wiki.gis-lab.info/index.php?title=%D0%9C%D0%BE%D0%B4%D1%83%D0%BB%D1%8C_r.series.filter_%D0%93%D0%98%D0%A1_GRASS&amp;diff=23435</id>
		<title>Модуль r.series.filter ГИС GRASS</title>
		<link rel="alternate" type="text/html" href="https://wiki.gis-lab.info/index.php?title=%D0%9C%D0%BE%D0%B4%D1%83%D0%BB%D1%8C_r.series.filter_%D0%93%D0%98%D0%A1_GRASS&amp;diff=23435"/>
		<updated>2015-12-21T18:37:19Z</updated>

		<summary type="html">&lt;p&gt;KolesovDmitry: /* Назначение модуля */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Статья|Черновик}}&lt;br /&gt;
&lt;br /&gt;
== Назначение модуля ==&lt;br /&gt;
Модуль r.series.filter -- это модуль для геоинформационной системы GRASS, предназначенный для обработки временных рядов растровых данных, в первую очередь вегетационных индексов. Модуль производит очистку от шумов временных рядов с использованием различных фильтров (медианый фильтр, [https://en.wikipedia.org/wiki/Savitzky%E2%80%93Golay_filter фильтр Савицкого-Голея]). Модуль может использоваться для очистки от шумов временных рядов произвольной природы, однако одной из важных особенностей модуля является поддерка фильтрации данных вегетационных индексов. Для обработки таких рядов модуль реализует процедуру фильтрации, предложенную в статье &amp;quot;Chen J. et al. A simple method for reconstructing a high-quality NDVI time-series data set based on the Savitzky–Golay filter //Remote sensing of Environment. – 2004. – Т. 91. – №. 3. – С. 332-344.&amp;quot;. Основная идея этого фильтра опирается на то, что шумы в значениях вегетационных индексов обычно индуцируются условиями съемки и атмосферными явлениями, которые занижают зачения индекса. В очень упрощенном виде можно сказать, что предлагаемая в указанной статье методика производит отбраковку низких значений индекса и производит фильтрацию по верхним значениям анализируемого временного ряда.&lt;br /&gt;
&lt;br /&gt;
== Установка ==&lt;br /&gt;
Модуль был написан на языке Python и предназначен для работы в GRASS GIS седьмой версии. В модуле используются библиотека [http://docs.scipy.org/doc/scipy/reference/signal.html scipy.signal], входящая в состав пакета [http://www.scipy.org/about.html SciPy]. Поэтому перед началом работы в интерпретатор Python, используемый в GRASS, следует установить SciPy.&lt;br /&gt;
&lt;br /&gt;
После установки SciPy появится возможность установить сам модуль r.series.filter. Данный модуль доступен в репозитории модулей GRASS ADDONS, поэтому его установка производится автоматически, если использовать модуль g.extension (вызываемый из графического интерфейса пользователя или командной строки). Например, можно использовать следущюую команду:&lt;br /&gt;
 g.extension r.series.filter&lt;br /&gt;
В результате модуль будет выкачан и установлен.&lt;br /&gt;
&lt;br /&gt;
== Особенности работы и примеры ==&lt;br /&gt;
&lt;br /&gt;
=== Параметры модуля и их назначение ===&lt;br /&gt;
Модуль находится в состоянии разработки, это означает, что в него будут добавляться новые возможности. На момент написания статьи модуль использует следующие параметры и ключи (показаны наиболее важные):&lt;br /&gt;
&lt;br /&gt;
 r.series.filter [-cu] input=string[,string,...] result_prefix=string&lt;br /&gt;
   [method=string] [winsize=value] [order=value] [opt_points=value]&lt;br /&gt;
   [diff_penalty=value] [deriv_penalty=value] [iterations=value]&lt;br /&gt;
 Flags:&lt;br /&gt;
   -c   Try to find optimal parameters for filtering&lt;br /&gt;
   -u   Fit the result curve by upper boundary&lt;br /&gt;
 Parameters:&lt;br /&gt;
          input   Raster names of equally spaced time series.&lt;br /&gt;
  result_prefix   Prefix for raster names of filtered X(t)&lt;br /&gt;
         method   Used method&lt;br /&gt;
                  default: savgol&lt;br /&gt;
        winsize   Length of running window for the filter&lt;br /&gt;
                  default: 9&lt;br /&gt;
          order   Order of the Savitzky-Golay filter&lt;br /&gt;
                  default: 2&lt;br /&gt;
     opt_points   Count of random points used for parameter optimization&lt;br /&gt;
                  default: 50&lt;br /&gt;
   diff_penalty   Penalty for difference between original and filtered signals&lt;br /&gt;
                  default: 1.0&lt;br /&gt;
  deriv_penalty   Penalty for big derivates of the filtered signal&lt;br /&gt;
                  default: 1.0&lt;br /&gt;
     iterations   Number of iterations&lt;br /&gt;
                  default: 1&lt;/div&gt;</summary>
		<author><name>KolesovDmitry</name></author>
	</entry>
	<entry>
		<id>https://wiki.gis-lab.info/index.php?title=%D0%9C%D0%BE%D0%B4%D1%83%D0%BB%D1%8C_r.series.filter_%D0%93%D0%98%D0%A1_GRASS&amp;diff=23434</id>
		<title>Модуль r.series.filter ГИС GRASS</title>
		<link rel="alternate" type="text/html" href="https://wiki.gis-lab.info/index.php?title=%D0%9C%D0%BE%D0%B4%D1%83%D0%BB%D1%8C_r.series.filter_%D0%93%D0%98%D0%A1_GRASS&amp;diff=23434"/>
		<updated>2015-12-21T18:11:08Z</updated>

		<summary type="html">&lt;p&gt;KolesovDmitry: /* Параметры модуля и их назначение */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Статья|Черновик}}&lt;br /&gt;
&lt;br /&gt;
== Назначение модуля ==&lt;br /&gt;
Модуль r.series.filter -- это модуль для геоинформационной системы GRASS, предназначенный для обработки временных рядов растровых данных, в первую очередь вегетационных индексов. Модуль производит очистку от шумов временных рядов с использованием различных фильтров (медианый фильтр, фильтр Савицкого-Голея). Модуль может использоваться для очистки от шумов временных рядов произвольной природы, однако одной из важных особенностей модуля является поддерка фильтрации данных вегетационных индексов. Для обработки таких рядов модуль реализует процедуру фильтрации, предложенную в статье &amp;quot;Chen J. et al. A simple method for reconstructing a high-quality NDVI time-series data set based on the Savitzky–Golay filter //Remote sensing of Environment. – 2004. – Т. 91. – №. 3. – С. 332-344.&amp;quot;. Основная идея этого фильтра опирается на то, что шумы в значениях вегетационных индексов обычно индуцируются условиями съемки и атмосферными явлениями, которые занижают зачения индекса. В очень упрощенном виде можно сказать, что предлагаемая в указанной статье методика производит отбраковку низких значений индекса и производит фильтрацию по верхним значениям анализируемого временного ряда.&lt;br /&gt;
&lt;br /&gt;
== Установка ==&lt;br /&gt;
Модуль был написан на языке Python и предназначен для работы в GRASS GIS седьмой версии. В модуле используются библиотека [http://docs.scipy.org/doc/scipy/reference/signal.html scipy.signal], входящая в состав пакета [http://www.scipy.org/about.html SciPy]. Поэтому перед началом работы в интерпретатор Python, используемый в GRASS, следует установить SciPy.&lt;br /&gt;
&lt;br /&gt;
После установки SciPy появится возможность установить сам модуль r.series.filter. Данный модуль доступен в репозитории модулей GRASS ADDONS, поэтому его установка производится автоматически, если использовать модуль g.extension (вызываемый из графического интерфейса пользователя или командной строки). Например, можно использовать следущюую команду:&lt;br /&gt;
 g.extension r.series.filter&lt;br /&gt;
В результате модуль будет выкачан и установлен.&lt;br /&gt;
&lt;br /&gt;
== Особенности работы и примеры ==&lt;br /&gt;
&lt;br /&gt;
=== Параметры модуля и их назначение ===&lt;br /&gt;
Модуль находится в состоянии разработки, это означает, что в него будут добавляться новые возможности. На момент написания статьи модуль использует следующие параметры и ключи (показаны наиболее важные):&lt;br /&gt;
&lt;br /&gt;
 r.series.filter [-cu] input=string[,string,...] result_prefix=string&lt;br /&gt;
   [method=string] [winsize=value] [order=value] [opt_points=value]&lt;br /&gt;
   [diff_penalty=value] [deriv_penalty=value] [iterations=value]&lt;br /&gt;
 Flags:&lt;br /&gt;
   -c   Try to find optimal parameters for filtering&lt;br /&gt;
   -u   Fit the result curve by upper boundary&lt;br /&gt;
 Parameters:&lt;br /&gt;
          input   Raster names of equally spaced time series.&lt;br /&gt;
  result_prefix   Prefix for raster names of filtered X(t)&lt;br /&gt;
         method   Used method&lt;br /&gt;
                  default: savgol&lt;br /&gt;
        winsize   Length of running window for the filter&lt;br /&gt;
                  default: 9&lt;br /&gt;
          order   Order of the Savitzky-Golay filter&lt;br /&gt;
                  default: 2&lt;br /&gt;
     opt_points   Count of random points used for parameter optimization&lt;br /&gt;
                  default: 50&lt;br /&gt;
   diff_penalty   Penalty for difference between original and filtered signals&lt;br /&gt;
                  default: 1.0&lt;br /&gt;
  deriv_penalty   Penalty for big derivates of the filtered signal&lt;br /&gt;
                  default: 1.0&lt;br /&gt;
     iterations   Number of iterations&lt;br /&gt;
                  default: 1&lt;/div&gt;</summary>
		<author><name>KolesovDmitry</name></author>
	</entry>
	<entry>
		<id>https://wiki.gis-lab.info/index.php?title=%D0%9C%D0%BE%D0%B4%D1%83%D0%BB%D1%8C_r.series.filter_%D0%93%D0%98%D0%A1_GRASS&amp;diff=23433</id>
		<title>Модуль r.series.filter ГИС GRASS</title>
		<link rel="alternate" type="text/html" href="https://wiki.gis-lab.info/index.php?title=%D0%9C%D0%BE%D0%B4%D1%83%D0%BB%D1%8C_r.series.filter_%D0%93%D0%98%D0%A1_GRASS&amp;diff=23433"/>
		<updated>2015-12-21T18:09:18Z</updated>

		<summary type="html">&lt;p&gt;KolesovDmitry: /* Принципы работы и примеры */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Статья|Черновик}}&lt;br /&gt;
&lt;br /&gt;
== Назначение модуля ==&lt;br /&gt;
Модуль r.series.filter -- это модуль для геоинформационной системы GRASS, предназначенный для обработки временных рядов растровых данных, в первую очередь вегетационных индексов. Модуль производит очистку от шумов временных рядов с использованием различных фильтров (медианый фильтр, фильтр Савицкого-Голея). Модуль может использоваться для очистки от шумов временных рядов произвольной природы, однако одной из важных особенностей модуля является поддерка фильтрации данных вегетационных индексов. Для обработки таких рядов модуль реализует процедуру фильтрации, предложенную в статье &amp;quot;Chen J. et al. A simple method for reconstructing a high-quality NDVI time-series data set based on the Savitzky–Golay filter //Remote sensing of Environment. – 2004. – Т. 91. – №. 3. – С. 332-344.&amp;quot;. Основная идея этого фильтра опирается на то, что шумы в значениях вегетационных индексов обычно индуцируются условиями съемки и атмосферными явлениями, которые занижают зачения индекса. В очень упрощенном виде можно сказать, что предлагаемая в указанной статье методика производит отбраковку низких значений индекса и производит фильтрацию по верхним значениям анализируемого временного ряда.&lt;br /&gt;
&lt;br /&gt;
== Установка ==&lt;br /&gt;
Модуль был написан на языке Python и предназначен для работы в GRASS GIS седьмой версии. В модуле используются библиотека [http://docs.scipy.org/doc/scipy/reference/signal.html scipy.signal], входящая в состав пакета [http://www.scipy.org/about.html SciPy]. Поэтому перед началом работы в интерпретатор Python, используемый в GRASS, следует установить SciPy.&lt;br /&gt;
&lt;br /&gt;
После установки SciPy появится возможность установить сам модуль r.series.filter. Данный модуль доступен в репозитории модулей GRASS ADDONS, поэтому его установка производится автоматически, если использовать модуль g.extension (вызываемый из графического интерфейса пользователя или командной строки). Например, можно использовать следущюую команду:&lt;br /&gt;
 g.extension r.series.filter&lt;br /&gt;
В результате модуль будет выкачан и установлен.&lt;br /&gt;
&lt;br /&gt;
== Особенности работы и примеры ==&lt;br /&gt;
&lt;br /&gt;
=== Параметры модуля и их назначение ===&lt;br /&gt;
Модуль находится в состоянии разработки, это означает, что в него будут добавляться новые возможности. На момент написания статьи модуль использует следующие параметры и ключи:&lt;br /&gt;
&lt;br /&gt;
 r.series.filter [-cu] input=string[,string,...] result_prefix=string&lt;br /&gt;
   [method=string] [winsize=value] [order=value] [opt_points=value]&lt;br /&gt;
   [diff_penalty=value] [deriv_penalty=value] [iterations=value]&lt;br /&gt;
   [--overwrite] [--help] [--verbose] [--quiet] [--ui]&lt;br /&gt;
&lt;br /&gt;
 Flags:&lt;br /&gt;
   -c   Try to find optimal parameters for filtering&lt;br /&gt;
   -u   Fit the result curve by upper boundary&lt;br /&gt;
  --o   Allow output files to overwrite existing files&lt;br /&gt;
  --h   Print usage summary&lt;br /&gt;
  --v   Verbose module output&lt;br /&gt;
  --q   Quiet module output&lt;br /&gt;
  --ui  Force launching GUI dialog&lt;br /&gt;
&lt;br /&gt;
 Parameters:&lt;br /&gt;
          input   Raster names of equally spaced time series.&lt;br /&gt;
  result_prefix   Prefix for raster names of filtered X(t)&lt;br /&gt;
         method   Used method&lt;br /&gt;
                  default: savgol&lt;br /&gt;
        winsize   Length of running window for the filter&lt;br /&gt;
                  default: 9&lt;br /&gt;
          order   Order of the Savitzky-Golay filter&lt;br /&gt;
                  default: 2&lt;br /&gt;
     opt_points   Count of random points used for parameter optimization&lt;br /&gt;
                  default: 50&lt;br /&gt;
   diff_penalty   Penalty for difference between original and filtered signals&lt;br /&gt;
                  default: 1.0&lt;br /&gt;
  deriv_penalty   Penalty for big derivates of the filtered signal&lt;br /&gt;
                  default: 1.0&lt;br /&gt;
     iterations   Number of iterations&lt;br /&gt;
                  default: 1&lt;/div&gt;</summary>
		<author><name>KolesovDmitry</name></author>
	</entry>
	<entry>
		<id>https://wiki.gis-lab.info/index.php?title=%D0%9C%D0%BE%D0%B4%D1%83%D0%BB%D1%8C_r.series.filter_%D0%93%D0%98%D0%A1_GRASS&amp;diff=23432</id>
		<title>Модуль r.series.filter ГИС GRASS</title>
		<link rel="alternate" type="text/html" href="https://wiki.gis-lab.info/index.php?title=%D0%9C%D0%BE%D0%B4%D1%83%D0%BB%D1%8C_r.series.filter_%D0%93%D0%98%D0%A1_GRASS&amp;diff=23432"/>
		<updated>2015-12-21T18:04:53Z</updated>

		<summary type="html">&lt;p&gt;KolesovDmitry: /* Установка */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Статья|Черновик}}&lt;br /&gt;
&lt;br /&gt;
== Назначение модуля ==&lt;br /&gt;
Модуль r.series.filter -- это модуль для геоинформационной системы GRASS, предназначенный для обработки временных рядов растровых данных, в первую очередь вегетационных индексов. Модуль производит очистку от шумов временных рядов с использованием различных фильтров (медианый фильтр, фильтр Савицкого-Голея). Модуль может использоваться для очистки от шумов временных рядов произвольной природы, однако одной из важных особенностей модуля является поддерка фильтрации данных вегетационных индексов. Для обработки таких рядов модуль реализует процедуру фильтрации, предложенную в статье &amp;quot;Chen J. et al. A simple method for reconstructing a high-quality NDVI time-series data set based on the Savitzky–Golay filter //Remote sensing of Environment. – 2004. – Т. 91. – №. 3. – С. 332-344.&amp;quot;. Основная идея этого фильтра опирается на то, что шумы в значениях вегетационных индексов обычно индуцируются условиями съемки и атмосферными явлениями, которые занижают зачения индекса. В очень упрощенном виде можно сказать, что предлагаемая в указанной статье методика производит отбраковку низких значений индекса и производит фильтрацию по верхним значениям анализируемого временного ряда.&lt;br /&gt;
&lt;br /&gt;
== Установка ==&lt;br /&gt;
Модуль был написан на языке Python и предназначен для работы в GRASS GIS седьмой версии. В модуле используются библиотека [http://docs.scipy.org/doc/scipy/reference/signal.html scipy.signal], входящая в состав пакета [http://www.scipy.org/about.html SciPy]. Поэтому перед началом работы в интерпретатор Python, используемый в GRASS, следует установить SciPy.&lt;br /&gt;
&lt;br /&gt;
После установки SciPy появится возможность установить сам модуль r.series.filter. Данный модуль доступен в репозитории модулей GRASS ADDONS, поэтому его установка производится автоматически, если использовать модуль g.extension (вызываемый из графического интерфейса пользователя или командной строки). Например, можно использовать следущюую команду:&lt;br /&gt;
 g.extension r.series.filter&lt;br /&gt;
В результате модуль будет выкачан и установлен.&lt;br /&gt;
&lt;br /&gt;
== Принципы работы и примеры ==&lt;/div&gt;</summary>
		<author><name>KolesovDmitry</name></author>
	</entry>
	<entry>
		<id>https://wiki.gis-lab.info/index.php?title=%D0%9C%D0%BE%D0%B4%D1%83%D0%BB%D1%8C_r.series.filter_%D0%93%D0%98%D0%A1_GRASS&amp;diff=23431</id>
		<title>Модуль r.series.filter ГИС GRASS</title>
		<link rel="alternate" type="text/html" href="https://wiki.gis-lab.info/index.php?title=%D0%9C%D0%BE%D0%B4%D1%83%D0%BB%D1%8C_r.series.filter_%D0%93%D0%98%D0%A1_GRASS&amp;diff=23431"/>
		<updated>2015-12-21T17:58:49Z</updated>

		<summary type="html">&lt;p&gt;KolesovDmitry: /* Установка */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Статья|Черновик}}&lt;br /&gt;
&lt;br /&gt;
== Назначение модуля ==&lt;br /&gt;
Модуль r.series.filter -- это модуль для геоинформационной системы GRASS, предназначенный для обработки временных рядов растровых данных, в первую очередь вегетационных индексов. Модуль производит очистку от шумов временных рядов с использованием различных фильтров (медианый фильтр, фильтр Савицкого-Голея). Модуль может использоваться для очистки от шумов временных рядов произвольной природы, однако одной из важных особенностей модуля является поддерка фильтрации данных вегетационных индексов. Для обработки таких рядов модуль реализует процедуру фильтрации, предложенную в статье &amp;quot;Chen J. et al. A simple method for reconstructing a high-quality NDVI time-series data set based on the Savitzky–Golay filter //Remote sensing of Environment. – 2004. – Т. 91. – №. 3. – С. 332-344.&amp;quot;. Основная идея этого фильтра опирается на то, что шумы в значениях вегетационных индексов обычно индуцируются условиями съемки и атмосферными явлениями, которые занижают зачения индекса. В очень упрощенном виде можно сказать, что предлагаемая в указанной статье методика производит отбраковку низких значений индекса и производит фильтрацию по верхним значениям анализируемого временного ряда.&lt;br /&gt;
&lt;br /&gt;
== Установка ==&lt;br /&gt;
Модуль был написан на языке Python и предназначен для работы в GRASS GIS седьмой версии. В модуле используются библиотека [http://docs.scipy.org/doc/scipy/reference/signal.html scipy.signal], входящая в состав пакета [http://www.scipy.org/about.html SciPy]. Поэтому перед началом работы в интерпретатор Python, используемый в GRASS, следует установить SciPy.&lt;br /&gt;
&lt;br /&gt;
== Принципы работы и примеры ==&lt;/div&gt;</summary>
		<author><name>KolesovDmitry</name></author>
	</entry>
	<entry>
		<id>https://wiki.gis-lab.info/index.php?title=%D0%9C%D0%BE%D0%B4%D1%83%D0%BB%D1%8C_r.series.filter_%D0%93%D0%98%D0%A1_GRASS&amp;diff=23430</id>
		<title>Модуль r.series.filter ГИС GRASS</title>
		<link rel="alternate" type="text/html" href="https://wiki.gis-lab.info/index.php?title=%D0%9C%D0%BE%D0%B4%D1%83%D0%BB%D1%8C_r.series.filter_%D0%93%D0%98%D0%A1_GRASS&amp;diff=23430"/>
		<updated>2015-12-21T17:43:05Z</updated>

		<summary type="html">&lt;p&gt;KolesovDmitry: /* Назначение модуля */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Статья|Черновик}}&lt;br /&gt;
&lt;br /&gt;
== Назначение модуля ==&lt;br /&gt;
Модуль r.series.filter -- это модуль для геоинформационной системы GRASS, предназначенный для обработки временных рядов растровых данных, в первую очередь вегетационных индексов. Модуль производит очистку от шумов временных рядов с использованием различных фильтров (медианый фильтр, фильтр Савицкого-Голея). Модуль может использоваться для очистки от шумов временных рядов произвольной природы, однако одной из важных особенностей модуля является поддерка фильтрации данных вегетационных индексов. Для обработки таких рядов модуль реализует процедуру фильтрации, предложенную в статье &amp;quot;Chen J. et al. A simple method for reconstructing a high-quality NDVI time-series data set based on the Savitzky–Golay filter //Remote sensing of Environment. – 2004. – Т. 91. – №. 3. – С. 332-344.&amp;quot;. Основная идея этого фильтра опирается на то, что шумы в значениях вегетационных индексов обычно индуцируются условиями съемки и атмосферными явлениями, которые занижают зачения индекса. В очень упрощенном виде можно сказать, что предлагаемая в указанной статье методика производит отбраковку низких значений индекса и производит фильтрацию по верхним значениям анализируемого временного ряда.&lt;br /&gt;
&lt;br /&gt;
== Установка ==&lt;br /&gt;
&lt;br /&gt;
== Принципы работы и примеры ==&lt;/div&gt;</summary>
		<author><name>KolesovDmitry</name></author>
	</entry>
	<entry>
		<id>https://wiki.gis-lab.info/index.php?title=%D0%9C%D0%BE%D0%B4%D1%83%D0%BB%D1%8C_r.series.filter_%D0%93%D0%98%D0%A1_GRASS&amp;diff=23429</id>
		<title>Модуль r.series.filter ГИС GRASS</title>
		<link rel="alternate" type="text/html" href="https://wiki.gis-lab.info/index.php?title=%D0%9C%D0%BE%D0%B4%D1%83%D0%BB%D1%8C_r.series.filter_%D0%93%D0%98%D0%A1_GRASS&amp;diff=23429"/>
		<updated>2015-12-21T17:25:02Z</updated>

		<summary type="html">&lt;p&gt;KolesovDmitry: /* Назначение модуля */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Статья|Черновик}}&lt;br /&gt;
&lt;br /&gt;
== Назначение модуля ==&lt;br /&gt;
Модуль r.series.filter -- это модуль для геоинформационной системы GRASS.&lt;br /&gt;
&lt;br /&gt;
== Установка ==&lt;br /&gt;
&lt;br /&gt;
== Принципы работы и примеры ==&lt;/div&gt;</summary>
		<author><name>KolesovDmitry</name></author>
	</entry>
	<entry>
		<id>https://wiki.gis-lab.info/index.php?title=%D0%9C%D0%BE%D0%B4%D1%83%D0%BB%D1%8C_r.series.filter_%D0%93%D0%98%D0%A1_GRASS&amp;diff=23428</id>
		<title>Модуль r.series.filter ГИС GRASS</title>
		<link rel="alternate" type="text/html" href="https://wiki.gis-lab.info/index.php?title=%D0%9C%D0%BE%D0%B4%D1%83%D0%BB%D1%8C_r.series.filter_%D0%93%D0%98%D0%A1_GRASS&amp;diff=23428"/>
		<updated>2015-12-21T17:11:32Z</updated>

		<summary type="html">&lt;p&gt;KolesovDmitry: Новая страница: «{{Статья|Черновик}}  == Назначение модуля ==  == Установка ==  == Принципы работы и примеры ==»&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Статья|Черновик}}&lt;br /&gt;
&lt;br /&gt;
== Назначение модуля ==&lt;br /&gt;
&lt;br /&gt;
== Установка ==&lt;br /&gt;
&lt;br /&gt;
== Принципы работы и примеры ==&lt;/div&gt;</summary>
		<author><name>KolesovDmitry</name></author>
	</entry>
	<entry>
		<id>https://wiki.gis-lab.info/index.php?title=GISConf_-_%D1%81%D0%BB%D1%83%D0%B6%D0%B1%D0%B0_%D0%BF%D0%BE%D0%BC%D0%BE%D1%89%D0%B8&amp;diff=22922</id>
		<title>GISConf - служба помощи</title>
		<link rel="alternate" type="text/html" href="https://wiki.gis-lab.info/index.php?title=GISConf_-_%D1%81%D0%BB%D1%83%D0%B6%D0%B1%D0%B0_%D0%BF%D0%BE%D0%BC%D0%BE%D1%89%D0%B8&amp;diff=22922"/>
		<updated>2015-10-21T16:53:30Z</updated>

		<summary type="html">&lt;p&gt;KolesovDmitry: /* Эксперты */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;На конференции Открытые ГИС планируется создать &amp;quot;Службу помощи&amp;quot; - отдельную стойку или стол, где каждый сможет подойти и задать свои вопросы одному из экспертов.&lt;br /&gt;
&lt;br /&gt;
==Как работает==&lt;br /&gt;
В этой секции работает группа умудренных экспертов, каждый из которых готов потратить от 30 до 60 минут своего времени на ответы по ГИС и около тематики.&lt;br /&gt;
Предполагается помещение на 5-7 человек для консультаций. На экране ноутбука (идеально - компьютер с двумя мониторами) эксперт может показать какие-то наглядные вещи.&lt;br /&gt;
Данный формат общения будет работать как минимум один день конференции.&lt;br /&gt;
&lt;br /&gt;
Компетенция эксперта может быть как технологической, так и тематической (например, GeoServer или Геомаркетинг). Для каждого эксперта можно определить круг компетенций (основная, второстепенные, &amp;quot;где-то что-то слышал&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
==Эксперты==&lt;br /&gt;
Имя и Фамилия. День, в который готов выступить. Время, которое готов потратить. '''Основные компетенции'''. Второстепенные компетенции. ''Ориентируюсь''. &lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Имя&lt;br /&gt;
! Даты&lt;br /&gt;
! Время, ч&lt;br /&gt;
! Компетенции (основные)&lt;br /&gt;
! Компетенции (второстепенные)&lt;br /&gt;
|-&lt;br /&gt;
|Андрей Жуков&lt;br /&gt;
|21-22&lt;br /&gt;
|2&lt;br /&gt;
|GeoServer, картографические стили&lt;br /&gt;
|QGIS, Python&lt;br /&gt;
|-&lt;br /&gt;
|Максим Дубинин&lt;br /&gt;
|21-22&lt;br /&gt;
|0.5-1&lt;br /&gt;
|Развертывание, лицензирование&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|Дмитрий Колесов&lt;br /&gt;
|21-22&lt;br /&gt;
|1&lt;br /&gt;
|GRASS GIS, обработка данных&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;/div&gt;</summary>
		<author><name>KolesovDmitry</name></author>
	</entry>
	<entry>
		<id>https://wiki.gis-lab.info/index.php?title=%D0%92%D1%8B%D0%B7%D0%BE%D0%B2_GRASS_GIS_%D0%B8%D0%B7_%D1%81%D0%BA%D1%80%D0%B8%D0%BF%D1%82%D0%B0_%D0%BD%D0%B0_Python&amp;diff=22114</id>
		<title>Вызов GRASS GIS из скрипта на Python</title>
		<link rel="alternate" type="text/html" href="https://wiki.gis-lab.info/index.php?title=%D0%92%D1%8B%D0%B7%D0%BE%D0%B2_GRASS_GIS_%D0%B8%D0%B7_%D1%81%D0%BA%D1%80%D0%B8%D0%BF%D1%82%D0%B0_%D0%BD%D0%B0_Python&amp;diff=22114"/>
		<updated>2015-06-22T07:16:35Z</updated>

		<summary type="html">&lt;p&gt;KolesovDmitry: /* Запуск команд */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Статья|Опубликована|grass-external-scripting}}&lt;br /&gt;
&lt;br /&gt;
Очень часто работа с GRASS GIS происходит в интерактивном режиме, когда пользователь вводит команды в консоли или вызывает их через графический интерфейс пользователя. При этом часто повторяемые действия пользователь может автоматизировать, создав скрипт, который будет доступен для повторного использования. GRASS GIS поддерживает большое количество языков программирования, на которых можно создавать пользовательские скрипты, наиболее распространенными из них являются скриптовый язык командной оболочки (shell, bash) и Python. Пример создания скрипта на языке Python описывается в статье [http://gis-lab.info/qa/grass64-python.html Создание скрипта на Python для ГИС GRASS]. После создания скрипта пользователь может запускать его из консоли, в которой запущена ГИС GRASS.&lt;br /&gt;
&lt;br /&gt;
Однако, иногда может потребоваться полностью автономный скрипт, который может работать, даже если консоль GRASS GIS не запущена, например, при вызове скрипта из какой-либо своей программы. Это может быть полезным при автоматической обработке геоданных, когда нужно по расписанию обновлять, генерировать или анализировать данные. Возможно также создание таких скриптов, которые автоматически создают проект GRASS, выполняют определенную работу (импортируют данные, анализируют их) и, по завершении обработки, удаляют проекты. Методика создания подобных скриптов подробно описана в статье [http://geoinformatics.fsv.cvut.cz/gwiki/On_scripting_GRASS_GIS:_Building_location-independent_command_line_tools On scripting GRASS GIS: Building location-independent command line tools]. В данной статье рассматривается лишь часть методов, описанных вышеуказанной работе -- создание скрипта, способного использовать готовые проекты GRASS.&lt;br /&gt;
&lt;br /&gt;
Пример подобного скрипта, написанного на shell, приводится в [http://gis-lab.info/forum/viewtopic.php?f=40&amp;amp;t=9303 рецепте], данная статья описывает решение данной задачи для языка Python. Нужно отметить, что описываемый подход можно применить к любому языку программирования, а не только к shell или Python.&lt;br /&gt;
&lt;br /&gt;
== Этапы работы ==&lt;br /&gt;
В общем случае внешний по отношению к ГИС GRASS скрипт должен реализовать следующие основные этапы обработки:&lt;br /&gt;
# Задать значения переменным окружения, которые используются в GRASS GIS (PATH, GISRC и т.д.). Этот этап служит инициализацией и необходим для того, чтобы скрипт был в состоянии определить, где находятся файлы проекта и модули ГИС GRASS и, как следствие, мог их использовать в своей работе.&lt;br /&gt;
# Собственно сама обработка данных, состоящая из последовательности команд GRASS GIS. Это основная часть скрипта, в которой пользователь задает последовательность действий, необходимых для того, чтобы выполнить планируемую обработку данных.&lt;br /&gt;
# Очистка системы от временных файлов. После выполнения необходимого анализа или действий над исходными данными все вспомогательные файлы следует удалить, чтобы не &amp;quot;мусорить&amp;quot; в системе.&lt;br /&gt;
&lt;br /&gt;
Данные этапы более подробно рассматриваются в последующих подразделах.&lt;br /&gt;
&lt;br /&gt;
== Инициализация ==&lt;br /&gt;
=== Теория ===&lt;br /&gt;
Описание этапа инициализации рассматривается в [http://grasswiki.osgeo.org/wiki/GRASS_and_Python#Creating_Python_scripts_that_call_GRASS_functionality_from_outside Wiki проекта GRASS]. В этом подразделе приводится краткий перевод этой страницы.&lt;br /&gt;
&lt;br /&gt;
Как было сказано выше, цель этапа инициализации -- установить переменные окружения так, чтобы скрипт мог получить информацию о том, где искать библиотеки GRASS и файлы проекта. Поэтому нужно задать следующие переменные:&lt;br /&gt;
* GISBASE путь к каталогу, в котором установлена ГИС GRASS. Узнать значение переменной можно, если запустить GRASS и в консоли выполнить команду: &amp;lt;code&amp;gt;echo $GISBASE&amp;lt;/code&amp;gt;&lt;br /&gt;
* PATH системная переменная окружения $PATH, в которой нужно прописать пути каталогам, в которых следует искать скрипты и команды GRASS.&lt;br /&gt;
* LD_LIBRARY_PATH переменная, в которой перечисляются все каталоги содержащие пользовательские динамические библиотеки.&lt;br /&gt;
* GISRC переменная, содержащая путь к файлу, в котором задаются путь к проекту, области и набору карт. Для ГИС GRASS 6.x этот файл обычно называется .grassrc6, но можно создать свой собственный и прописать туда необходимые сведения. В последнем случае в файле должны быть установлены значения следующих переменных GISDBASE, LOCATION, MAPSET (посмотреть формат файла можно, открыв его в текстовом редакторе).&lt;br /&gt;
&lt;br /&gt;
Если речь идет о скрипте на языке Python, то нужно задать еще переменные окружения, описывающие, где хранится интерпретатор языка:&lt;br /&gt;
* PYTHONLIB  путь к интерпретатору Python.&lt;br /&gt;
* PYTHONPATH эта переменная должна указывать на %GISBASE%\etc\python.&lt;br /&gt;
&lt;br /&gt;
Например, для системы Windows эти переменые могут быть такими (зависит от конкретных путей установки GRASS):&lt;br /&gt;
 GISBASE= C:\GRASS-64&lt;br /&gt;
 GISRC= C:\Documents and Settings\user\.grassrc6&lt;br /&gt;
 LD_LIBRARY_PATH= C:\GRASS-64\lib&lt;br /&gt;
 PATH= C:\GRASS-64\etc;C:\GRASS-64\etc\python;C:\GRASS-64\lib;C:\GRASS-64\bin;C:\GRASS-64\extralib;C:\GRASS-64\msys\bin;C:\Python26;&lt;br /&gt;
 PYTHONLIB= C:\Python26&lt;br /&gt;
 PYTHONPATH= C:\GRASS-64\etc\python&lt;br /&gt;
 GRASS_SH= C:\GRASS-64\msys\bin\sh.exe&lt;br /&gt;
&lt;br /&gt;
Для Linux переменные могут быть:&lt;br /&gt;
 export GISBASE=&amp;quot;/usr/local/grass-6.4.svn/&amp;quot;&lt;br /&gt;
 export PATH=&amp;quot;$PATH:$GISBASE/bin:$GISBASE/scripts&amp;quot;&lt;br /&gt;
 export LD_LIBRARY_PATH=&amp;quot;$LD_LIBRARY_PATH:$GISBASE/lib&amp;quot;&lt;br /&gt;
 export GISRC=&amp;quot;$HOME/.grassrc6&amp;quot;&lt;br /&gt;
 export PYTHONPATH=&amp;quot;$PYTHONPATH:$GISBASE/etc/python&amp;quot;&lt;br /&gt;
&lt;br /&gt;
=== Реализация ===&lt;br /&gt;
Язык Python несколько облегчает общую схему работы, рассмотренную в предыдущем подразделе, в частности, пользователь не обязан создавать файл с описанием путей проекта и, как следствие, этап очистки системы может быть также пропущен. &lt;br /&gt;
&lt;br /&gt;
Предположим, что пользователь работает с набором данных [[http://gis-lab.info/qa/geosample.html geosample]], и пусть $HOME/grassdata -- каталог, в котором хранится данный набор. Тогда для установки переменных можно воспользоваться следующими командами на языке Python:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
import os&lt;br /&gt;
import sys&lt;br /&gt;
gisbase = os.environ['GISBASE'] = &amp;quot;/usr/lib/grass64&amp;quot;&lt;br /&gt;
gisdbase = os.path.join(os.environ['HOME'], &amp;quot;grassdata&amp;quot;)&lt;br /&gt;
location = &amp;quot;geosample&amp;quot;&lt;br /&gt;
mapset   = &amp;quot;PERMANENT&amp;quot;&lt;br /&gt;
sys.path.append(os.path.join(os.environ['GISBASE'], &amp;quot;etc&amp;quot;, &amp;quot;python&amp;quot;))&lt;br /&gt;
import grass.script as grass&lt;br /&gt;
import grass.script.setup as gsetup&lt;br /&gt;
gsetup.init(gisbase,&lt;br /&gt;
           gisdbase, location, mapset)&lt;br /&gt;
print grass.gisenv()&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Третья строка задает переменную окружения GISBASE. Четвертая, пятая и шестая строки задают переменные путей к проекту GRASS, которые будут использоваться в команде ''gsetup.init''. Обратите внимание на то, что использование команды ''gsetup.init'' избавляет программиста от создания/редактирования файла путей к проекту (см. переменную GISRC).&lt;br /&gt;
&lt;br /&gt;
В Windows при установке GRASS через OSGeo4W/NextGIS_QGIS набор переменных может выглядеть так:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
gisbase = os.environ['GISBASE'] = &amp;quot;c:/tools/NextGIS_QGIS/apps/grass/grass-6.4.4/&amp;quot;&lt;br /&gt;
gisdbase = os.environ['GISDBASE'] = &amp;quot;e:/users/maxim/thematic/dhi/&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Запускать python в этом случае нужно после OSGeo4W.bat.&lt;br /&gt;
&lt;br /&gt;
== Запуск команд ==&lt;br /&gt;
Здесь происходит собственно обработка данных, которая зависит от целей и задач пользователя. Пользователь может вызывать любые команды GRASS или запускать сторонние модули Python или написать свой собственный обработчик.&lt;br /&gt;
&lt;br /&gt;
Поскольку цель данной статьи -- продемонстрировать этапы предварительной подготовки, необходимые для вызова GRASS GIS из скрипта на Python, а не выполнение того или иного анализа данных, то в качестве пример обработки будем использовать &amp;quot;заглушку&amp;quot;, т.е. демонстрационный пример вызова команд GRASS GIS. В качестве такого простого примера покажем, как можно произвести циклическую обработку растров. Следующий кусок кода производит поиск всех растровых файлов и:&lt;br /&gt;
# Выводит называние растра на экран&lt;br /&gt;
# Выводит статистику по данному растру (значение ячейки растра и общая площадь ячеек с данным значением)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
grass.message('Raster maps:')&lt;br /&gt;
for rast in grass.list_strings(type = 'rast'):&lt;br /&gt;
    print rast&lt;br /&gt;
    grass.run_command('r.stats', input=rast, flags='a')&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Читатель легко может заменить эти команды на свои, отражающие суть необходимых ему манипуляций с данными. Обратите внимание, что флаги (например --o перезапись) передаются в flags.&lt;br /&gt;
&lt;br /&gt;
Для обработки выводов команд GRASS может понадобится работа с каналами (пайпами), например для получения списка растров области в виде массива:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
result = []&lt;br /&gt;
p = grass.pipe_command('g.mlist', type = 'rast', quiet=True)&lt;br /&gt;
for line in p.stdout:&lt;br /&gt;
    result.append(line)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Для некоторых команд GRASS параметры передаются не в виде &amp;quot;ключ - значение&amp;quot;, а простым аргументом, в этом случае запуск осуществляется не через run_command, а саму команду, например для r.mapcalc:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
grass.mapcalc('dh3 = std/ave')&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Очистка системы ==&lt;br /&gt;
Если пользователь в своем скрипте создавал те или иные вспомогательные файлы, то он должен удалить их по окончании работы скрипта. В первую очередь это относится к файлу с указанием путей к проекту, который хранится в переменной GISRC. Однако, если пользователь для настройки путей проекта использовал команду gsetup.init, то данный шаг можно опустить.&lt;br /&gt;
&lt;br /&gt;
== Итоговый скрипт ==&lt;br /&gt;
Окончательный вид скрипта, готового для использования, приводится ниже:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
#!/usr/bin/env python&lt;br /&gt;
# -*- coding: utf-8 -*-&lt;br /&gt;
 &lt;br /&gt;
import os&lt;br /&gt;
import sys&lt;br /&gt;
gisbase = os.environ['GISBASE'] = &amp;quot;/usr/lib/grass64&amp;quot;&lt;br /&gt;
gisdbase = os.path.join(os.environ['HOME'], &amp;quot;grassdata&amp;quot;)&lt;br /&gt;
location = &amp;quot;geosample&amp;quot;&lt;br /&gt;
mapset   = &amp;quot;PERMANENT&amp;quot;&lt;br /&gt;
sys.path.append(os.path.join(os.environ['GISBASE'], &amp;quot;etc&amp;quot;, &amp;quot;python&amp;quot;))&lt;br /&gt;
import grass.script as grass&lt;br /&gt;
import grass.script.setup as gsetup&lt;br /&gt;
gsetup.init(gisbase,&lt;br /&gt;
        gisdbase, location, mapset)&lt;br /&gt;
print grass.gisenv()&lt;br /&gt;
 &lt;br /&gt;
# Обработка&lt;br /&gt;
grass.message('Raster maps:')&lt;br /&gt;
for rast in grass.list_strings(type = 'rast'):&lt;br /&gt;
    print rast&lt;br /&gt;
    grass.run_command('r.stats', input=rast, flags='a')&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Ссылки ==&lt;br /&gt;
* [http://grasswiki.osgeo.org/wiki/Working_with_GRASS_without_starting_it_explicitly Working with GRASS without starting it explicitly (англ.)]&lt;br /&gt;
* [http://gis-lab.info/forum/viewtopic.php?f=40&amp;amp;t=9303 Рецепт создания внешнего для ГИС GRASS скрипта на shell]&lt;/div&gt;</summary>
		<author><name>KolesovDmitry</name></author>
	</entry>
	<entry>
		<id>https://wiki.gis-lab.info/index.php?title=%D0%A0%D0%B0%D0%B7%D1%80%D0%B0%D0%B1%D0%BE%D1%82%D0%BA%D0%B0_%D0%BF%D1%80%D0%BE%D1%81%D1%82%D0%BE%D0%B3%D0%BE_%D1%80%D0%B0%D1%81%D1%88%D0%B8%D1%80%D0%B5%D0%BD%D0%B8%D1%8F_%D0%B4%D0%BB%D1%8F_QGIS_%D0%BD%D0%B0_Python&amp;diff=22053</id>
		<title>Разработка простого расширения для QGIS на Python</title>
		<link rel="alternate" type="text/html" href="https://wiki.gis-lab.info/index.php?title=%D0%A0%D0%B0%D0%B7%D1%80%D0%B0%D0%B1%D0%BE%D1%82%D0%BA%D0%B0_%D0%BF%D1%80%D0%BE%D1%81%D1%82%D0%BE%D0%B3%D0%BE_%D1%80%D0%B0%D1%81%D1%88%D0%B8%D1%80%D0%B5%D0%BD%D0%B8%D1%8F_%D0%B4%D0%BB%D1%8F_QGIS_%D0%BD%D0%B0_Python&amp;diff=22053"/>
		<updated>2015-06-06T14:17:12Z</updated>

		<summary type="html">&lt;p&gt;KolesovDmitry: /* Разработка */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Статья|Опубликована|qgis-dev-python}}&lt;br /&gt;
{{Аннотация|Описание процесса создания элементарного расширения для QGIS.}}&lt;br /&gt;
&lt;br /&gt;
QGIS — свободная пользовательская ГИС, обладающая развитым API и продвинутой системой расширений (модулей). Модули создаются для расширения функциональности программы. QGIS написана на объектно-ориентированном языке высокого уровня C++. Так же в QGIS встроены привязки (bindings), которые реализуют практически весь функционал QGIS на языке Python. Графический интерфейс пользователя QGIS базируется на библиотеках Qt4. Разработка для QGIS может вестись на двух языках, Python и C++. Для разработки на языке Python необходимы привязки [http://www.riverbankcomputing.co.uk/software/pyqt/intro PyQt], обеспечивающие взаимодействия Python с Qt4. Помимо расширений библиотеки QGIS могут быть также использованы для разработки отдельных приложений, что подробно описано в статье «[http://gis-lab.info/qa/qgis-standalone.html Создание приложения на базе набора библиотек QGIS на Python]».&lt;br /&gt;
&lt;br /&gt;
Данная статья описывает процесс создания каркаса расширения на языке Python. Разработанный каркас можно в дальнейшем использовать как основу для других расширений, выполняющих нужные функции.&lt;br /&gt;
&lt;br /&gt;
Создание расширения состоит из нескольких этапов:&lt;br /&gt;
&lt;br /&gt;
* Идея&lt;br /&gt;
* Создание каркаса&lt;br /&gt;
* Разработка необходимой функциональности.&lt;br /&gt;
* Тестирование&lt;br /&gt;
* Публикация&lt;br /&gt;
&lt;br /&gt;
Задача этой статьи - иллюстрация процесса создания простого расширения, которое:&lt;br /&gt;
* добавит новую кнопку на панель инструментов&lt;br /&gt;
* добавит подменю в меню расширений&lt;br /&gt;
* выполнит простое действие. &lt;br /&gt;
&lt;br /&gt;
Это расширение можно будет использовать как каркас для других будущих, более функциональных расширений. Далее мы более подробно разберем процесс создания по шагам.&lt;br /&gt;
&lt;br /&gt;
=== Получение исходного кода ===&lt;br /&gt;
&lt;br /&gt;
Код расширения, работающий под QGIS 2.0 можно получить в [https://github.com/nextgis/testplugin репозитории GitHub]:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;git clone git@github.com:nextgis/testplugin.git&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Подготовка ===&lt;br /&gt;
&lt;br /&gt;
Для разработки расширения понадобится&lt;br /&gt;
&lt;br /&gt;
* Любой текстовый редактор&lt;br /&gt;
* Python, лучше версии 2.5-2.7.х (3.x не подойдет)&lt;br /&gt;
* QGIS версии 2.0 и выше, для проверки работоспособности расширения.&lt;br /&gt;
&lt;br /&gt;
Если вы установили QGIS с помощью установщика [http://gis-lab.info/qa/qgis-osgeo4w.html osgeo4w] или [http://nextgis.ru/nextgis-qgis NextGIS QGIS], то у вас уже есть все необходимое для разработки. Ничего дополнительно устанавливать не нужно.&lt;br /&gt;
&lt;br /&gt;
Разработку можно вести прямо в папке, где хранятся расширения или переместить его в нее после разработки, в QGIS эта папка либо &amp;lt;tt&amp;gt;QGIS\python\plugins&amp;lt;/tt&amp;gt; либо &amp;lt;/tt&amp;gt;C:\Documents and Settings\username\.qgis2\python\plugins\&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В папке с плагинами необходимо создать новую, назвав ее так, чтобы бы по названию можно было легко определить, что именно делает расширение. Назовем нашу папку &amp;lt;code&amp;gt;testplugin&amp;lt;/code&amp;gt;. Это название следует запомнить, так как оно будет фигурировать в различных компонентах кода.&lt;br /&gt;
&lt;br /&gt;
Перед разработкой, нам нужно создать в этой папке несколько новых, пока пустых текстовых файлов:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;tt&amp;gt;__init__.py&amp;lt;/tt&amp;gt; — начальная точка, создаёт экземпляр основного класса, который передается в QGIS&lt;br /&gt;
* &amp;lt;tt&amp;gt;testplugin.py&amp;lt;/tt&amp;gt; — основной код расширения. Содержит всю информацию о всех действиях расширения.&lt;br /&gt;
* &amp;lt;tt&amp;gt;resources.qrc&amp;lt;/tt&amp;gt; — xml файл, создаваемый Qt Designer или вручную и содержащий относительные пути к ресурсам расширения, формам, иконкам и т.п. Компилируется в py перед созданием пакета плагина.&lt;br /&gt;
* &amp;lt;tt&amp;gt;metadata.txt&amp;lt;/tt&amp;gt; — описание модуля, содержит информацию о расширении, версию, имя разработчика&lt;br /&gt;
&lt;br /&gt;
Помимо этих файлов, если расширение использует формы, могут также присутствовать файлы:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;tt&amp;gt;form.ui&amp;lt;/tt&amp;gt; — форма созданная с помощью Qt Designer&lt;br /&gt;
* &amp;lt;tt&amp;gt;form.py&amp;lt;/tt&amp;gt; — она же, скомпилированная в виде программы на языке Python&lt;br /&gt;
&lt;br /&gt;
Для примера из данной статьи эти файлы не понадобятся.&lt;br /&gt;
&lt;br /&gt;
Итак, пустые файлы созданы и лежат в нужной папке.&lt;br /&gt;
&lt;br /&gt;
Перед разработкой, отредактируем файл metadata.txt. Этот файл содержит информацию о расширении, такую как его название &amp;lt;tt&amp;gt;name&amp;lt;/tt&amp;gt;, т.е. то, как он будет показываться в Менеджере модулей, его описание &amp;lt;tt&amp;gt;description&amp;lt;/tt&amp;gt;, показывается там же. Нужно также указать минимальную версию QGIS, для которой разработано это расширение (при попытке загрузки в QGIS меньшей версии плагин будет отключен) и другие параметры:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;[general]&lt;br /&gt;
name=TestPlugin&lt;br /&gt;
description=This plugin is for testing and templating purposes&lt;br /&gt;
category=Vector&lt;br /&gt;
version=0.0.2&lt;br /&gt;
qgisMinimumVersion=2.0&lt;br /&gt;
&lt;br /&gt;
author=NextGIS&lt;br /&gt;
email=info@nextgis.org&lt;br /&gt;
&lt;br /&gt;
icon=icons/icon.png&lt;br /&gt;
&lt;br /&gt;
tags=testing,template&lt;br /&gt;
&lt;br /&gt;
homepage=http://gis-lab.info/qa/qgis-dev-python.html&lt;br /&gt;
tracker=https://github.com/nextgis/testplugin/issues&lt;br /&gt;
repository=https://github.com/nextgis/testplugin&lt;br /&gt;
&lt;br /&gt;
experimental=True&lt;br /&gt;
deprecated=False&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Разработка ===&lt;br /&gt;
&lt;br /&gt;
Разработка начинается с файла &amp;lt;tt&amp;gt;__init__.py&amp;lt;/tt&amp;gt;. Главным фрагментом кода является импорт исполняемой части расширения, содержащейся в файле &amp;lt;tt&amp;gt;plugin.py&amp;lt;/tt&amp;gt; (поэтому &amp;lt;tt&amp;gt;from testplugin&amp;lt;/tt&amp;gt;) и содержащей всю содержательную часть кода.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
def classFactory(iface):&lt;br /&gt;
  # Import class TestPlugin from file testplugin.py&lt;br /&gt;
  from testplugin import TestPlugin&lt;br /&gt;
  return TestPlugin(iface)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Название главного импортируемого класса &amp;lt;tt&amp;gt;TestPlugin&amp;lt;/tt&amp;gt; должно быть равно названию класса в коде &amp;lt;tt&amp;gt;testplugin.py&amp;lt;/tt&amp;gt;, название — регистрозависимое, если вызывается &amp;lt;tt&amp;gt;TestPlugin&amp;lt;/tt&amp;gt;, а класс носит название &amp;lt;tt&amp;gt;testplugin&amp;lt;/tt&amp;gt;, будет выдано сообщение об ошибке.&lt;br /&gt;
&lt;br /&gt;
Рассмотрим &amp;lt;tt&amp;gt;testplugin.py&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Как и во всех программах на языке Python, все начинается с импорта необходимых для работы классов, в нашем случае это будут классы PyQt — обертки для Qt на языке Python: PyQt4.QtCore и PyQt4.QtGui, активно используемые QGIS и сами классы QGIS: qgis.core&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
# -*- coding: utf-8 -*-&lt;br /&gt;
from PyQt4.QtCore import *&lt;br /&gt;
from PyQt4.QtGui import *&lt;br /&gt;
from qgis.core import *&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Помимо этого нужно также импортировать ресурсы самого расширения, в нашем случае они будут задаваться через &amp;lt;tt&amp;gt;resources.py&amp;lt;/tt&amp;gt;, как его создать мы разберем чуть позже.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
import resources&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
После импорта идет раздел главного класса, импортируемого в &amp;lt;tt&amp;gt;__init__.py&amp;lt;/tt&amp;gt; и содержащего все нужные функции. Необходимо обратить внимание, что название класса должно быть равно названию используемому для его вызова в &amp;lt;tt&amp;gt;__init__.py&amp;lt;/tt&amp;gt;. Определение функции начинается с ключевого слова &amp;lt;tt&amp;gt;def&amp;lt;/tt&amp;gt;, за которым следует имя функции и ее аргументы.&lt;br /&gt;
&lt;br /&gt;
Объявим наш основной класс и функцию инициализации:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
class TestPlugin:&lt;br /&gt;
&lt;br /&gt;
  def __init__(self, iface):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Initialize class&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    # сохраним ссылку на интерфейс QGIS//save reference to QGIS interface&lt;br /&gt;
    self.iface = iface&lt;br /&gt;
    self.qgsVersion = unicode(QGis.QGIS_VERSION_INT)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Одна из важнейших функций — создание элементов интерфейса расширения &amp;lt;tt&amp;gt;initGui&amp;lt;/tt&amp;gt;. При загрузке расширения к пользовательскому интерфейсу &amp;lt;tt&amp;gt;iface.self&amp;lt;/tt&amp;gt; могут добавляться кнопки &amp;lt;tt&amp;gt;addToolBarIcon&amp;lt;/tt&amp;gt; или строки в меню «Модули», &amp;lt;tt&amp;gt;addPluginToMenu&amp;lt;/tt&amp;gt;. Не забываем документировать функции с помощью тройных кавычек.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
import resources&lt;br /&gt;
def initGui(self):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Инициализируем графический интерфейс пользователя&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    #проверим, не пытаются ли запустить плагин из QGIS версии ниже 2.0//check if the plugin is ran below 2.0&lt;br /&gt;
    if int(self.qgsVersion) &amp;lt; 10900:&lt;br /&gt;
        qgisVersion = self.qgsVersion[0] + &amp;quot;.&amp;quot; + self.qgsVersion[2] + &amp;quot;.&amp;quot; + self.qgsVersion[3]&lt;br /&gt;
        QMessageBox.warning(self.iface.mainWindow(),&lt;br /&gt;
                            &amp;quot;TestPlugin&amp;quot;, &amp;quot;Error&amp;quot;,&lt;br /&gt;
                            &amp;quot;TestPlugin&amp;quot;, &amp;quot;QGIS %s detected.\n&amp;quot; % (qgisVersion) +&lt;br /&gt;
                            &amp;quot;TestPlugin&amp;quot;, &amp;quot;This version of TestPlugin requires at least QGIS version 2.0.\nPlugin will not be enabled.&amp;quot;)&lt;br /&gt;
        return None&lt;br /&gt;
&lt;br /&gt;
    # create action that will be run by the plugin//создадим действие, которое будет запускать конфигурацию расширения&lt;br /&gt;
    self.action = QAction(&amp;quot;Test plugin&amp;quot;, self.iface.mainWindow())&lt;br /&gt;
    self.action.setIcon(QIcon(&amp;quot;:/icons/icon.png&amp;quot;))&lt;br /&gt;
    self.action.setWhatsThis(&amp;quot;Configuration for test plugin&amp;quot;)&lt;br /&gt;
    self.action.setStatusTip(&amp;quot;This is status tip&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
    # добавим пункт в меню инструментов Vector//add plugin menu to Vector toolbar&lt;br /&gt;
    self.iface.addPluginToVectorMenu(&amp;quot;TestPlugin&amp;quot;,self.action)&lt;br /&gt;
    &lt;br /&gt;
    # добавим кнопку на панель инструментов Vector//add icon to new menu item in Vector toolbar&lt;br /&gt;
    self.iface.addVectorToolBarIcon(self.action)&lt;br /&gt;
&lt;br /&gt;
    # связь действия с функцией run//connect action to the run method&lt;br /&gt;
    self.action.triggered.connect(self.run)&lt;br /&gt;
      &lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Следующая важная функция расширения описывает то, что происходит при его выгрузке, выключении через Менеджер модулей — &amp;lt;tt&amp;gt;unload(self)&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
  def unload(self):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Действия при выгрузке расширения&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    # удалить меню расширения и иконку//remove menu and icon from the menu&lt;br /&gt;
    self.iface.removeVectorToolBarIcon(self.action)&lt;br /&gt;
    self.iface.removePluginVectorMenu(&amp;quot;TestPlugin&amp;quot;,self.action)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
И наконец функция выполняющая единственное действие в нашем расширении — &amp;lt;tt&amp;gt;run()&amp;lt;/tt&amp;gt;. Функция создаёт строку сообщения и показывает ее в &amp;lt;tt&amp;gt;QMessageBox&amp;lt;/tt&amp;gt; в главном окне программы.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
  def run(self):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Действия при запуске расширения&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    # создать и показать сообщение//create a string and show it&lt;br /&gt;
    infoString = &amp;quot;This is a test&amp;quot;&lt;br /&gt;
    QMessageBox.information(self.iface.mainWindow(),&amp;quot;About&amp;quot;,infoString)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Какие функции из API доступны через Python ===&lt;br /&gt;
&lt;br /&gt;
К сожалению, не все функции API QGIS доступны через Python (через C++ доступны все). Чтобы определить, доступны ли конкретные классы и функции, необходимо сначала найти их в документации к API GIS [http://doc.qgis.org/ http://doc.qgis.org]. А затем в консоли Python (Модули\Консоль Python) определить с помощью команды &amp;lt;tt&amp;gt;dir&amp;lt;/tt&amp;gt; видны ли эти классы и функции из Python.&lt;br /&gt;
&lt;br /&gt;
Например, определим доступные классы:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
import qgis.core&lt;br /&gt;
dir(qgis.core)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Результат:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
['DEFAULT_LINE_WIDTH', 'DEFAULT_POINT_SIZE', 'DEFAULT_SEGMENT_EPSILON', 'ELLPS_PREFIX_LEN', 'GEOCRS_ID', 'GEOPROJ4', 'GEOSRID', 'GEOWKT', 'GEO_EPSG_CRS_AUTHID', 'GEO_EPSG_CRS_ID', 'GEO_NONE', 'LAT_PREFIX_LEN', 'MINIMUM_POINT_SIZE', 'NULL', 'PROJECT_SCALES', 'PROJ_PREFIX_LEN', 'QGis', 'QgsAbstractCacheIndex', 'QgsAbstractFeatureIterator', 'QgsAction', 'QgsAddRemoveItemCommand', 'QgsAddRemoveMultiFrameCommand', 'QgsApplication', 'QgsAtlasComposition', 'QgsAttributeAction', 'QgsAttributeEditorContainer', 'QgsAttributeEditorElement', 'QgsAttributeEditorField', 'QgsBilinearRasterResampler', 'QgsBrightnessContrastFilter', 'QgsBrowserModel', 'QgsCRSCache', 'QgsCacheIndexFeatureId', 'QgsCachedFeatureIterator', 'QgsCachedFeatureWriterIterator', 'QgsCategorizedSymbolRendererV2', 'QgsCentroidFillSymbolLayerV2', 'QgsClipToMinMaxEnhancement', 'QgsClipper', 'QgsColorBrewerPalette', 'QgsColorRampShader', 'QgsComposerArrow', 'QgsComposerAttributeTable', 'QgsComposerAttributeTableCompare', 'QgsComposerEffect', 'QgsComposerFrame', 'QgsComposerGroupItem', 'QgsComposerHtml', 'QgsComposerItem', 'QgsComposerItemCommand', 'QgsComposerItemGroup', 'QgsComposerLabel', 'QgsComposerLayerItem', 'QgsComposerLegend', 'QgsComposerLegendItem', 'QgsComposerLegendStyle', 'QgsComposerMap', 'QgsComposerMergeCommand', 'QgsComposerMultiFrame', 'QgsComposerMultiFrameCommand', 'QgsComposerPicture', 'QgsComposerRasterSymbolItem', 'QgsComposerScaleBar', 'QgsComposerShape', 'QgsComposerSymbolV2Item', 'QgsComposerTable', 'QgsComposerTextTable', 'QgsComposition', 'QgsContextHelp', 'QgsContrastEnhancement', 'QgsContrastEnhancementFunction', 'QgsCoordinateReferenceSystem', 'QgsCoordinateTransform', 'QgsCoordinateTransformCache', 'QgsCptCityArchive', 'QgsCptCityBrowserModel', 'QgsCptCityCollectionItem', 'QgsCptCityColorRampItem', 'QgsCptCityColorRampV2', 'QgsCptCityDataItem', 'QgsCptCityDirectoryItem', 'QgsCptCitySelectionItem', 'QgsCredentials', 'QgsCredentialsConsole', 'QgsCsException', 'QgsCubicRasterResampler', 'QgsDataCollectionItem', 'QgsDataDefined', 'QgsDataItem', 'QgsDataProvider', 'QgsDataSourceURI', 'QgsDbFilterProxyModel', 'QgsDiagram', 'QgsDiagramInterpolationSettings', 'QgsDiagramLayerSettings', 'QgsDiagramRendererV2', 'QgsDiagramSettings', 'QgsDirectoryItem', 'QgsDirectoryParamWidget', 'QgsDistanceArea', 'QgsDoubleBoxScaleBarStyle', 'QgsEllipseSymbolLayerV2', 'QgsError', 'QgsErrorItem', 'QgsErrorMessage', 'QgsException', 'QgsExpression', 'QgsFavouritesItem', 'QgsFeature', 'QgsFeatureIterator', 'QgsFeatureRendererV2', 'QgsFeatureRequest', 'QgsFeatureStore', 'QgsField', 'QgsFields', 'QgsFillSymbolLayerV2', 'QgsFillSymbolV2', 'QgsFontMarkerSymbolLayerV2', 'QgsFontUtils', 'QgsGPSConnection', 'QgsGPSConnectionRegistry', 'QgsGPSDetector', 'QgsGPSInformation', 'QgsGeometry', 'QgsGeometryCache', 'QgsGeometryValidator', 'QgsGml', 'QgsGmlFeatureClass', 'QgsGmlSchema', 'QgsGpsdConnection', 'QgsGradientStop', 'QgsGraduatedSymbolRendererV2', 'QgsHistogramDiagram', 'QgsHttpTransaction', 'QgsHueSaturationFilter', 'QgsImageFillSymbolLayer', 'QgsLabel', 'QgsLabelAttributes', 'QgsLabelCandidate', 'QgsLabelComponent', 'QgsLabelPosition', 'QgsLabelSearchTree', 'QgsLabelingEngineInterface', 'QgsLayerItem', 'QgsLegendModel', 'QgsLinePatternFillSymbolLayer', 'QgsLineSymbolLayerV2', 'QgsLineSymbolV2', 'QgsLinearMinMaxEnhancement', 'QgsLinearMinMaxEnhancementWithClip', 'QgsLinearlyInterpolatedDiagramRenderer', 'QgsLogger', 'QgsMapLayer', 'QgsMapLayerRegistry', 'QgsMapRenderer', 'QgsMapToPixel', 'QgsMarkerLineSymbolLayerV2', 'QgsMarkerSymbolLayerV2', 'QgsMarkerSymbolV2', 'QgsMessageLog', 'QgsMessageLogConsole', 'QgsMessageOutput', 'QgsMessageOutputConsole', 'QgsMimeDataUtils', 'QgsMultiBandColorRenderer', 'QgsNMEAConnection', 'QgsNetworkAccessManager', 'QgsNumericScaleBarStyle', 'QgsOWSConnection', 'QgsOfflineEditing', 'QgsOgcUtils', 'QgsPaintEngineHack', 'QgsPalLabeling', 'QgsPalLayerSettings', 'QgsPalettedRasterRenderer', 'QgsPaperItem', 'QgsPieDiagram', 'QgsPluginLayer', 'QgsPluginLayerRegistry', 'QgsPluginLayerType', 'QgsPoint', 'QgsPointDisplacementRenderer', 'QgsPointPatternFillSymbolLayer', 'QgsProject', 'QgsProjectBadLayerDefaultHandler', 'QgsProjectBadLayerHandler', 'QgsProjectFileTransform', 'QgsProjectVersion', 'QgsProperty', 'QgsPropertyKey', 'QgsPropertyValue', 'QgsProviderCountCalcEvent', 'QgsProviderExtentCalcEvent', 'QgsProviderMetadata', 'QgsProviderRegistry', 'QgsPseudoColorShader', 'QgsPythonRunner', 'QgsRaster', 'QgsRasterBandStats', 'QgsRasterBlock', 'QgsRasterChecker', 'QgsRasterDataProvider', 'QgsRasterDrawer', 'QgsRasterFileWriter', 'QgsRasterHistogram', 'QgsRasterIdentifyResult', 'QgsRasterInterface', 'QgsRasterIterator', 'QgsRasterLayer', 'QgsRasterNuller', 'QgsRasterPipe', 'QgsRasterProjector', 'QgsRasterPyramid', 'QgsRasterRange', 'QgsRasterRenderer', 'QgsRasterResampleFilter', 'QgsRasterResampler', 'QgsRasterShader', 'QgsRasterShaderFunction', 'QgsRasterTransparency', 'QgsRasterViewPort', 'QgsRectangle', 'QgsRenderChecker', 'QgsRenderContext', 'QgsRendererCategoryV2', 'QgsRendererRangeV2', 'QgsRendererV2AbstractMetadata', 'QgsRendererV2Metadata', 'QgsRendererV2Registry', 'QgsRuleBasedRendererV2', 'QgsRunProcess', 'QgsSVGFillSymbolLayer', 'QgsSatelliteInfo', 'QgsScaleBarStyle', 'QgsScaleCalculator', 'QgsScaleUtils', 'QgsSimpleFillSymbolLayerV2', 'QgsSimpleLineSymbolLayerV2', 'QgsSimpleMarkerSymbolLayerV2', 'QgsSingleBandColorDataRenderer', 'QgsSingleBandGrayRenderer', 'QgsSingleBandPseudoColorRenderer', 'QgsSingleBoxScaleBarStyle', 'QgsSingleCategoryDiagramRenderer', 'QgsSingleSymbolRendererV2', 'QgsSnapper', 'QgsSnappingResult', 'QgsSpatialIndex', 'QgsStyleV2', 'QgsSvgCache', 'QgsSvgCacheEntry', 'QgsSvgMarkerSymbolLayerV2', 'QgsSymbolLayerV2', 'QgsSymbolLayerV2AbstractMetadata', 'QgsSymbolLayerV2Metadata', 'QgsSymbolLayerV2Registry', 'QgsSymbolLayerV2Utils', 'QgsSymbolV2', 'QgsSymbolV2LevelItem', 'QgsSymbolV2RenderContext', 'QgsSymbologyV2Conversion', 'QgsTextDiagram', 'QgsTicksScaleBarStyle', 'QgsTolerance', 'QgsVectorColorBrewerColorRampV2', 'QgsVectorColorRampV2', 'QgsVectorDataProvider', 'QgsVectorFieldSymbolLayer', 'QgsVectorFileWriter', 'QgsVectorGradientColorRampV2', 'QgsVectorJoinInfo', 'QgsVectorLayer', 'QgsVectorLayerCache', 'QgsVectorLayerEditBuffer', 'QgsVectorLayerEditUtils', 'QgsVectorLayerFeatureIterator', 'QgsVectorLayerImport', 'QgsVectorLayerJoinBuffer', 'QgsVectorRandomColorRampV2', 'QgsZipItem', 'USER_CRS_START_ID', '__doc__', '__file__', '__name__', '__package__']&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Далее, после выбора нужного класса, например QgsFeature, посмотрим его методы:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
dir(qgis.core.QgsFeature)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Результат:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
['__class__', '__delattr__', '__delitem__', '__dict__', '__doc__', '__format__', '__getattribute__', '__getitem__', '__hash__', '__init__', '__iter__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__setitem__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'attribute', 'attributes', 'deleteAttribute', 'fieldNameIndex', 'fields', 'geometry', 'geometryAndOwnership', 'id', 'initAttributes', 'isValid', 'setAttribute', 'setAttributes', 'setFeatureId', 'setFields', 'setGeometry', 'setGeometryAndOwnership', 'setValid']&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Ресурсы ===&lt;br /&gt;
&lt;br /&gt;
Для разработки расширения понадобится создать специальный файл, который будет содержать указатели на используемые расширением ресурсы, такие как например иконки. Пример такого файла:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;RCC&amp;gt;&lt;br /&gt;
&amp;lt;qresource prefix=&amp;quot;&amp;quot; &amp;gt;&lt;br /&gt;
    &amp;lt;file&amp;gt;icons/icon.png&amp;lt;/file&amp;gt;&lt;br /&gt;
&amp;lt;/qresource&amp;gt;&lt;br /&gt;
&amp;lt;/RCC&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Рекомендуется использовать уникальный qresource prefix, который не будет конфликтовать с другими расширениями.&lt;br /&gt;
&lt;br /&gt;
После создания этого файла, необходимо его скомпилировать с помощью &amp;lt;tt&amp;gt;pyrcc4&amp;lt;/tt&amp;gt; в формат, который можно импортировать с помощью Python:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
pyrcc4 -o resources.py resources.qrc &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
И как уже упоминалось выше, импортировать получившиеся ресурсы в основном коде &amp;lt;tt&amp;gt;testplugin.py&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Заключение ===&lt;br /&gt;
&lt;br /&gt;
Разработка каркаса нашего расширения завершена. Если она велась в папке расширений, то после запуска QGIS расширение должно автоматически появиться в списке расширений и можно начать его тестирование, отладку и, конечно, наполнение нужными полезными функциями.&lt;br /&gt;
&lt;br /&gt;
Помните, что лучшим пособием по разработке для QGIS являются расширения созданные другими авторами.&lt;br /&gt;
&lt;br /&gt;
=== Ссылки по теме ===&lt;br /&gt;
&lt;br /&gt;
* [http://gis-lab.info/qa/qgis-standalone.html Создание приложения на базе набора библиотек QGIS на Python]&lt;br /&gt;
* [http://gis-lab.info/qa/qgis-repo.html Организация и работа с репозиториями расширений QGIS]&lt;br /&gt;
* [http://gis-lab.info/qa/qgis-install-plugin.html Установка модулей расширения в QGIS]&lt;br /&gt;
* [http://gis-lab.info/docs/qgis Документация по QGIS]&lt;/div&gt;</summary>
		<author><name>KolesovDmitry</name></author>
	</entry>
	<entry>
		<id>https://wiki.gis-lab.info/index.php?title=ReconstructLine_-_%D0%B2%D0%BE%D1%81%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BB%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BB%D0%B8%D0%BD%D0%B8%D0%B9_%D0%BF%D0%BE_%D1%82%D0%BE%D1%87%D0%BA%D0%B0%D0%BC_%D0%B2_QGIS&amp;diff=22010</id>
		<title>ReconstructLine - восстановление линий по точкам в QGIS</title>
		<link rel="alternate" type="text/html" href="https://wiki.gis-lab.info/index.php?title=ReconstructLine_-_%D0%B2%D0%BE%D1%81%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BB%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BB%D0%B8%D0%BD%D0%B8%D0%B9_%D0%BF%D0%BE_%D1%82%D0%BE%D1%87%D0%BA%D0%B0%D0%BC_%D0%B2_QGIS&amp;diff=22010"/>
		<updated>2015-05-12T03:58:15Z</updated>

		<summary type="html">&lt;p&gt;KolesovDmitry: /* Случай линии с ответвлениями */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Статья|Опубликована|reconstruct_line}}&lt;br /&gt;
{{Аннотация|Описание инструмента для создания линий по точкам в QGIS}}&lt;br /&gt;
&lt;br /&gt;
[http://plugins.qgis.org/plugins/reconstruct_line/ ReconstructLine] - это инструмент для интерактивного создания линейных объектов по точечным.&lt;br /&gt;
&lt;br /&gt;
Вы наверняка сталкивались с инструментом, объединяющим точки в линии. Все такие инструменты работают либо последовательно, т.е. точки объединяются в линии так, как они идут в таблице, либо про атрибутам. Теперь представьте, что вам не важен порядок записей в таблице и атрибутивная информация отсутствует или бесполезна, но что вам все равно нужно объединить точки в линию. &lt;br /&gt;
&lt;br /&gt;
Расширение ReconstructLine умеет восстанавливать линии по точкам, используя '''только''' их пространственное расположение. Расширение может работать в двух режимах, &amp;quot;восстанавливая&amp;quot; единую линию или несколько линий. Поскольку восстановление - это сложный алгоритм, ReconstructLine работает только интерактивно. Процесс восстановления может занять значительное время, если точек много.&lt;br /&gt;
&lt;br /&gt;
ReconstructLine плохо подходит для облаков точек.&lt;br /&gt;
&lt;br /&gt;
Реальный пример применения - у вас есть несколько треков снятых в разное время, возможно разными людьми и представляющих один и тот же линейный объект. Их все необходимо объединить в единый объект. Подобная задача часто возникает при съемке протяженных объектов - линий электропередач, трубопроводов и т.п.&lt;br /&gt;
&lt;br /&gt;
{{NextGIS}}&lt;br /&gt;
&lt;br /&gt;
=== Замечания по установке ===&lt;br /&gt;
&lt;br /&gt;
Расширение доступно из [http://plugins.qgis.org/plugins/reconstruct_line/ официального репозитория].&lt;br /&gt;
&lt;br /&gt;
ReconstructLine находится в разработке и протестирован с QGIS 2.6 и выше. Расширение работает в Windows и Linux (Ubuntu).&lt;br /&gt;
&lt;br /&gt;
Исходный код модуля доступен в ([https://github.com/nextgis/ReconstructLine репозитории] на Github).&lt;br /&gt;
&lt;br /&gt;
=== Алгоритм ===&lt;br /&gt;
Модуль предназначен для работы с двумя типами расположения точек:&lt;br /&gt;
* Точки образуют единственную линию.&lt;br /&gt;
* Точки образуют несколько пересекающихся линий (основная линия и короткие боковые ответвления).&lt;br /&gt;
Для каждого из этих случаев точки обрабатываются отдельным алгоритмом. Пользователь может выбрать тот или иной алгоритм, нажав на соответсвующую точку на панели инструментов.&lt;br /&gt;
&lt;br /&gt;
==== Случай одной линии ====&lt;br /&gt;
&lt;br /&gt;
При разработке модуля принималось во внимание то, что точки можно соединить между собой &amp;quot;логичным&amp;quot; образом, если они образуют &amp;quot;видимую глазами&amp;quot; кривую линию. В этом случае задачу можно сформулировать следующим образом:&lt;br /&gt;
&lt;br /&gt;
* Дан набор точек &amp;lt;math&amp;gt;T_1, T_2, \dots T_n&amp;lt;/math&amp;gt;.&lt;br /&gt;
* Дана метрика &amp;lt;math&amp;gt;d(T_i, T_j)&amp;lt;/math&amp;gt; -- функция, которая измеряет расстояния между произвольной парой точек. Тогда потенциальной восстановленной кривой (т.е. последовательности точек &amp;lt;math&amp;gt;(T_{i_1}, T_{i_2}, ..., T_{i_n})&amp;lt;/math&amp;gt;) можно поставить в соответствие её длину, равную сумме растояний между парами точек, составляющих восстановленную кривую: &amp;lt;math&amp;gt;L = d(T_{i_1}, T_{i_2}) + d(T_{i_2}, T_{i_3}) + \dots + d(T_{i_{n-1}}, T_{i_n})&amp;lt;/math&amp;gt;.&lt;br /&gt;
* Требуется найти среди всех комбинаций &amp;lt;math&amp;gt;(T_{i_1}, T_{i_2}, ..., T_{i_n})&amp;lt;/math&amp;gt; такую комбинацию, для которой ее длина L будет минимальной.&lt;br /&gt;
&lt;br /&gt;
Нужно заметить, что требование того, что восстановленная кривая должна иметь минимальную длину из всех возможных комбинаций точек -- чисто эвристическое допущение, которое, тем не менее, хорошо согласуется с реальным положением дел. (Чтобы убедиться в этом достаточно нарисовать кривую, измерить ее длину, затем &amp;quot;перепутать&amp;quot; в ней пару или несколько пар точек и измерить длину новой кривой).&lt;br /&gt;
&lt;br /&gt;
Приведенная выше формулировка задачи представляет собой хорошо известную задачу поиска Гамильтонова пути. Также хорошо известно, что эта задача уже при небольшом числе точек не может быть решена &amp;quot;в лоб&amp;quot; простым перебором вариантов, поскольку их число взрыовобразно растет. Так, например, для пяти точек будет всего 60 (т.е. 5!/2) возможных комбинаций, для десяти точек -- уже почти два миллиона, а, например, для тридцати -- количество комбинаций описывется числом, состоящим из 34-х цифр.&lt;br /&gt;
&lt;br /&gt;
Поэтому алгоритмы построения Гамильтонова пути, используемые на практике, представляют собой субоптимальные алгоритмы, которые позволяют найти хорошее решение за приемлемое время, но не гарантируют того, что оно будет лучшим из всех возможных. В данном модуле в качестве основного алгорима использовались  [https://ru.wikipedia.org/wiki/%D0%A1%D0%B0%D0%BC%D0%BE%D0%BE%D1%80%D0%B3%D0%B0%D0%BD%D0%B8%D0%B7%D1%83%D1%8E%D1%89%D0%B0%D1%8F%D1%81%D1%8F_%D0%BA%D0%B0%D1%80%D1%82%D0%B0_%D0%9A%D0%BE%D1%85%D0%BE%D0%BD%D0%B5%D0%BD%D0%B0 самоорганизующиеся карты Кохонена]. Поскольку перед нами стоит задача восстановления линии, то и архитектура сети была выбрана линейной. Обученная сеть упорядочивает точки и в целом обеспечивает неплохой результат работы. Но в некоторых случаях &amp;quot;неудачного&amp;quot; расположения входных точек с одним узлом сети оказываются связаны несколько точек, их упорядоченность может оказаться нарушенной. Для того, чтобы отследить подобные случаи, в модуле используется постобработка: в упорядоченном картой Кохонена наборе точек производятся попарные перестановки соседних точек и измеряется совокупная длина линии. В итоге линия наименьшей длины возвращается в качестве результата алгоритма.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Случай линии с ответвлениями ====&lt;br /&gt;
Бывает так, что точки образуют основную (длинную) линию, от которой отходят короткие боковые ходы. В этом случае предположение о том, что конечная линия должна представлять собой линию минимальной длины (Гамильтонов путь) не верно. Зато данный случах хорошо &amp;quot;ложится&amp;quot; на [https://ru.wikipedia.org/wiki/%D0%9C%D0%B8%D0%BD%D0%B8%D0%BC%D0%B0%D0%BB%D1%8C%D0%BD%D0%BE%D0%B5_%D0%BE%D1%81%D1%82%D0%BE%D0%B2%D0%BD%D0%BE%D0%B5_%D0%B4%D0%B5%D1%80%D0%B5%D0%B2%D0%BE задачу о нахождении минимального остовного дерева]. &lt;br /&gt;
&lt;br /&gt;
В плагине реализуется классический [https://ru.wikipedia.org/wiki/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%9F%D1%80%D0%B8%D0%BC%D0%B0 алгоритм Прима], предназначенный для решения этой задачи. В отличие от предыдущего случая, строится не одна итоговая линия, а множество сегментов между соседними точками. В случае необходимости объединить сегменты в одну линию, пользователь может воспользоваться стандартным иструментом QGIS объединения геометрий.&lt;br /&gt;
&lt;br /&gt;
=== Работа с расширением ===&lt;br /&gt;
&lt;br /&gt;
=== Режим одной линии ===&lt;br /&gt;
&lt;br /&gt;
После установки расширения появится новая панель инструментов с двумя кнопками: &amp;quot;копировать точки&amp;quot; и &amp;quot;вставить линию&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
[[Файл:Reconstructline-05.png|center]]&lt;br /&gt;
&lt;br /&gt;
Предположим, что исходный набор точек выглядит следующим образом (обратите внимание на нумерацию, она отражает последовательность точек в таблице):&lt;br /&gt;
&lt;br /&gt;
[[Файл:Reconstructline-02.png|center|thumb|600px|Исходные точки]]&lt;br /&gt;
&lt;br /&gt;
Что будет, если просто соединить их в линию (например с помощью расширения Points2One):&lt;br /&gt;
&lt;br /&gt;
[[Файл:Reconstructline-03.png|center|thumb|600px|Последовательное объединение точек в линию]]&lt;br /&gt;
&lt;br /&gt;
Для объединения с помощью ReconstructLine:&lt;br /&gt;
&lt;br /&gt;
1. Инструментом выделения выделите нужные точки, нажмите на кнопку &amp;quot;Копировать точки&amp;quot; в панели инструментов ReconstructLine&lt;br /&gt;
&lt;br /&gt;
2. Вставьте линию в линейный слой (если слоя нет - создайте новый или добавьте существующий). Выберите слой в списке слоёв, начните редактирование и нажмите на кнопку &amp;quot;Вставить линию&amp;quot; в панели инструментов ReconstructLine&lt;br /&gt;
&lt;br /&gt;
Результат должен выглядеть более логично:&lt;br /&gt;
&lt;br /&gt;
[[Файл:Reconstructline-04.png|center|thumb|600px|Объединение точек в линию с помощью ReconstructLine]]&lt;br /&gt;
&lt;br /&gt;
=== Режим восстановления нескольких линий ===&lt;br /&gt;
&lt;br /&gt;
Используя инструмент &amp;quot;вставить линии&amp;quot; можно попытаться реконструировать несколько линий в исходных данных. Особенностью работы данного алгоритма является то, что создается не одна, а много линий, по количеству сегментов соединяющих точки.&lt;br /&gt;
&lt;br /&gt;
Для примера рассмотрим следующий набор данных:&lt;br /&gt;
&lt;br /&gt;
[[Файл:Reconstructline-06.png|center|thumb|600px|Точки и реальные линейная сеть их объединяющая (проверочные данные)]]&lt;br /&gt;
&lt;br /&gt;
Используя алгоритм восстановления линий можно достичь следующего результата:&lt;br /&gt;
&lt;br /&gt;
[[Файл:Reconstructline-07.png|center|thumb|600px|То же, что и выше, но красным цветом показана сеть восстановленная по точкам]]&lt;br /&gt;
&lt;br /&gt;
Как можно видеть, автоматический алгоритм лишь в нескольких местах (синие фрагменты) не смог восстановить ожидаемую сеть.&lt;br /&gt;
&lt;br /&gt;
=== Контакты ===&lt;br /&gt;
&lt;br /&gt;
Если вы нашли ошибку или у вас есть предложения по улучшению расширения — воспользуйтесь [https://github.com/nextgis/ReconstructLine/issues багтрекером]. Кроме того, вопросы по использованию расширения можно задать авторам [http://nextgis.ru/contact/ напрямую].&lt;br /&gt;
&lt;br /&gt;
=== Ссылки по теме ===&lt;br /&gt;
&lt;br /&gt;
* [http://gis-lab.info/qa/qgis-install-plugin.html Установка модулей расширения в QGIS]&lt;br /&gt;
* [http://gis-lab.info/docs/qgis/ Документация по QGIS]&lt;/div&gt;</summary>
		<author><name>KolesovDmitry</name></author>
	</entry>
	<entry>
		<id>https://wiki.gis-lab.info/index.php?title=ReconstructLine_-_%D0%B2%D0%BE%D1%81%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BB%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BB%D0%B8%D0%BD%D0%B8%D0%B9_%D0%BF%D0%BE_%D1%82%D0%BE%D1%87%D0%BA%D0%B0%D0%BC_%D0%B2_QGIS&amp;diff=22009</id>
		<title>ReconstructLine - восстановление линий по точкам в QGIS</title>
		<link rel="alternate" type="text/html" href="https://wiki.gis-lab.info/index.php?title=ReconstructLine_-_%D0%B2%D0%BE%D1%81%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BB%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BB%D0%B8%D0%BD%D0%B8%D0%B9_%D0%BF%D0%BE_%D1%82%D0%BE%D1%87%D0%BA%D0%B0%D0%BC_%D0%B2_QGIS&amp;diff=22009"/>
		<updated>2015-05-12T03:52:48Z</updated>

		<summary type="html">&lt;p&gt;KolesovDmitry: /* Алгоритм */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Статья|Опубликована|reconstruct_line}}&lt;br /&gt;
{{Аннотация|Описание инструмента для создания линий по точкам в QGIS}}&lt;br /&gt;
&lt;br /&gt;
[http://plugins.qgis.org/plugins/reconstruct_line/ ReconstructLine] - это инструмент для интерактивного создания линейных объектов по точечным.&lt;br /&gt;
&lt;br /&gt;
Вы наверняка сталкивались с инструментом, объединяющим точки в линии. Все такие инструменты работают либо последовательно, т.е. точки объединяются в линии так, как они идут в таблице, либо про атрибутам. Теперь представьте, что вам не важен порядок записей в таблице и атрибутивная информация отсутствует или бесполезна, но что вам все равно нужно объединить точки в линию. &lt;br /&gt;
&lt;br /&gt;
Расширение ReconstructLine умеет восстанавливать линии по точкам, используя '''только''' их пространственное расположение. Расширение может работать в двух режимах, &amp;quot;восстанавливая&amp;quot; единую линию или несколько линий. Поскольку восстановление - это сложный алгоритм, ReconstructLine работает только интерактивно. Процесс восстановления может занять значительное время, если точек много.&lt;br /&gt;
&lt;br /&gt;
ReconstructLine плохо подходит для облаков точек.&lt;br /&gt;
&lt;br /&gt;
Реальный пример применения - у вас есть несколько треков снятых в разное время, возможно разными людьми и представляющих один и тот же линейный объект. Их все необходимо объединить в единый объект. Подобная задача часто возникает при съемке протяженных объектов - линий электропередач, трубопроводов и т.п.&lt;br /&gt;
&lt;br /&gt;
{{NextGIS}}&lt;br /&gt;
&lt;br /&gt;
=== Замечания по установке ===&lt;br /&gt;
&lt;br /&gt;
Расширение доступно из [http://plugins.qgis.org/plugins/reconstruct_line/ официального репозитория].&lt;br /&gt;
&lt;br /&gt;
ReconstructLine находится в разработке и протестирован с QGIS 2.6 и выше. Расширение работает в Windows и Linux (Ubuntu).&lt;br /&gt;
&lt;br /&gt;
Исходный код модуля доступен в ([https://github.com/nextgis/ReconstructLine репозитории] на Github).&lt;br /&gt;
&lt;br /&gt;
=== Алгоритм ===&lt;br /&gt;
Модуль предназначен для работы с двумя типами расположения точек:&lt;br /&gt;
* Точки образуют единственную линию.&lt;br /&gt;
* Точки образуют несколько пересекающихся линий (основная линия и короткие боковые ответвления).&lt;br /&gt;
Для каждого из этих случаев точки обрабатываются отдельным алгоритмом. Пользователь может выбрать тот или иной алгоритм, нажав на соответсвующую точку на панели инструментов.&lt;br /&gt;
&lt;br /&gt;
==== Случай одной линии ====&lt;br /&gt;
&lt;br /&gt;
При разработке модуля принималось во внимание то, что точки можно соединить между собой &amp;quot;логичным&amp;quot; образом, если они образуют &amp;quot;видимую глазами&amp;quot; кривую линию. В этом случае задачу можно сформулировать следующим образом:&lt;br /&gt;
&lt;br /&gt;
* Дан набор точек &amp;lt;math&amp;gt;T_1, T_2, \dots T_n&amp;lt;/math&amp;gt;.&lt;br /&gt;
* Дана метрика &amp;lt;math&amp;gt;d(T_i, T_j)&amp;lt;/math&amp;gt; -- функция, которая измеряет расстояния между произвольной парой точек. Тогда потенциальной восстановленной кривой (т.е. последовательности точек &amp;lt;math&amp;gt;(T_{i_1}, T_{i_2}, ..., T_{i_n})&amp;lt;/math&amp;gt;) можно поставить в соответствие её длину, равную сумме растояний между парами точек, составляющих восстановленную кривую: &amp;lt;math&amp;gt;L = d(T_{i_1}, T_{i_2}) + d(T_{i_2}, T_{i_3}) + \dots + d(T_{i_{n-1}}, T_{i_n})&amp;lt;/math&amp;gt;.&lt;br /&gt;
* Требуется найти среди всех комбинаций &amp;lt;math&amp;gt;(T_{i_1}, T_{i_2}, ..., T_{i_n})&amp;lt;/math&amp;gt; такую комбинацию, для которой ее длина L будет минимальной.&lt;br /&gt;
&lt;br /&gt;
Нужно заметить, что требование того, что восстановленная кривая должна иметь минимальную длину из всех возможных комбинаций точек -- чисто эвристическое допущение, которое, тем не менее, хорошо согласуется с реальным положением дел. (Чтобы убедиться в этом достаточно нарисовать кривую, измерить ее длину, затем &amp;quot;перепутать&amp;quot; в ней пару или несколько пар точек и измерить длину новой кривой).&lt;br /&gt;
&lt;br /&gt;
Приведенная выше формулировка задачи представляет собой хорошо известную задачу поиска Гамильтонова пути. Также хорошо известно, что эта задача уже при небольшом числе точек не может быть решена &amp;quot;в лоб&amp;quot; простым перебором вариантов, поскольку их число взрыовобразно растет. Так, например, для пяти точек будет всего 60 (т.е. 5!/2) возможных комбинаций, для десяти точек -- уже почти два миллиона, а, например, для тридцати -- количество комбинаций описывется числом, состоящим из 34-х цифр.&lt;br /&gt;
&lt;br /&gt;
Поэтому алгоритмы построения Гамильтонова пути, используемые на практике, представляют собой субоптимальные алгоритмы, которые позволяют найти хорошее решение за приемлемое время, но не гарантируют того, что оно будет лучшим из всех возможных. В данном модуле в качестве основного алгорима использовались  [https://ru.wikipedia.org/wiki/%D0%A1%D0%B0%D0%BC%D0%BE%D0%BE%D1%80%D0%B3%D0%B0%D0%BD%D0%B8%D0%B7%D1%83%D1%8E%D1%89%D0%B0%D1%8F%D1%81%D1%8F_%D0%BA%D0%B0%D1%80%D1%82%D0%B0_%D0%9A%D0%BE%D1%85%D0%BE%D0%BD%D0%B5%D0%BD%D0%B0 самоорганизующиеся карты Кохонена]. Поскольку перед нами стоит задача восстановления линии, то и архитектура сети была выбрана линейной. Обученная сеть упорядочивает точки и в целом обеспечивает неплохой результат работы. Но в некоторых случаях &amp;quot;неудачного&amp;quot; расположения входных точек с одним узлом сети оказываются связаны несколько точек, их упорядоченность может оказаться нарушенной. Для того, чтобы отследить подобные случаи, в модуле используется постобработка: в упорядоченном картой Кохонена наборе точек производятся попарные перестановки соседних точек и измеряется совокупная длина линии. В итоге линия наименьшей длины возвращается в качестве результата алгоритма.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Случай линии с ответвлениями ====&lt;br /&gt;
Бывает так, что точки образуют основную (длинную) линию, от которой отходят короткие боковые ходы. В этом случае предположение о том, что конечная линия должна представлять собой линию минимальной длины (Гамильтонов путь) не верно. Зато данный случах хорошо &amp;quot;ложится&amp;quot; на задачу о нахождении минимального остовного дерева.&lt;br /&gt;
&lt;br /&gt;
=== Работа с расширением ===&lt;br /&gt;
&lt;br /&gt;
=== Режим одной линии ===&lt;br /&gt;
&lt;br /&gt;
После установки расширения появится новая панель инструментов с двумя кнопками: &amp;quot;копировать точки&amp;quot; и &amp;quot;вставить линию&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
[[Файл:Reconstructline-05.png|center]]&lt;br /&gt;
&lt;br /&gt;
Предположим, что исходный набор точек выглядит следующим образом (обратите внимание на нумерацию, она отражает последовательность точек в таблице):&lt;br /&gt;
&lt;br /&gt;
[[Файл:Reconstructline-02.png|center|thumb|600px|Исходные точки]]&lt;br /&gt;
&lt;br /&gt;
Что будет, если просто соединить их в линию (например с помощью расширения Points2One):&lt;br /&gt;
&lt;br /&gt;
[[Файл:Reconstructline-03.png|center|thumb|600px|Последовательное объединение точек в линию]]&lt;br /&gt;
&lt;br /&gt;
Для объединения с помощью ReconstructLine:&lt;br /&gt;
&lt;br /&gt;
1. Инструментом выделения выделите нужные точки, нажмите на кнопку &amp;quot;Копировать точки&amp;quot; в панели инструментов ReconstructLine&lt;br /&gt;
&lt;br /&gt;
2. Вставьте линию в линейный слой (если слоя нет - создайте новый или добавьте существующий). Выберите слой в списке слоёв, начните редактирование и нажмите на кнопку &amp;quot;Вставить линию&amp;quot; в панели инструментов ReconstructLine&lt;br /&gt;
&lt;br /&gt;
Результат должен выглядеть более логично:&lt;br /&gt;
&lt;br /&gt;
[[Файл:Reconstructline-04.png|center|thumb|600px|Объединение точек в линию с помощью ReconstructLine]]&lt;br /&gt;
&lt;br /&gt;
=== Режим восстановления нескольких линий ===&lt;br /&gt;
&lt;br /&gt;
Используя инструмент &amp;quot;вставить линии&amp;quot; можно попытаться реконструировать несколько линий в исходных данных. Особенностью работы данного алгоритма является то, что создается не одна, а много линий, по количеству сегментов соединяющих точки.&lt;br /&gt;
&lt;br /&gt;
Для примера рассмотрим следующий набор данных:&lt;br /&gt;
&lt;br /&gt;
[[Файл:Reconstructline-06.png|center|thumb|600px|Точки и реальные линейная сеть их объединяющая (проверочные данные)]]&lt;br /&gt;
&lt;br /&gt;
Используя алгоритм восстановления линий можно достичь следующего результата:&lt;br /&gt;
&lt;br /&gt;
[[Файл:Reconstructline-07.png|center|thumb|600px|То же, что и выше, но красным цветом показана сеть восстановленная по точкам]]&lt;br /&gt;
&lt;br /&gt;
Как можно видеть, автоматический алгоритм лишь в нескольких местах (синие фрагменты) не смог восстановить ожидаемую сеть.&lt;br /&gt;
&lt;br /&gt;
=== Контакты ===&lt;br /&gt;
&lt;br /&gt;
Если вы нашли ошибку или у вас есть предложения по улучшению расширения — воспользуйтесь [https://github.com/nextgis/ReconstructLine/issues багтрекером]. Кроме того, вопросы по использованию расширения можно задать авторам [http://nextgis.ru/contact/ напрямую].&lt;br /&gt;
&lt;br /&gt;
=== Ссылки по теме ===&lt;br /&gt;
&lt;br /&gt;
* [http://gis-lab.info/qa/qgis-install-plugin.html Установка модулей расширения в QGIS]&lt;br /&gt;
* [http://gis-lab.info/docs/qgis/ Документация по QGIS]&lt;/div&gt;</summary>
		<author><name>KolesovDmitry</name></author>
	</entry>
	<entry>
		<id>https://wiki.gis-lab.info/index.php?title=ReconstructLine_-_%D0%B2%D0%BE%D1%81%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BB%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BB%D0%B8%D0%BD%D0%B8%D0%B9_%D0%BF%D0%BE_%D1%82%D0%BE%D1%87%D0%BA%D0%B0%D0%BC_%D0%B2_QGIS&amp;diff=21924</id>
		<title>ReconstructLine - восстановление линий по точкам в QGIS</title>
		<link rel="alternate" type="text/html" href="https://wiki.gis-lab.info/index.php?title=ReconstructLine_-_%D0%B2%D0%BE%D1%81%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BB%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BB%D0%B8%D0%BD%D0%B8%D0%B9_%D0%BF%D0%BE_%D1%82%D0%BE%D1%87%D0%BA%D0%B0%D0%BC_%D0%B2_QGIS&amp;diff=21924"/>
		<updated>2015-04-28T09:14:37Z</updated>

		<summary type="html">&lt;p&gt;KolesovDmitry: /* Контакты */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Статья|Черновик|reconstructline}}&lt;br /&gt;
{{Аннотация|Описание инструмента для создания линейных объектов в QGIS.}}&lt;br /&gt;
&lt;br /&gt;
[http://plugins.qgis.org/plugins/reconstruct_line/ ReconstructLine] - это инструмент для интерактивного создания линейных объектов по точечным.&lt;br /&gt;
&lt;br /&gt;
Вы наверняка сталкивались с инструментом, объединяющим точки в линии. Все такие инструменты работают либо последовательно, т.е. точки объединяются в линии так, как они идут в таблице, либо про атрибутам. Теперь представьте, что вам не важен порядок записей в таблице и атрибутивная информация отсутствует или бесполезна, но что вам все равно нужно объединить точки в линию. &lt;br /&gt;
&lt;br /&gt;
Расширение ReconstructLine умеет восстанавливать линии по точкам, используя '''только''' их пространственное расположение, &amp;quot;восстанавливая&amp;quot; линию. Поскольку восстановление - это сложный алгоритм, ReconstructLine работает только интерактивно. Процесс восстановления может занять значительное время, если точек много.&lt;br /&gt;
&lt;br /&gt;
ReconstructLine плохо подходит для облаков точек.&lt;br /&gt;
&lt;br /&gt;
{{NextGIS}}&lt;br /&gt;
&lt;br /&gt;
=== Замечания по установке ===&lt;br /&gt;
&lt;br /&gt;
Расширение доступно из [http://plugins.qgis.org/plugins/reconstruct_line/ официального репозитория].&lt;br /&gt;
&lt;br /&gt;
ReconstructLine находится в разработке и протестирован с QGIS 2.6 и выше. Расширение работает в Windows и Linux (Ubuntu).&lt;br /&gt;
&lt;br /&gt;
Исходный код модуля доступен в ([https://github.com/nextgis/ReconstructLine репозитории] на Github).&lt;br /&gt;
&lt;br /&gt;
=== Алгоритм ===&lt;br /&gt;
При разработке модуля принималось во внимание то, что точки можно соединить между собой &amp;quot;логичным&amp;quot; образом, если они образуют &amp;quot;видимую глазами&amp;quot; кривую линию. В этом случае задачу можно сформулировать следующим образом:&lt;br /&gt;
&lt;br /&gt;
* Дан набор точек &amp;lt;math&amp;gt;T_1, T_2, \dots T_n&amp;lt;/math&amp;gt;.&lt;br /&gt;
* Дана метрика &amp;lt;math&amp;gt;d(T_i, T_j)&amp;lt;/math&amp;gt; -- функция, которая измеряет расстояния между произвольной парой точек. Тогда потенциальной восстановленной кривой (т.е. последовательности точек &amp;lt;math&amp;gt;(T_{i_1}, T_{i_2}, ..., T_{i_n})&amp;lt;/math&amp;gt;) можно поставить в соответствие её длину, равную сумме растояний между парами точек, составляющих восстановленную кривую: &amp;lt;math&amp;gt;L = d(T_{i_1}, T_{i_2}) + d(T_{i_2}, T_{i_3}) + \dots + d(T_{i_{n-1}}, T_{i_n})&amp;lt;/math&amp;gt;.&lt;br /&gt;
* Требуется найти среди всех комбинаций &amp;lt;math&amp;gt;(T_{i_1}, T_{i_2}, ..., T_{i_n})&amp;lt;/math&amp;gt; такую комбинацию, для которой ее длина L будет минимальной.&lt;br /&gt;
&lt;br /&gt;
Нужно заметить, что требование того, что восстановленная кривая должна иметь минимальную длину из всех возможных комбинаций точек -- чисто эвристическое допущение, которое, тем не менее, хорошо согласуется с реальным положением дел. (Чтобы убедиться в этом достаточно нарисовать кривую, измерить ее длину, затем &amp;quot;перепутать&amp;quot; в ней пару или несколько пар точек и измерить длину новой кривой).&lt;br /&gt;
&lt;br /&gt;
Приведенная выше формулировка задачи представляет собой хорошо известную задачу поиска Гамильтонова пути. Также хорошо известно, что эта задача уже при небольшом числе точек не может быть решена &amp;quot;в лоб&amp;quot; простым перебором вариантов, поскольку их число взрыовобразно растет. Так, например, для пяти точек будет всего 60 (т.е. 5!/2) возможных комбинаций, для десяти точек -- уже почти два миллиона, а, например, для тридцати -- количество комбинаций описывется числом, состоящим из 34-х цифр.&lt;br /&gt;
&lt;br /&gt;
Поэтому алгоритмы построения Гамильтонова пути, используемые на практике, представляют собой субоптимальные алгоритмы, которые позволяют найти хорошее решение за приемлемое время, но не гарантируют того, что оно будет лучшим из всех возможных. В данном модуле в качестве основного алгорима использовались  [https://ru.wikipedia.org/wiki/%D0%A1%D0%B0%D0%BC%D0%BE%D0%BE%D1%80%D0%B3%D0%B0%D0%BD%D0%B8%D0%B7%D1%83%D1%8E%D1%89%D0%B0%D1%8F%D1%81%D1%8F_%D0%BA%D0%B0%D1%80%D1%82%D0%B0_%D0%9A%D0%BE%D1%85%D0%BE%D0%BD%D0%B5%D0%BD%D0%B0 самоорганизующиеся карты Кохонена]. Поскольку перед нами стоит задача восстановления линии, то и архитектура сети была выбрана линейной. Обученная сеть упорядочивает точки и в целом обеспечивает неплохой результат работы. Но в некоторых случаях &amp;quot;неудачного&amp;quot; расположения входных точек с одним узлом сети оказываются связаны несколько точек, их упорядоченность может оказаться нарушенной. Для того, чтобы отследить подобные случаи, в модуле используется постобработка: в упорядоченном картой Кохонена наборе точек производятся попарные перестановки соседних точек и измеряется совокупная длина линии. В итоге линия наименьшей длины возвращается в качестве результата алгоритма.&lt;br /&gt;
&lt;br /&gt;
=== Работа с расширением ===&lt;br /&gt;
&lt;br /&gt;
После установки расширения появится новая панель инструментов с двумя кнопками: &amp;quot;копировать точки&amp;quot; и &amp;quot;вставить линию&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
[[Файл:Reconstructline-01.png|center]]&lt;br /&gt;
&lt;br /&gt;
Предположим, что исходный набор точек выглядит следующим образом (обратите внимание на нумерацию, она отражает последовательность точек в таблице):&lt;br /&gt;
&lt;br /&gt;
[[Файл:Reconstructline-02.png|center|thumb|600px|Исходные точки]]&lt;br /&gt;
&lt;br /&gt;
Что будет, если просто соединить их в линию (например с помощью расширения Points2One):&lt;br /&gt;
&lt;br /&gt;
[[Файл:Reconstructline-03.png|center|thumb|600px|Последовательное объединение точек в линию]]&lt;br /&gt;
&lt;br /&gt;
Для объединения с помощью ReconstructLine:&lt;br /&gt;
&lt;br /&gt;
1. Инструментом выделения выделите нужные точки, нажмите на кнопку &amp;quot;копировать точки&amp;quot; в панели инструментов ReconstructLine&lt;br /&gt;
&lt;br /&gt;
2. Вставьте линию в существующий или новый линейный слой, нажмите на кнопку &amp;quot;вставить линию&amp;quot; в панели инструментов ReconstructLine&lt;br /&gt;
&lt;br /&gt;
Результат должен выглядеть более логично:&lt;br /&gt;
&lt;br /&gt;
[[Файл:Reconstructline-04.png|center|thumb|600px|Объединение точек в линию с помощью ReconstructLine]]&lt;br /&gt;
&lt;br /&gt;
=== Контакты ===&lt;br /&gt;
&lt;br /&gt;
Если вы нашли ошибку или у вас есть предложения по улучшению расширения — воспользуйтесь [https://github.com/nextgis/ReconstructLine/issues багтрекером]. Кроме того, вопросы по использованию расширения можно задать авторам [http://nextgis.ru/contact/ напрямую].&lt;br /&gt;
&lt;br /&gt;
=== Ссылки по теме ===&lt;br /&gt;
&lt;br /&gt;
* [http://gis-lab.info/qa/qgis-install-plugin.html Установка модулей расширения в QGIS]&lt;br /&gt;
* [http://gis-lab.info/docs/qgis/ Документация по QGIS]&lt;/div&gt;</summary>
		<author><name>KolesovDmitry</name></author>
	</entry>
	<entry>
		<id>https://wiki.gis-lab.info/index.php?title=ReconstructLine_-_%D0%B2%D0%BE%D1%81%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BB%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BB%D0%B8%D0%BD%D0%B8%D0%B9_%D0%BF%D0%BE_%D1%82%D0%BE%D1%87%D0%BA%D0%B0%D0%BC_%D0%B2_QGIS&amp;diff=21921</id>
		<title>ReconstructLine - восстановление линий по точкам в QGIS</title>
		<link rel="alternate" type="text/html" href="https://wiki.gis-lab.info/index.php?title=ReconstructLine_-_%D0%B2%D0%BE%D1%81%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BB%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BB%D0%B8%D0%BD%D0%B8%D0%B9_%D0%BF%D0%BE_%D1%82%D0%BE%D1%87%D0%BA%D0%B0%D0%BC_%D0%B2_QGIS&amp;diff=21921"/>
		<updated>2015-04-28T07:53:45Z</updated>

		<summary type="html">&lt;p&gt;KolesovDmitry: /* Алгоритм */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Статья|Черновик|reconstructline}}&lt;br /&gt;
{{Аннотация|Описание инструмента для создания линейных объектов в QGIS.}}&lt;br /&gt;
&lt;br /&gt;
[http://plugins.qgis.org/plugins/reconstruct_line/ ReconstructLine] - это инструмент для интерактивного создания линейных объектов по точечным.&lt;br /&gt;
&lt;br /&gt;
Вы наверняка сталкивались с инструментом объединяющим точки в линии. Все такие инструменты работают либо последовательно, т.е. точки объединяются в линии так, как они идут в таблице, либо про атрибутам. Теперь представьте, что вам не важен порядок записей в таблице и атрибутивная информация отсутствует или бесполезна, что вам все равно нужно объединить точки в линию. &lt;br /&gt;
&lt;br /&gt;
Расширение ReconstructLine умеет восстанавливать линии по точкам используя '''только''' их пространственное расположение, &amp;quot;восстанавливая&amp;quot; линию. Поскольку восстановление это сложный алгоритм, ReconstructLine работает только интерактивно. Процесс восстановления может занять значительное время, если точек много.&lt;br /&gt;
&lt;br /&gt;
ReconstructLine плохо подходит для облаков точек.&lt;br /&gt;
&lt;br /&gt;
{{NextGIS}}&lt;br /&gt;
&lt;br /&gt;
=== Замечания по установке ===&lt;br /&gt;
&lt;br /&gt;
Расширение доступно из [http://plugins.qgis.org/plugins/reconstruct_line/ официального репозитория].&lt;br /&gt;
&lt;br /&gt;
ReconstructLine находится в разработке и протестирован с QGIS 2.6 и выше. Расширение работает в Windows и Linux (Ubuntu).&lt;br /&gt;
&lt;br /&gt;
Исходный код модуля доступен в ([https://github.com/nextgis/ReconstructLine репозитории] на Github).&lt;br /&gt;
&lt;br /&gt;
=== Алгоритм ===&lt;br /&gt;
При разработке модуля принималось во внимание то, что точки можно соединить между собой &amp;quot;логичным&amp;quot; образом, если они образуют &amp;quot;видимую глазами&amp;quot; кривую линию. В этом случае задачу можно сформулировать следующим образом:&lt;br /&gt;
&lt;br /&gt;
* Дан набор точек &amp;lt;math&amp;gt;T_1, T_2, \dots T_n&amp;lt;/math&amp;gt;.&lt;br /&gt;
* Дана метрика &amp;lt;math&amp;gt;d(T_i, T_j)&amp;lt;/math&amp;gt; -- функция, которая измеряет расстояния между произвольной парой точек. Тогда потенциальной восстановленной кривой (т.е. последовательности точек &amp;lt;math&amp;gt;(T_{i_1}, T_{i_2}, ..., T_{i_n})&amp;lt;/math&amp;gt;) можно поставить в соответствие её длину, равную сумме растояний между парами точек, составляющих восстановленную кривую: &amp;lt;math&amp;gt;L = d(T_{i_1}, T_{i_2}) + d(T_{i_2}, T_{i_3}) + \dots + d(T_{i_{n-1}}, T_{i_n})&amp;lt;/math&amp;gt;.&lt;br /&gt;
* Требуется найти среди всех комбинаций &amp;lt;math&amp;gt;(T_{i_1}, T_{i_2}, ..., T_{i_n})&amp;lt;/math&amp;gt; такую комбинацию, для которой ее длина L будет минимальной.&lt;br /&gt;
&lt;br /&gt;
Нужно заметить, что требование того, что восстановленная кривая должна иметь минимальную длину из всех возможных комбинаций точек -- чисто эвристическое допущение, которое, тем не менее, хорошо согласуется с реальным положением дел. (Чтобы убедиться в этом достаточно нарисовать кривую, измерить ее длину, затем &amp;quot;перепутать&amp;quot; в ней пару или несколько пар точек и измерить длину новой кривой).&lt;br /&gt;
&lt;br /&gt;
Приведенная выше формулировка задачи представляет собой хорошо известную задачу поиска Гамильтонова пути. Также хорошо известно, что эта задача уже при небольшом числе точек не может быть решена &amp;quot;в лоб&amp;quot; простым перебором вариантов, поскольку их число взрыовобразно растет. Так, например, для пяти точек будет всего 60 (т.е. 5!/2) возможных комбинаций, для десяти точек -- уже почти два миллиона, а, например, для тридцати -- количество комбинаций описывется числом, состоящим из 34-х цифр.&lt;br /&gt;
&lt;br /&gt;
Поэтому алгоритмы построения Гамильтонова пути, используемые на практике, представляют собой субоптимальные алгоритмы, которые позволяют найти хорошее решение за приемлемое время, но не гарантируют того, что оно будет лучшим из всех возможных. В данном модуле в качестве основного алгорима использовались  [https://ru.wikipedia.org/wiki/%D0%A1%D0%B0%D0%BC%D0%BE%D0%BE%D1%80%D0%B3%D0%B0%D0%BD%D0%B8%D0%B7%D1%83%D1%8E%D1%89%D0%B0%D1%8F%D1%81%D1%8F_%D0%BA%D0%B0%D1%80%D1%82%D0%B0_%D0%9A%D0%BE%D1%85%D0%BE%D0%BD%D0%B5%D0%BD%D0%B0 самоорганизующиеся карты Кохонена]. Поскольку перед нами стоит задача восстановления линии, то и архитектура сети была выбрана линейной. Обученная сеть упорядочивает точки, и в целом обеспечивает неплохой результат работы. Но в некоторых случаях &amp;quot;неудачного&amp;quot; расположения входных точек с одним узлом сети оказываются связаны несколько точек, их упорядоченность может оказаться нарушенной. Для того, чтобы отследить подобные случаи, в модуле используется постобработка: в упорядоченном картой Кохонена наборе точек производятся попарные перестановки соседних точек и измеряется совокупная длина линии. В итоге линия наименьшей длины возвращается в качестве результата алгоритма.&lt;br /&gt;
&lt;br /&gt;
=== Работа с расширением ===&lt;br /&gt;
&lt;br /&gt;
После установки расширения появится новая панель инструментов с двумя кнопками: &amp;quot;копировать точки&amp;quot; и &amp;quot;вставить линию&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
[[Файл:Reconstructline-01.png|center]]&lt;br /&gt;
&lt;br /&gt;
Предположим, что исходный набор точек выглядит следующим образом (обратите внимание на нумерацию, она отражает последовательность точек в таблице):&lt;br /&gt;
&lt;br /&gt;
[[Файл:Reconstructline-02.png|center|thumb|600px|Исходные точки]]&lt;br /&gt;
&lt;br /&gt;
Что будет, если просто соединить их в линию (например с помощью расширения Points2One):&lt;br /&gt;
&lt;br /&gt;
[[Файл:Reconstructline-03.png|center|thumb|600px|Последовательное объединение точек в линию]]&lt;br /&gt;
&lt;br /&gt;
Для объединения с помощью ReconstructLine:&lt;br /&gt;
&lt;br /&gt;
1. Инструментом выделения выделите нужные точки, нажмите на кнопку &amp;quot;копировать точки&amp;quot; в панели инструментов ReconstructLine&lt;br /&gt;
&lt;br /&gt;
2. Вставьте линию в существующий или новый линейный слой, нажмите на кнопку &amp;quot;вставить линию&amp;quot; в панели инструментов ReconstructLine&lt;br /&gt;
&lt;br /&gt;
Результат должен выглядеть более логично:&lt;br /&gt;
&lt;br /&gt;
[[Файл:Reconstructline-04.png|center|thumb|600px|Объединение точек в линию с помощью ReconstructLine]]&lt;br /&gt;
&lt;br /&gt;
=== Контакты ===&lt;br /&gt;
&lt;br /&gt;
Если вы нашли ошибку или у вас есть предложения по улучшению расширения — воспользуйтесь [https://github.com/nextgis/shortcut_manager/issues багтрекером]. Кроме того, вопросы по использованию расширения можно задать авторам [http://nextgis.ru/contact/ напрямую].&lt;br /&gt;
&lt;br /&gt;
=== Ссылки по теме ===&lt;br /&gt;
&lt;br /&gt;
* [http://gis-lab.info/qa/qgis-install-plugin.html Установка модулей расширения в QGIS]&lt;br /&gt;
* [http://gis-lab.info/docs/qgis/ Документация по QGIS]&lt;/div&gt;</summary>
		<author><name>KolesovDmitry</name></author>
	</entry>
	<entry>
		<id>https://wiki.gis-lab.info/index.php?title=ReconstructLine_-_%D0%B2%D0%BE%D1%81%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BB%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BB%D0%B8%D0%BD%D0%B8%D0%B9_%D0%BF%D0%BE_%D1%82%D0%BE%D1%87%D0%BA%D0%B0%D0%BC_%D0%B2_QGIS&amp;diff=21920</id>
		<title>ReconstructLine - восстановление линий по точкам в QGIS</title>
		<link rel="alternate" type="text/html" href="https://wiki.gis-lab.info/index.php?title=ReconstructLine_-_%D0%B2%D0%BE%D1%81%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BB%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BB%D0%B8%D0%BD%D0%B8%D0%B9_%D0%BF%D0%BE_%D1%82%D0%BE%D1%87%D0%BA%D0%B0%D0%BC_%D0%B2_QGIS&amp;diff=21920"/>
		<updated>2015-04-28T07:17:35Z</updated>

		<summary type="html">&lt;p&gt;KolesovDmitry: /* Алгоритм */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Статья|Черновик|reconstructline}}&lt;br /&gt;
{{Аннотация|Описание инструмента для создания линейных объектов в QGIS.}}&lt;br /&gt;
&lt;br /&gt;
[http://plugins.qgis.org/plugins/reconstruct_line/ ReconstructLine] - это инструмент для интерактивного создания линейных объектов по точечным.&lt;br /&gt;
&lt;br /&gt;
Вы наверняка сталкивались с инструментом объединяющим точки в линии. Все такие инструменты работают либо последовательно, т.е. точки объединяются в линии так, как они идут в таблице, либо про атрибутам. Теперь представьте, что вам не важен порядок записей в таблице и атрибутивная информация отсутствует или бесполезна, что вам все равно нужно объединить точки в линию. &lt;br /&gt;
&lt;br /&gt;
Расширение ReconstructLine умеет восстанавливать линии по точкам используя '''только''' их пространственное расположение, &amp;quot;восстанавливая&amp;quot; линию. Поскольку восстановление это сложный алгоритм, ReconstructLine работает только интерактивно. Процесс восстановления может занять значительное время, если точек много.&lt;br /&gt;
&lt;br /&gt;
ReconstructLine плохо подходит для облаков точек.&lt;br /&gt;
&lt;br /&gt;
{{NextGIS}}&lt;br /&gt;
&lt;br /&gt;
=== Замечания по установке ===&lt;br /&gt;
&lt;br /&gt;
Расширение доступно из [http://plugins.qgis.org/plugins/reconstruct_line/ официального репозитория].&lt;br /&gt;
&lt;br /&gt;
ReconstructLine находится в разработке и протестирован с QGIS 2.6 и выше. Расширение работает в Windows и Linux (Ubuntu).&lt;br /&gt;
&lt;br /&gt;
Исходный код модуля доступен в ([https://github.com/nextgis/ReconstructLine репозитории] на Github).&lt;br /&gt;
&lt;br /&gt;
=== Алгоритм ===&lt;br /&gt;
При разработке модуля принималось во внимание то, что точки можно соединить между собой &amp;quot;логичным&amp;quot; образом, если они образуют &amp;quot;видимую глазами&amp;quot; кривую линию. В этом случае задачу можно сформулировать следующим образом:&lt;br /&gt;
&lt;br /&gt;
* Дан набор точек &amp;lt;math&amp;gt;T_1, T_2, \dots T_n&amp;lt;/math&amp;gt;.&lt;br /&gt;
* Дана метрика &amp;lt;math&amp;gt;d(T_i, T_j)&amp;lt;/math&amp;gt; -- функция, которая измеряет расстояния между произвольной парой точек. Тогда потенциальной восстановленной кривой (т.е. последовательности точек &amp;lt;math&amp;gt;(T_{i_1}, T_{i_2}, ..., T_{i_n})&amp;lt;/math&amp;gt;) можно поставить в соответствие её длину, равную сумме растояний между парами точек, составляющих восстановленную кривую: &amp;lt;math&amp;gt;L = d(T_{i_1}, T_{i_2}) + d(T_{i_2}, T_{i_3}) + \dots + d(T_{i_{n-1}}, T_{i_n})&amp;lt;/math&amp;gt;.&lt;br /&gt;
* Требуется найти среди всех комбинаций &amp;lt;math&amp;gt;(T_{i_1}, T_{i_2}, ..., T_{i_n})&amp;lt;/math&amp;gt; такую комбинацию, для которой ее длина L будет минимальной.&lt;br /&gt;
&lt;br /&gt;
Нужно заметить, что требование того, что восстановленная кривая должна иметь минимальную длину из всех возможных комбинаций точек -- чисто эвристическое допущение, которое, тем не менее, хорошо согласуется с реальным положением дел. (Чтобы убедиться в этом достаточно нарисовать кривую, измерить ее длину, затем &amp;quot;перепутать&amp;quot; в ней пару или несколько пар точек и измерить длину новой кривой).&lt;br /&gt;
&lt;br /&gt;
Приведенная выше формулировка задачи представляет собой хорошо известную задачи поиска Гамильтонова пути. Также хорошо известно, что эта задача уже при небольшом числе точек не может быть решена &amp;quot;в лоб&amp;quot; простым перебором вариантов поскольку их число взрыовобразно растет. Так, например, для пяти точек будет всего 60 (т.е. 5!/2) возможных комбинаций, для десяти точек -- уже почти два миллиона, а, например, для тридцати -- количество комбинаций описывется числом, состоящим из 34-х цифр.&lt;br /&gt;
&lt;br /&gt;
Поэтому алгоритмы построения Гамильтонова пути, используемые на практике, представляют собой субоптимальные алгоритмы, которые позволяют найти хорошее решение за приемлемое время, но не гарантируют того, что оно будет лучшим из всех возможных. В данном модуле в качестве основного алгорима использовались  [https://ru.wikipedia.org/wiki/%D0%A1%D0%B0%D0%BC%D0%BE%D0%BE%D1%80%D0%B3%D0%B0%D0%BD%D0%B8%D0%B7%D1%83%D1%8E%D1%89%D0%B0%D1%8F%D1%81%D1%8F_%D0%BA%D0%B0%D1%80%D1%82%D0%B0_%D0%9A%D0%BE%D1%85%D0%BE%D0%BD%D0%B5%D0%BD%D0%B0 самоорганизующиеся карты Кохонена]. Поскольку перед нами стоит задача восстановления линии, то и архитектура сети была выбрана линейной. Обученная сеть упорядочивает точки, и в целом обеспечивает неплохой результат работы. Но в некоторых случаях &amp;quot;неудачного&amp;quot; расположения входных точек с одним узлом сети оказываются связаны несколько точек, их упорядоченность может оказаться нарушенной. Для того, чтобы отследить подобные случаи, в модуле используется постобработка: в упорядоченном картой Кохонена наборе точек производятся попарные перестановки соседних точек и измеряется совокупная длина линии. В итоге линия наименьшей длины возвращается в качестве результата алгоритма.&lt;br /&gt;
&lt;br /&gt;
=== Работа с расширением ===&lt;br /&gt;
&lt;br /&gt;
После установки расширения появится новая панель инструментов с двумя кнопками: &amp;quot;копировать точки&amp;quot; и &amp;quot;вставить линию&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
[[Файл:Reconstructline-01.png|center]]&lt;br /&gt;
&lt;br /&gt;
Предположим, что исходный набор точек выглядит следующим образом (обратите внимание на нумерацию, она отражает последовательность точек в таблице):&lt;br /&gt;
&lt;br /&gt;
[[Файл:Reconstructline-02.png|center|thumb|600px|Исходные точки]]&lt;br /&gt;
&lt;br /&gt;
Что будет, если просто соединить их в линию (например с помощью расширения Points2One):&lt;br /&gt;
&lt;br /&gt;
[[Файл:Reconstructline-03.png|center|thumb|600px|Последовательное объединение точек в линию]]&lt;br /&gt;
&lt;br /&gt;
Для объединения с помощью ReconstructLine:&lt;br /&gt;
&lt;br /&gt;
1. Инструментом выделения выделите нужные точки, нажмите на кнопку &amp;quot;копировать точки&amp;quot; в панели инструментов ReconstructLine&lt;br /&gt;
&lt;br /&gt;
2. Вставьте линию в существующий или новый линейный слой, нажмите на кнопку &amp;quot;вставить линию&amp;quot; в панели инструментов ReconstructLine&lt;br /&gt;
&lt;br /&gt;
Результат должен выглядеть более логично:&lt;br /&gt;
&lt;br /&gt;
[[Файл:Reconstructline-04.png|center|thumb|600px|Объединение точек в линию с помощью ReconstructLine]]&lt;br /&gt;
&lt;br /&gt;
=== Контакты ===&lt;br /&gt;
&lt;br /&gt;
Если вы нашли ошибку или у вас есть предложения по улучшению расширения — воспользуйтесь [https://github.com/nextgis/shortcut_manager/issues багтрекером]. Кроме того, вопросы по использованию расширения можно задать авторам [http://nextgis.ru/contact/ напрямую].&lt;br /&gt;
&lt;br /&gt;
=== Ссылки по теме ===&lt;br /&gt;
&lt;br /&gt;
* [http://gis-lab.info/qa/qgis-install-plugin.html Установка модулей расширения в QGIS]&lt;br /&gt;
* [http://gis-lab.info/docs/qgis/ Документация по QGIS]&lt;/div&gt;</summary>
		<author><name>KolesovDmitry</name></author>
	</entry>
	<entry>
		<id>https://wiki.gis-lab.info/index.php?title=ReconstructLine_-_%D0%B2%D0%BE%D1%81%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BB%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BB%D0%B8%D0%BD%D0%B8%D0%B9_%D0%BF%D0%BE_%D1%82%D0%BE%D1%87%D0%BA%D0%B0%D0%BC_%D0%B2_QGIS&amp;diff=21919</id>
		<title>ReconstructLine - восстановление линий по точкам в QGIS</title>
		<link rel="alternate" type="text/html" href="https://wiki.gis-lab.info/index.php?title=ReconstructLine_-_%D0%B2%D0%BE%D1%81%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BB%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BB%D0%B8%D0%BD%D0%B8%D0%B9_%D0%BF%D0%BE_%D1%82%D0%BE%D1%87%D0%BA%D0%B0%D0%BC_%D0%B2_QGIS&amp;diff=21919"/>
		<updated>2015-04-28T07:14:57Z</updated>

		<summary type="html">&lt;p&gt;KolesovDmitry: /* Алгоритм */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Статья|Черновик|reconstructline}}&lt;br /&gt;
{{Аннотация|Описание инструмента для создания линейных объектов в QGIS.}}&lt;br /&gt;
&lt;br /&gt;
[http://plugins.qgis.org/plugins/reconstruct_line/ ReconstructLine] - это инструмент для интерактивного создания линейных объектов по точечным.&lt;br /&gt;
&lt;br /&gt;
Вы наверняка сталкивались с инструментом объединяющим точки в линии. Все такие инструменты работают либо последовательно, т.е. точки объединяются в линии так, как они идут в таблице, либо про атрибутам. Теперь представьте, что вам не важен порядок записей в таблице и атрибутивная информация отсутствует или бесполезна, что вам все равно нужно объединить точки в линию. &lt;br /&gt;
&lt;br /&gt;
Расширение ReconstructLine умеет восстанавливать линии по точкам используя '''только''' их пространственное расположение, &amp;quot;восстанавливая&amp;quot; линию. Поскольку восстановление это сложный алгоритм, ReconstructLine работает только интерактивно. Процесс восстановления может занять значительное время, если точек много.&lt;br /&gt;
&lt;br /&gt;
ReconstructLine плохо подходит для облаков точек.&lt;br /&gt;
&lt;br /&gt;
{{NextGIS}}&lt;br /&gt;
&lt;br /&gt;
=== Замечания по установке ===&lt;br /&gt;
&lt;br /&gt;
Расширение доступно из [http://plugins.qgis.org/plugins/reconstruct_line/ официального репозитория].&lt;br /&gt;
&lt;br /&gt;
ReconstructLine находится в разработке и протестирован с QGIS 2.6 и выше. Расширение работает в Windows и Linux (Ubuntu).&lt;br /&gt;
&lt;br /&gt;
Исходный код модуля доступен в ([https://github.com/nextgis/ReconstructLine репозитории] на Github).&lt;br /&gt;
&lt;br /&gt;
=== Алгоритм ===&lt;br /&gt;
При разработке модуля принималось во внимание то, что точки можно соединить между собой &amp;quot;логичным&amp;quot; образом, если они образуют &amp;quot;видимую глазами&amp;quot; кривую линию. В этом случае задачу можно сформулировать следующим образом:&lt;br /&gt;
&lt;br /&gt;
* Дан набор точек &amp;lt;math&amp;gt;T_1, T_2, \dots T_n&amp;lt;/math&amp;gt;.&lt;br /&gt;
* Дана метрика &amp;lt;math&amp;gt;d(T_i, T_j)&amp;lt;/math&amp;gt; -- функция, которая измеряет расстояния между произвольной парой точек. Тогда потенциальной восстановленной кривой (т.е. последовательности точек &amp;lt;math&amp;gt;(T_{i_1}, T_{i_2}, ..., T_{i_n})&amp;lt;/math&amp;gt;) можно поставить в соответствие её длину, равную сумме растояний между парами точек, составляющих восстановленную кривую: &amp;lt;math&amp;gt;L = d(T_{i_1}, T_{i_2}) + d(T_{i_2}, T_{i_3}) + \dots + d(T_{i_{n-1}}, T_{i_n})&amp;lt;/math&amp;gt;.&lt;br /&gt;
* Требуется найти среди всех комбинаций &amp;lt;math&amp;gt;(T_{i_1}, T_{i_2}, ..., T_{i_n})&amp;lt;/math&amp;gt; такую комбинацию, для которой ее длина L будет минимальной.&lt;br /&gt;
&lt;br /&gt;
Нужно заметить, что требование того, что восстановленная кривая должна иметь минимальную длину из всех возможных комбинаций точек -- чисто эвристическое допущение, которое, тем не менее, хорошо согласуется с реальным положением дел. (Чтобы убедиться в этом достаточно нарисовать кривую, измерить ее длину, затем &amp;quot;перепутать&amp;quot; в ней пару или несколько пар точек и измерить длину новой кривой).&lt;br /&gt;
&lt;br /&gt;
Приведенная выше формулировка задачи представляет собой по сути хорошо известную задачи поиска Гамильтонова пути. Также хорошо известно, что эта задача уже при небольшом числе точек не может быть решена &amp;quot;в лоб&amp;quot; простым перебором вариантов поскольку их число взрыовобразно растет. Так, например, для пяти точке будет всего 60 (5!/2) возможных комбинаций, для десяти точек -- уже почти два миллиона, а для тридцати - количество комбинаций описывется числом, состоящим из 34-х цифр.&lt;br /&gt;
&lt;br /&gt;
Поэтому алгоритмы построения Гамильтонова пути, используемые на практике, представляют собой субоптимальные алгоритмы, которые позволяют найти хорошее решение за приемлемое время, но не гарантируют того, что оно будет лучшим из всех возможных. В данном плагине в качестве основного алгорима использовались  [https://ru.wikipedia.org/wiki/%D0%A1%D0%B0%D0%BC%D0%BE%D0%BE%D1%80%D0%B3%D0%B0%D0%BD%D0%B8%D0%B7%D1%83%D1%8E%D1%89%D0%B0%D1%8F%D1%81%D1%8F_%D0%BA%D0%B0%D1%80%D1%82%D0%B0_%D0%9A%D0%BE%D1%85%D0%BE%D0%BD%D0%B5%D0%BD%D0%B0 самоорганизующиеся карты Кохонена]. Поскольку перед нами стоит задача восстановления линии, то и архитектура сети была выбрана линейной. Обученная сеть упорядочивает точки, и в целом обеспечивает неплохой результат работы. Но в некоторых случаях &amp;quot;неудачного&amp;quot; расположения входных точек с одним узлом сети оказываются связаны несколько точек, их упорядоченность может оказаться нарушенной. Для того, чтобы отследить подобные случаи в модуле используется постобработка: в упорядоченном картой Кохонена наборе точек производятся попарные перестановки соседних точек и измеряется совокупная длина линии. В итоге линия наименьшей длины возвращается в качестве результата алгоритма.&lt;br /&gt;
&lt;br /&gt;
=== Работа с расширением ===&lt;br /&gt;
&lt;br /&gt;
После установки расширения появится новая панель инструментов с двумя кнопками: &amp;quot;копировать точки&amp;quot; и &amp;quot;вставить линию&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
[[Файл:Reconstructline-01.png|center]]&lt;br /&gt;
&lt;br /&gt;
Предположим, что исходный набор точек выглядит следующим образом (обратите внимание на нумерацию, она отражает последовательность точек в таблице):&lt;br /&gt;
&lt;br /&gt;
[[Файл:Reconstructline-02.png|center|thumb|600px|Исходные точки]]&lt;br /&gt;
&lt;br /&gt;
Что будет, если просто соединить их в линию (например с помощью расширения Points2One):&lt;br /&gt;
&lt;br /&gt;
[[Файл:Reconstructline-03.png|center|thumb|600px|Последовательное объединение точек в линию]]&lt;br /&gt;
&lt;br /&gt;
Для объединения с помощью ReconstructLine:&lt;br /&gt;
&lt;br /&gt;
1. Инструментом выделения выделите нужные точки, нажмите на кнопку &amp;quot;копировать точки&amp;quot; в панели инструментов ReconstructLine&lt;br /&gt;
&lt;br /&gt;
2. Вставьте линию в существующий или новый линейный слой, нажмите на кнопку &amp;quot;вставить линию&amp;quot; в панели инструментов ReconstructLine&lt;br /&gt;
&lt;br /&gt;
Результат должен выглядеть более логично:&lt;br /&gt;
&lt;br /&gt;
[[Файл:Reconstructline-04.png|center|thumb|600px|Объединение точек в линию с помощью ReconstructLine]]&lt;br /&gt;
&lt;br /&gt;
=== Контакты ===&lt;br /&gt;
&lt;br /&gt;
Если вы нашли ошибку или у вас есть предложения по улучшению расширения — воспользуйтесь [https://github.com/nextgis/shortcut_manager/issues багтрекером]. Кроме того, вопросы по использованию расширения можно задать авторам [http://nextgis.ru/contact/ напрямую].&lt;br /&gt;
&lt;br /&gt;
=== Ссылки по теме ===&lt;br /&gt;
&lt;br /&gt;
* [http://gis-lab.info/qa/qgis-install-plugin.html Установка модулей расширения в QGIS]&lt;br /&gt;
* [http://gis-lab.info/docs/qgis/ Документация по QGIS]&lt;/div&gt;</summary>
		<author><name>KolesovDmitry</name></author>
	</entry>
	<entry>
		<id>https://wiki.gis-lab.info/index.php?title=ReconstructLine_-_%D0%B2%D0%BE%D1%81%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BB%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BB%D0%B8%D0%BD%D0%B8%D0%B9_%D0%BF%D0%BE_%D1%82%D0%BE%D1%87%D0%BA%D0%B0%D0%BC_%D0%B2_QGIS&amp;diff=21918</id>
		<title>ReconstructLine - восстановление линий по точкам в QGIS</title>
		<link rel="alternate" type="text/html" href="https://wiki.gis-lab.info/index.php?title=ReconstructLine_-_%D0%B2%D0%BE%D1%81%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BB%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BB%D0%B8%D0%BD%D0%B8%D0%B9_%D0%BF%D0%BE_%D1%82%D0%BE%D1%87%D0%BA%D0%B0%D0%BC_%D0%B2_QGIS&amp;diff=21918"/>
		<updated>2015-04-28T07:04:34Z</updated>

		<summary type="html">&lt;p&gt;KolesovDmitry: /* Алгоритм */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Статья|Черновик|reconstructline}}&lt;br /&gt;
{{Аннотация|Описание инструмента для создания линейных объектов в QGIS.}}&lt;br /&gt;
&lt;br /&gt;
[http://plugins.qgis.org/plugins/reconstruct_line/ ReconstructLine] - это инструмент для интерактивного создания линейных объектов по точечным.&lt;br /&gt;
&lt;br /&gt;
Вы наверняка сталкивались с инструментом объединяющим точки в линии. Все такие инструменты работают либо последовательно, т.е. точки объединяются в линии так, как они идут в таблице, либо про атрибутам. Теперь представьте, что вам не важен порядок записей в таблице и атрибутивная информация отсутствует или бесполезна, что вам все равно нужно объединить точки в линию. &lt;br /&gt;
&lt;br /&gt;
Расширение ReconstructLine умеет восстанавливать линии по точкам используя '''только''' их пространственное расположение, &amp;quot;восстанавливая&amp;quot; линию. Поскольку восстановление это сложный алгоритм, ReconstructLine работает только интерактивно. Процесс восстановления может занять значительное время, если точек много.&lt;br /&gt;
&lt;br /&gt;
ReconstructLine плохо подходит для облаков точек.&lt;br /&gt;
&lt;br /&gt;
{{NextGIS}}&lt;br /&gt;
&lt;br /&gt;
=== Замечания по установке ===&lt;br /&gt;
&lt;br /&gt;
Расширение доступно из [http://plugins.qgis.org/plugins/reconstruct_line/ официального репозитория].&lt;br /&gt;
&lt;br /&gt;
ReconstructLine находится в разработке и протестирован с QGIS 2.6 и выше. Расширение работает в Windows и Linux (Ubuntu).&lt;br /&gt;
&lt;br /&gt;
Исходный код модуля доступен в ([https://github.com/nextgis/ReconstructLine репозитории] на Github).&lt;br /&gt;
&lt;br /&gt;
=== Алгоритм ===&lt;br /&gt;
При разработке модуля принималось во внимание то, что точки можно соединить между собой &amp;quot;логичным&amp;quot; образом, если они образуют &amp;quot;видимую глазами&amp;quot; кривую линию. В этом случае задачу можно сформулировать следующим образом:&lt;br /&gt;
&lt;br /&gt;
* Дан набор точек &amp;lt;math&amp;gt;T_1, T_2, \dots T_n&amp;lt;/math&amp;gt;.&lt;br /&gt;
* Дана метрика &amp;lt;math&amp;gt;d(T_i, T_j)&amp;lt;/math&amp;gt; -- функция, которая измеряет расстояния между произвольной парой точек. Тогда потенциальной восстановленной кривой (т.е. последовательности точек &amp;lt;math&amp;gt;(T_{i_1}, T_{i_2}, ..., T_{i_n})&amp;lt;/math&amp;gt;) можно поставить в соответствие её длину, равную сумме растояний между парами точек, составляющих восстановленную кривую: &amp;lt;math&amp;gt;L = d(T_{i_1}, T_{i_2}) + d(T_{i_2}, T_{i_3}) + \dots + d(T_{i_{n-1}}, T_{i_n})&amp;lt;/math&amp;gt;.&lt;br /&gt;
* Требуется найти среди всех комбинаций &amp;lt;math&amp;gt;(T_{i_1}, T_{i_2}, ..., T_{i_n})&amp;lt;/math&amp;gt; такую комбинацию, для которой ее длина L будет минимальной.&lt;br /&gt;
&lt;br /&gt;
Требование того, что восстановленная кривая должна иметь минимальную длину из всех возможных комбинаций -- чисто эвристическое допущение, которое, тем не менее, хорошо согласуется с реальным положением дел. (Чтобы убедиться в этом достаточно нарисовать кривую, измерить ее длину, затем &amp;quot;перепутать&amp;quot; в ней пару или несколько пар точек и измерить длину новой кривой).&lt;br /&gt;
&lt;br /&gt;
Приведенная выше формулировка задачи представляет собой по сути хорошо известную задачи поиска Гамильтонова пути. Также хорошо известно, что эта задача уже при небольшом числе точек не может быть решена &amp;quot;в лоб&amp;quot; простым перебором вариантов поскольку их число взрыовобразно растет. Так, например, для пяти точке будет всего 60 (5!/2) возможных комбинаций, для десяти точек -- уже почти два миллиона, а для тридцати - количество комбинаций описывется числом, состоящим из 34-х цифр.&lt;br /&gt;
&lt;br /&gt;
Поэтому алгоритмы построения Гамильтонова пути, используемые на практике, все представляют собой субоптимальные алгоритмы, которые позволяют найти хорошее решение за приемлемое время, но не гарантируют того, что оно будет лучшим из всех возможных. В данном плагине в качестве основного алгорима использовались  [https://ru.wikipedia.org/wiki/%D0%A1%D0%B0%D0%BC%D0%BE%D0%BE%D1%80%D0%B3%D0%B0%D0%BD%D0%B8%D0%B7%D1%83%D1%8E%D1%89%D0%B0%D1%8F%D1%81%D1%8F_%D0%BA%D0%B0%D1%80%D1%82%D0%B0_%D0%9A%D0%BE%D1%85%D0%BE%D0%BD%D0%B5%D0%BD%D0%B0 самоорганизующиеся карты Кохонена].&lt;br /&gt;
&lt;br /&gt;
=== Работа с расширением ===&lt;br /&gt;
&lt;br /&gt;
После установки расширения появится новая панель инструментов с двумя кнопками: &amp;quot;копировать точки&amp;quot; и &amp;quot;вставить линию&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
[[Файл:Reconstructline-01.png|center]]&lt;br /&gt;
&lt;br /&gt;
Предположим, что исходный набор точек выглядит следующим образом (обратите внимание на нумерацию, она отражает последовательность точек в таблице):&lt;br /&gt;
&lt;br /&gt;
[[Файл:Reconstructline-02.png|center|thumb|600px|Исходные точки]]&lt;br /&gt;
&lt;br /&gt;
Что будет, если просто соединить их в линию (например с помощью расширения Points2One):&lt;br /&gt;
&lt;br /&gt;
[[Файл:Reconstructline-03.png|center|thumb|600px|Последовательное объединение точек в линию]]&lt;br /&gt;
&lt;br /&gt;
Для объединения с помощью ReconstructLine:&lt;br /&gt;
&lt;br /&gt;
1. Инструментом выделения выделите нужные точки, нажмите на кнопку &amp;quot;копировать точки&amp;quot; в панели инструментов ReconstructLine&lt;br /&gt;
&lt;br /&gt;
2. Вставьте линию в существующий или новый линейный слой, нажмите на кнопку &amp;quot;вставить линию&amp;quot; в панели инструментов ReconstructLine&lt;br /&gt;
&lt;br /&gt;
Результат должен выглядеть более логично:&lt;br /&gt;
&lt;br /&gt;
[[Файл:Reconstructline-04.png|center|thumb|600px|Объединение точек в линию с помощью ReconstructLine]]&lt;br /&gt;
&lt;br /&gt;
=== Контакты ===&lt;br /&gt;
&lt;br /&gt;
Если вы нашли ошибку или у вас есть предложения по улучшению расширения — воспользуйтесь [https://github.com/nextgis/shortcut_manager/issues багтрекером]. Кроме того, вопросы по использованию расширения можно задать авторам [http://nextgis.ru/contact/ напрямую].&lt;br /&gt;
&lt;br /&gt;
=== Ссылки по теме ===&lt;br /&gt;
&lt;br /&gt;
* [http://gis-lab.info/qa/qgis-install-plugin.html Установка модулей расширения в QGIS]&lt;br /&gt;
* [http://gis-lab.info/docs/qgis/ Документация по QGIS]&lt;/div&gt;</summary>
		<author><name>KolesovDmitry</name></author>
	</entry>
	<entry>
		<id>https://wiki.gis-lab.info/index.php?title=ReconstructLine_-_%D0%B2%D0%BE%D1%81%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BB%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BB%D0%B8%D0%BD%D0%B8%D0%B9_%D0%BF%D0%BE_%D1%82%D0%BE%D1%87%D0%BA%D0%B0%D0%BC_%D0%B2_QGIS&amp;diff=21917</id>
		<title>ReconstructLine - восстановление линий по точкам в QGIS</title>
		<link rel="alternate" type="text/html" href="https://wiki.gis-lab.info/index.php?title=ReconstructLine_-_%D0%B2%D0%BE%D1%81%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BB%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BB%D0%B8%D0%BD%D0%B8%D0%B9_%D0%BF%D0%BE_%D1%82%D0%BE%D1%87%D0%BA%D0%B0%D0%BC_%D0%B2_QGIS&amp;diff=21917"/>
		<updated>2015-04-28T07:00:12Z</updated>

		<summary type="html">&lt;p&gt;KolesovDmitry: /* Алгоритм */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Статья|Черновик|reconstructline}}&lt;br /&gt;
{{Аннотация|Описание инструмента для создания линейных объектов в QGIS.}}&lt;br /&gt;
&lt;br /&gt;
[http://plugins.qgis.org/plugins/reconstruct_line/ ReconstructLine] - это инструмент для интерактивного создания линейных объектов по точечным.&lt;br /&gt;
&lt;br /&gt;
Вы наверняка сталкивались с инструментом объединяющим точки в линии. Все такие инструменты работают либо последовательно, т.е. точки объединяются в линии так, как они идут в таблице, либо про атрибутам. Теперь представьте, что вам не важен порядок записей в таблице и атрибутивная информация отсутствует или бесполезна, что вам все равно нужно объединить точки в линию. &lt;br /&gt;
&lt;br /&gt;
Расширение ReconstructLine умеет восстанавливать линии по точкам используя '''только''' их пространственное расположение, &amp;quot;восстанавливая&amp;quot; линию. Поскольку восстановление это сложный алгоритм, ReconstructLine работает только интерактивно. Процесс восстановления может занять значительное время, если точек много.&lt;br /&gt;
&lt;br /&gt;
ReconstructLine плохо подходит для облаков точек.&lt;br /&gt;
&lt;br /&gt;
{{NextGIS}}&lt;br /&gt;
&lt;br /&gt;
=== Замечания по установке ===&lt;br /&gt;
&lt;br /&gt;
Расширение доступно из [http://plugins.qgis.org/plugins/reconstruct_line/ официального репозитория].&lt;br /&gt;
&lt;br /&gt;
ReconstructLine находится в разработке и протестирован с QGIS 2.6 и выше. Расширение работает в Windows и Linux (Ubuntu).&lt;br /&gt;
&lt;br /&gt;
Исходный код модуля доступен в ([https://github.com/nextgis/ReconstructLine репозитории] на Github).&lt;br /&gt;
&lt;br /&gt;
=== Алгоритм ===&lt;br /&gt;
При разработке модуля принималось во внимание то, что точки можно соединить между собой &amp;quot;логичным&amp;quot; образом, если они образуют &amp;quot;видимую глазами&amp;quot; кривую линию. В этом случае задачу можно сформулировать следующим образом:&lt;br /&gt;
&lt;br /&gt;
* Дан набор точек T1, T2, ... Tn.&lt;br /&gt;
* Дана метрика d(Ti, Tj) -- функция, которая измеряет расстояния между произвольной парой точек. Тогда потенциальной восстановленной кривой (т.е. последовательности точек (Ti1, Ti2, ..., Tin)) можно поставить в соответствие её длину, равную сумме растояний между парами точек, составляющих восстановленную кривую: L = d(Ti1, Ti2) + d(Ti2, Ti3) + .... + d(Tin-1, Tin).&lt;br /&gt;
* Требуется найти среди всех комбинаций (Ti1, Ti2, ..., Tin) такую комбинацию, для которой ее длина L будет минимальной.&lt;br /&gt;
&lt;br /&gt;
Требование того, что восстановленная кривая должна иметь минимальную длину из всех возможных комбинаций -- чисто эвристическое допущение, которое, тем не менее, хорошо согласуется с реальным положением дел. (Чтобы убедиться в этом достаточно нарисовать кривую, измерить ее длину, затем &amp;quot;перепутать&amp;quot; в ней пару или несколько пар точек и измерить длину новой кривой).&lt;br /&gt;
&lt;br /&gt;
Приведенная выше формулировка задачи представляет собой по сути хорошо известную задачи поиска Гамильтонова пути. Также хорошо известно, что эта задача уже при небольшом числе точек не может быть решена &amp;quot;в лоб&amp;quot; простым перебором вариантов поскольку их число взрыовобразно растет. Так, например, для пяти точке будет всего 60 (5!/2) возможных комбинаций, для десяти точек -- уже почти два миллиона, а для тридцати - количество комбинаций описывется числом, состоящим из 34-х цифр.&lt;br /&gt;
&lt;br /&gt;
Поэтому алгоритмы построения Гамильтонова пути, используемые на практике, все представляют собой субоптимальные алгоритмы, которые позволяют найти хорошее решение за приемлемое время, но не гарантируют того, что оно будет лучшим из всех возможных. В данном плагине в качестве основного алгорима использовались  [https://ru.wikipedia.org/wiki/%D0%A1%D0%B0%D0%BC%D0%BE%D0%BE%D1%80%D0%B3%D0%B0%D0%BD%D0%B8%D0%B7%D1%83%D1%8E%D1%89%D0%B0%D1%8F%D1%81%D1%8F_%D0%BA%D0%B0%D1%80%D1%82%D0%B0_%D0%9A%D0%BE%D1%85%D0%BE%D0%BD%D0%B5%D0%BD%D0%B0 самоорганизующиеся карты Кохонена]. Использованию карт Кохонена для решения данной задачи посвещается достаточно обширная литература&lt;br /&gt;
&lt;br /&gt;
=== Работа с расширением ===&lt;br /&gt;
&lt;br /&gt;
После установки расширения появится новая панель инструментов с двумя кнопками: &amp;quot;копировать точки&amp;quot; и &amp;quot;вставить линию&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
[[Файл:Reconstructline-01.png|center]]&lt;br /&gt;
&lt;br /&gt;
Предположим, что исходный набор точек выглядит следующим образом (обратите внимание на нумерацию, она отражает последовательность точек в таблице):&lt;br /&gt;
&lt;br /&gt;
[[Файл:Reconstructline-02.png|center|thumb|600px|Исходные точки]]&lt;br /&gt;
&lt;br /&gt;
Что будет, если просто соединить их в линию (например с помощью расширения Points2One):&lt;br /&gt;
&lt;br /&gt;
[[Файл:Reconstructline-03.png|center|thumb|600px|Последовательное объединение точек в линию]]&lt;br /&gt;
&lt;br /&gt;
Для объединения с помощью ReconstructLine:&lt;br /&gt;
&lt;br /&gt;
1. Инструментом выделения выделите нужные точки, нажмите на кнопку &amp;quot;копировать точки&amp;quot; в панели инструментов ReconstructLine&lt;br /&gt;
&lt;br /&gt;
2. Вставьте линию в существующий или новый линейный слой, нажмите на кнопку &amp;quot;вставить линию&amp;quot; в панели инструментов ReconstructLine&lt;br /&gt;
&lt;br /&gt;
Результат должен выглядеть более логично:&lt;br /&gt;
&lt;br /&gt;
[[Файл:Reconstructline-04.png|center|thumb|600px|Объединение точек в линию с помощью ReconstructLine]]&lt;br /&gt;
&lt;br /&gt;
=== Контакты ===&lt;br /&gt;
&lt;br /&gt;
Если вы нашли ошибку или у вас есть предложения по улучшению расширения — воспользуйтесь [https://github.com/nextgis/shortcut_manager/issues багтрекером]. Кроме того, вопросы по использованию расширения можно задать авторам [http://nextgis.ru/contact/ напрямую].&lt;br /&gt;
&lt;br /&gt;
=== Ссылки по теме ===&lt;br /&gt;
&lt;br /&gt;
* [http://gis-lab.info/qa/qgis-install-plugin.html Установка модулей расширения в QGIS]&lt;br /&gt;
* [http://gis-lab.info/docs/qgis/ Документация по QGIS]&lt;/div&gt;</summary>
		<author><name>KolesovDmitry</name></author>
	</entry>
	<entry>
		<id>https://wiki.gis-lab.info/index.php?title=ReconstructLine_-_%D0%B2%D0%BE%D1%81%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BB%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BB%D0%B8%D0%BD%D0%B8%D0%B9_%D0%BF%D0%BE_%D1%82%D0%BE%D1%87%D0%BA%D0%B0%D0%BC_%D0%B2_QGIS&amp;diff=21916</id>
		<title>ReconstructLine - восстановление линий по точкам в QGIS</title>
		<link rel="alternate" type="text/html" href="https://wiki.gis-lab.info/index.php?title=ReconstructLine_-_%D0%B2%D0%BE%D1%81%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BB%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BB%D0%B8%D0%BD%D0%B8%D0%B9_%D0%BF%D0%BE_%D1%82%D0%BE%D1%87%D0%BA%D0%B0%D0%BC_%D0%B2_QGIS&amp;diff=21916"/>
		<updated>2015-04-28T05:08:15Z</updated>

		<summary type="html">&lt;p&gt;KolesovDmitry: /* Алгоритм */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Статья|Черновик|reconstructline}}&lt;br /&gt;
{{Аннотация|Описание инструмента для создания линейных объектов в QGIS.}}&lt;br /&gt;
&lt;br /&gt;
[http://plugins.qgis.org/plugins/reconstruct_line/ ReconstructLine] - это инструмент для интерактивного создания линейных объектов по точечным.&lt;br /&gt;
&lt;br /&gt;
Вы наверняка сталкивались с инструментом объединяющим точки в линии. Все такие инструменты работают либо последовательно, т.е. точки объединяются в линии так, как они идут в таблице, либо про атрибутам. Теперь представьте, что вам не важен порядок записей в таблице и атрибутивная информация отсутствует или бесполезна, что вам все равно нужно объединить точки в линию. &lt;br /&gt;
&lt;br /&gt;
Расширение ReconstructLine умеет восстанавливать линии по точкам используя '''только''' их пространственное расположение, &amp;quot;восстанавливая&amp;quot; линию. Поскольку восстановление это сложный алгоритм, ReconstructLine работает только интерактивно. Процесс восстановления может занять значительное время, если точек много.&lt;br /&gt;
&lt;br /&gt;
ReconstructLine плохо подходит для облаков точек.&lt;br /&gt;
&lt;br /&gt;
{{NextGIS}}&lt;br /&gt;
&lt;br /&gt;
=== Замечания по установке ===&lt;br /&gt;
&lt;br /&gt;
Расширение доступно из [http://plugins.qgis.org/plugins/reconstruct_line/ официального репозитория].&lt;br /&gt;
&lt;br /&gt;
ReconstructLine находится в разработке и протестирован с QGIS 2.6 и выше. Расширение работает в Windows и Linux (Ubuntu).&lt;br /&gt;
&lt;br /&gt;
Исходный код модуля доступен в ([https://github.com/nextgis/ReconstructLine репозитории] на Github).&lt;br /&gt;
&lt;br /&gt;
=== Алгоритм ===&lt;br /&gt;
При разработке модуля принималось во внимание то, что точки можно соединить между собой &amp;quot;логичным&amp;quot; образом, если они образуют &amp;quot;видимую глазами&amp;quot; кривую линию. В этом случае задачу можно сформулировать следующим образом:&lt;br /&gt;
&lt;br /&gt;
* Дан набор точек T1, T2, ... Tn.&lt;br /&gt;
* Дана метрика d(Ti, Tj) -- функция, которая измеряет расстояния между произвольной парой точек. Тогда потенциальной восстановленной кривой (т.е. последовательности точек (Ti1, Ti2, ..., Tin)) можно поставить в соответствие её длину, равную сумме растояний между парами точек, составляющих восстановленную кривую: L = d(Ti1, Ti2) + d(Ti2, Ti3) + .... + d(Tin-1, Tin).&lt;br /&gt;
* Требуется найти среди всех комбинаций (Ti1, Ti2, ..., Tin) такую комбинацию, для которой ее длина L будет минимальной.&lt;br /&gt;
&lt;br /&gt;
Требование того, что восстановленная кривая должна иметь минимальную длину из всех возможных комбинаций -- чисто эвристическое допущение, которое, тем не менее, хорошо согласуется с реальным положением дел. (Чтобы убедиться в этом достаточно нарисовать кривую, измерить ее длину, затем &amp;quot;перепутать&amp;quot; в ней пару или несколько пар точек и измерить длину новой кривой).&lt;br /&gt;
&lt;br /&gt;
Приведенная выше формулировка задачи представляет собой по сути хорошо известную задачи поиска Гамильтонова пути. Также хорошо известно, что эта задача уже при небольшом числе точек не может быть решена &amp;quot;в лоб&amp;quot; простым перебором вариантов поскольку их число взрыовобразно растет. Так, например, для пяти точке будет всего 60 (5!/2) возможных комбинаций, для десяти уже почти два миллиона, а для двадцати точек количество комбинаций описывется числом с 19-ю нулями.&lt;br /&gt;
&lt;br /&gt;
=== Работа с расширением ===&lt;br /&gt;
&lt;br /&gt;
После установки расширения появится новая панель инструментов с двумя кнопками: &amp;quot;копировать точки&amp;quot; и &amp;quot;вставить линию&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
[[Файл:Reconstructline-01.png|center]]&lt;br /&gt;
&lt;br /&gt;
Предположим, что исходный набор точек выглядит следующим образом (обратите внимание на нумерацию, она отражает последовательность точек в таблице):&lt;br /&gt;
&lt;br /&gt;
[[Файл:Reconstructline-02.png|center|thumb|600px|Исходные точки]]&lt;br /&gt;
&lt;br /&gt;
Что будет, если просто соединить их в линию (например с помощью расширения Points2One):&lt;br /&gt;
&lt;br /&gt;
[[Файл:Reconstructline-03.png|center|thumb|600px|Последовательное объединение точек в линию]]&lt;br /&gt;
&lt;br /&gt;
Для объединения с помощью ReconstructLine:&lt;br /&gt;
&lt;br /&gt;
1. Инструментом выделения выделите нужные точки, нажмите на кнопку &amp;quot;копировать точки&amp;quot; в панели инструментов ReconstructLine&lt;br /&gt;
&lt;br /&gt;
2. Вставьте линию в существующий или новый линейный слой, нажмите на кнопку &amp;quot;вставить линию&amp;quot; в панели инструментов ReconstructLine&lt;br /&gt;
&lt;br /&gt;
Результат должен выглядеть более логично:&lt;br /&gt;
&lt;br /&gt;
[[Файл:Reconstructline-04.png|center|thumb|600px|Объединение точек в линию с помощью ReconstructLine]]&lt;br /&gt;
&lt;br /&gt;
=== Контакты ===&lt;br /&gt;
&lt;br /&gt;
Если вы нашли ошибку или у вас есть предложения по улучшению расширения — воспользуйтесь [https://github.com/nextgis/shortcut_manager/issues багтрекером]. Кроме того, вопросы по использованию расширения можно задать авторам [http://nextgis.ru/contact/ напрямую].&lt;br /&gt;
&lt;br /&gt;
=== Ссылки по теме ===&lt;br /&gt;
&lt;br /&gt;
* [http://gis-lab.info/qa/qgis-install-plugin.html Установка модулей расширения в QGIS]&lt;br /&gt;
* [http://gis-lab.info/docs/qgis/ Документация по QGIS]&lt;/div&gt;</summary>
		<author><name>KolesovDmitry</name></author>
	</entry>
	<entry>
		<id>https://wiki.gis-lab.info/index.php?title=ReconstructLine_-_%D0%B2%D0%BE%D1%81%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BB%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BB%D0%B8%D0%BD%D0%B8%D0%B9_%D0%BF%D0%BE_%D1%82%D0%BE%D1%87%D0%BA%D0%B0%D0%BC_%D0%B2_QGIS&amp;diff=21915</id>
		<title>ReconstructLine - восстановление линий по точкам в QGIS</title>
		<link rel="alternate" type="text/html" href="https://wiki.gis-lab.info/index.php?title=ReconstructLine_-_%D0%B2%D0%BE%D1%81%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BB%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BB%D0%B8%D0%BD%D0%B8%D0%B9_%D0%BF%D0%BE_%D1%82%D0%BE%D1%87%D0%BA%D0%B0%D0%BC_%D0%B2_QGIS&amp;diff=21915"/>
		<updated>2015-04-28T04:58:56Z</updated>

		<summary type="html">&lt;p&gt;KolesovDmitry: /* Алгоритм */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Статья|Черновик|reconstructline}}&lt;br /&gt;
{{Аннотация|Описание инструмента для создания линейных объектов в QGIS.}}&lt;br /&gt;
&lt;br /&gt;
[http://plugins.qgis.org/plugins/reconstruct_line/ ReconstructLine] - это инструмент для интерактивного создания линейных объектов по точечным.&lt;br /&gt;
&lt;br /&gt;
Вы наверняка сталкивались с инструментом объединяющим точки в линии. Все такие инструменты работают либо последовательно, т.е. точки объединяются в линии так, как они идут в таблице, либо про атрибутам. Теперь представьте, что вам не важен порядок записей в таблице и атрибутивная информация отсутствует или бесполезна, что вам все равно нужно объединить точки в линию. &lt;br /&gt;
&lt;br /&gt;
Расширение ReconstructLine умеет восстанавливать линии по точкам используя '''только''' их пространственное расположение, &amp;quot;восстанавливая&amp;quot; линию. Поскольку восстановление это сложный алгоритм, ReconstructLine работает только интерактивно. Процесс восстановления может занять значительное время, если точек много.&lt;br /&gt;
&lt;br /&gt;
ReconstructLine плохо подходит для облаков точек.&lt;br /&gt;
&lt;br /&gt;
{{NextGIS}}&lt;br /&gt;
&lt;br /&gt;
=== Замечания по установке ===&lt;br /&gt;
&lt;br /&gt;
Расширение доступно из [http://plugins.qgis.org/plugins/reconstruct_line/ официального репозитория].&lt;br /&gt;
&lt;br /&gt;
ReconstructLine находится в разработке и протестирован с QGIS 2.6 и выше. Расширение работает в Windows и Linux (Ubuntu).&lt;br /&gt;
&lt;br /&gt;
Исходный код модуля доступен в ([https://github.com/nextgis/ReconstructLine репозитории] на Github).&lt;br /&gt;
&lt;br /&gt;
=== Алгоритм ===&lt;br /&gt;
При разработке модуля принималось во внимание то, что точки можно соединить между собой &amp;quot;логичным&amp;quot; образом, если они образуют &amp;quot;видимую глазами&amp;quot; кривую линию. В этом случае задачу можно сформулировать следующим образом:&lt;br /&gt;
&lt;br /&gt;
 * Дан набор точек T1, T2, ... Tn.&lt;br /&gt;
 * Дана метрика d(Ti, Tj) -- функция, которая измеряет расстояния между произвольной парой точек. Тогда потенциальной восстановленной кривой (т.е. последовательности точек (Ti1, Ti2, ..., Tin)) можно поставить в соответствие её длину, равную сумме растояний между парами точек, составляющих восстановленную кривую: L = d(Ti1, Ti2) + d(Ti2, Ti3) + .... + d(Tin-1, Tin).&lt;br /&gt;
 * Требуется найти среди всех комбинаций (Ti1, Ti2, ..., Tin) такую комбинацию, для которой ее длина L будет минимальной.&lt;br /&gt;
&lt;br /&gt;
Требование того, что восстановленная кривая должна иметь минимальную длину из всех возможных комбинаций -- чисто эвристическое допущение, которое, тем не менее, хорошо согласуется с реальным положением дел. (Чтобы убедиться в этом достаточно нарисовать кривую, измерить ее длину, затем &amp;quot;перепутать&amp;quot; в ней пару или несколько пар точек и измерить длину новой кривой).&lt;br /&gt;
&lt;br /&gt;
=== Работа с расширением ===&lt;br /&gt;
&lt;br /&gt;
После установки расширения появится новая панель инструментов с двумя кнопками: &amp;quot;копировать точки&amp;quot; и &amp;quot;вставить линию&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
[[Файл:Reconstructline-01.png|center]]&lt;br /&gt;
&lt;br /&gt;
Предположим, что исходный набор точек выглядит следующим образом (обратите внимание на нумерацию, она отражает последовательность точек в таблице):&lt;br /&gt;
&lt;br /&gt;
[[Файл:Reconstructline-02.png|center|thumb|600px|Исходные точки]]&lt;br /&gt;
&lt;br /&gt;
Что будет, если просто соединить их в линию (например с помощью расширения Points2One):&lt;br /&gt;
&lt;br /&gt;
[[Файл:Reconstructline-03.png|center|thumb|600px|Последовательное объединение точек в линию]]&lt;br /&gt;
&lt;br /&gt;
Для объединения с помощью ReconstructLine:&lt;br /&gt;
&lt;br /&gt;
1. Инструментом выделения выделите нужные точки, нажмите на кнопку &amp;quot;копировать точки&amp;quot; в панели инструментов ReconstructLine&lt;br /&gt;
&lt;br /&gt;
2. Вставьте линию в существующий или новый линейный слой, нажмите на кнопку &amp;quot;вставить линию&amp;quot; в панели инструментов ReconstructLine&lt;br /&gt;
&lt;br /&gt;
Результат должен выглядеть более логично:&lt;br /&gt;
&lt;br /&gt;
[[Файл:Reconstructline-04.png|center|thumb|600px|Объединение точек в линию с помощью ReconstructLine]]&lt;br /&gt;
&lt;br /&gt;
=== Контакты ===&lt;br /&gt;
&lt;br /&gt;
Если вы нашли ошибку или у вас есть предложения по улучшению расширения — воспользуйтесь [https://github.com/nextgis/shortcut_manager/issues багтрекером]. Кроме того, вопросы по использованию расширения можно задать авторам [http://nextgis.ru/contact/ напрямую].&lt;br /&gt;
&lt;br /&gt;
=== Ссылки по теме ===&lt;br /&gt;
&lt;br /&gt;
* [http://gis-lab.info/qa/qgis-install-plugin.html Установка модулей расширения в QGIS]&lt;br /&gt;
* [http://gis-lab.info/docs/qgis/ Документация по QGIS]&lt;/div&gt;</summary>
		<author><name>KolesovDmitry</name></author>
	</entry>
	<entry>
		<id>https://wiki.gis-lab.info/index.php?title=MOLUSCE_-_%D0%B0%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7_%D0%B8%D0%B7%D0%BC%D0%B5%D0%BD%D0%B5%D0%BD%D0%B8%D0%B9_%D0%BB%D0%B0%D0%BD%D0%B4%D1%88%D0%B0%D1%84%D1%82%D0%BD%D0%BE%D0%B3%D0%BE_%D0%BF%D0%BE%D0%BA%D1%80%D0%BE%D0%B2%D0%B0&amp;diff=21081</id>
		<title>MOLUSCE - анализ изменений ландшафтного покрова</title>
		<link rel="alternate" type="text/html" href="https://wiki.gis-lab.info/index.php?title=MOLUSCE_-_%D0%B0%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7_%D0%B8%D0%B7%D0%BC%D0%B5%D0%BD%D0%B5%D0%BD%D0%B8%D0%B9_%D0%BB%D0%B0%D0%BD%D0%B4%D1%88%D0%B0%D1%84%D1%82%D0%BD%D0%BE%D0%B3%D0%BE_%D0%BF%D0%BE%D0%BA%D1%80%D0%BE%D0%B2%D0%B0&amp;diff=21081"/>
		<updated>2014-11-26T06:15:00Z</updated>

		<summary type="html">&lt;p&gt;KolesovDmitry: /* Замечания по установке */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Статья|Черновик|molusce-intro-ru}}&lt;br /&gt;
{{NextGIS}}&lt;br /&gt;
Разработано NextGIS по заказу и в сотрудничестве с [http://www.asiaairsurvey.com/ Asia Air Survey], Япония.&lt;br /&gt;
&lt;br /&gt;
= Модуль анализа изменения ландшафтного покрова (MOLUSCE) =&lt;br /&gt;
MOLUSCE, акроним от Modules for Land Use Change Simulations, представляет собой расширение (plug-in) для геоинформационной системы QGIS, предназначенное для анализа динамики состояния территорий.&lt;br /&gt;
&lt;br /&gt;
== Замечания по установке ==&lt;br /&gt;
&lt;br /&gt;
Расширение доступно из [http://plugins.qgis.org/plugins/plugins.xml официального репозитория].&lt;br /&gt;
&lt;br /&gt;
MOLUSCE разработан для QGIS версии 2.0.0 и старше. Для работы требует установленного пакета scipy. В случае, если пакет scipy отсутствует в системе, работа с модулем возможна, но построение моделей на базе логистической регрессии будет недоступно.&lt;br /&gt;
&lt;br /&gt;
Расширение доступно для установки из менеджера плагинов QGIS или со [http://plugins.qgis.org/plugins/molusce/ страницы расширения на plugins.qgis.org].&lt;br /&gt;
&lt;br /&gt;
Исходный код модуля можно получить через [https://github.com/nextgis/molusce репозиторий на GitHub] или выполнив команду&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;git clone git@github.com:nextgis/molusce.git&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Задача ==&lt;br /&gt;
Предположим, что имеется серия карт/дешифрированных снимков/... за различные периоды времени, на которых отображено текущее состояние территории. Исследователь, анализирующий динамику состояния территории, сталкивается со следующими вопросами:&lt;br /&gt;
* ''Какие'' изменения произошли и ''где'' они произошли?&lt;br /&gt;
* ''Какие'' факторы связаны с изменениями и ''как сильно'' они связаны?&lt;br /&gt;
* ''Какие'' изменения ожидаются в будущем и ''где'' именно?&lt;br /&gt;
Если ответ на первый вопрос можно получить путем визуальной оценки карт, но для ответа на последующие вопросы исследователь должен выдвигать те или иные гипотезы, проверять их адекватность, выводить следствия из гипотез и смотреть, насколько они согласуются с действительностью. &lt;br /&gt;
&lt;br /&gt;
MOLUSCE представляет собой собой расширение, предназначенное для частичной автоматизации данного процесса.&lt;br /&gt;
&lt;br /&gt;
== Упрощенная схема работы расширения ==&lt;br /&gt;
&lt;br /&gt;
На рисунке представлена упрощенная схема работы расширения.&lt;br /&gt;
&lt;br /&gt;
[[Файл:ModelWorkflows.png|700px|Упрощенная схема работы расширения]]&lt;br /&gt;
&lt;br /&gt;
В качестве входных данных расширению требутся:&lt;br /&gt;
* Карты начальных и конечных состояний территории. Это растровые изображения, в пикселях которых закодированы номера состояний территории (например, 1=лес, 2=поле, 3=городская застройка и т.п.). Расширению требуется как минимум две такие карты -- одна для исходного состояния (Начальная_дата), вторая для конечного состояния (Начальная_дата+N). Однако, для оценки качества построенной модели прогноза рекомендуется использование еще третьей карты (Начальная_дата + 2N), с которой будет сравниваться прогнозное значение. Здесь число N -- глубина прогноза, которая измеряется в зависимости от задачи в днях, неделях, месяцах, годах и т.д.&lt;br /&gt;
* Карты факторов, влияющих на изменение территории. Исследователь строит гипотезы о том, какие факторы могли повлиять на наблюдаемые изменения, и предоставляет расширению карты интенсивностей данных факторов. Например, если исследователь работает над проблемой изчезновения лесов, такими факторами могут быть: карта почв (каждый тип почвы закодирован своим числом), карта расстояний от дорог (пиксели карты содержат число -- кратчайшее расстояние от точки, связанной с данным пикселем, до дороги), карта плотности населения и т.п.&lt;br /&gt;
&lt;br /&gt;
Процесс анализа происходит в несколько этапов:&lt;br /&gt;
&lt;br /&gt;
# Поиск изменений.&lt;br /&gt;
# Построение модели для оценки вклада отдельных факторов на вероятность появления изменений.&lt;br /&gt;
# Построение карты значимости вклада фактора.&lt;br /&gt;
# Построение интегральной карты вклада всех факторов.&lt;br /&gt;
# Прогноз.&lt;br /&gt;
# Оценка качества модели/прогноза.&lt;br /&gt;
&lt;br /&gt;
Данная схема является обобщенной. Например, некоторые методы моделирования (нейронные сети, логистическая регрессия) объединяют пункты 2-4 в один этап, другие же методы (метод многокритериальной оценки, метод значимости признака), наоборот, требуют выделения их в отдельные этапы.&lt;br /&gt;
&lt;br /&gt;
Ниже приводится описание каждого из этапов.&lt;br /&gt;
&lt;br /&gt;
=== Поиск изменений ===&lt;br /&gt;
На данном этапе используются карты начальных и конечных состояний, на основе которых производится поиск мест, в которых произошли изменения и количественная оценка размера территорий, подвегнувшихся изменениям.&lt;br /&gt;
&lt;br /&gt;
Выходными значениями данного этапа будут:&lt;br /&gt;
* Карта изменений.&lt;br /&gt;
* Матрица переходов: матрица вероятностей того, что взятый наугдад пиксель будет подвергнут тому или иному изменению (отдельно по каждому типу изменений, например, лес-&amp;gt;поле, поле-&amp;gt;городская застройка, поле-&amp;gt;лес и т.п.).&lt;br /&gt;
&lt;br /&gt;
=== Построение модели для оценки вклада отдельных факторов на вероятность появления изменений ===&lt;br /&gt;
На данном этапе пользователь указывает какую модель он хочет использовать для оценки значимости факторов. Входными данными для этого шага являются карта изменений и список факторов, предположительно влияющих на вероятность возникновения изменений. Выходными значениями являются веса факторов определенные моделью.&lt;br /&gt;
&lt;br /&gt;
В расширении заложена возможность использования следующих моделей:&lt;br /&gt;
* Нейронные сети ([http://ru.wikipedia.org/wiki/%D0%9C%D0%B5%D1%82%D0%BE%D0%B4_%D0%BE%D0%B1%D1%80%D0%B0%D1%82%D0%BD%D0%BE%D0%B3%D0%BE_%D1%80%D0%B0%D1%81%D0%BF%D1%80%D0%BE%D1%81%D1%82%D1%80%D0%B0%D0%BD%D0%B5%D0%BD%D0%B8%D1%8F_%D0%BE%D1%88%D0%B8%D0%B1%D0%BA%D0%B8 многослойный перцептрон, обучающийся методом обратного распространения ошибки]).&lt;br /&gt;
* [http://ru.wikipedia.org/wiki/%D0%9B%D0%BE%D0%B3%D0%B8%D1%81%D1%82%D0%B8%D1%87%D0%B5%D1%81%D0%BA%D0%B0%D1%8F_%D1%80%D0%B5%D0%B3%D1%80%D0%B5%D1%81%D1%81%D0%B8%D1%8F Логистическая регрессия].&lt;br /&gt;
* Метод весомости признака ([http://www.ige.unicamp.br/wofe/documentation/wofeintr.htm Weights of Evidence]).&lt;br /&gt;
* Метод многокритериальной оценки, основанный на методе [http://ru.wikipedia.org/wiki/%D0%9C%D0%B5%D1%82%D0%BE%D0%B4_%D0%B0%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0_%D0%B8%D0%B5%D1%80%D0%B0%D1%80%D1%85%D0%B8%D0%B9 анализа иерархий Саати].&lt;br /&gt;
Все методы широко известны и активно используются в ГИС, поэтому ссылки даются в основном на энциклопедические источники.&lt;br /&gt;
&lt;br /&gt;
В результате настройки модели каждый фактор получает тот или иной вес в зависимости от его вклада вероятность появления изменений. Вес может быть как положительным (тесная связь между фактором и возможностью появления изменений), так и отрицательным (обратная связь -- если фактор присутствует, то изменения маловероятны).&lt;br /&gt;
&lt;br /&gt;
=== Построение карты влияния фактора ===&lt;br /&gt;
Входными данными для этого шага являются веса и карты интенсивности факторов. Выходным значением будет карта влияния факторов.  &lt;br /&gt;
&lt;br /&gt;
Суть данного этапа заключается в том, что исходная карта интенсивности фактора умножается на его вес, в итоге получается карта вклада фактора. Например, если на некотором участке интенсивность фактора близка к нулю, то и влияние фактора будет невелико независимо от его веса. И наоборот, если интенсивность фактора была высокая, то в его влияние будет значительным (положительным или отрицательным в зависимости от знака веса фактора).&lt;br /&gt;
&lt;br /&gt;
=== Построение интегральной карты вкладов ===&lt;br /&gt;
Взвешенные карты вкладов, построенные на предыдущем этапе, суммируются между собой, в итоге получается интегральная карта, учитывающая все факторы. Чем больше интегральная величина на каком-либо участке карты, тем более вероятно, что на этом участке произойдут изменения.&lt;br /&gt;
&lt;br /&gt;
=== Прогноз ===&lt;br /&gt;
Входными данными являются интегральная карта и вероятности переходов, а выходным параметром является карта-прогноз изменений.&lt;br /&gt;
&lt;br /&gt;
На данном этапе анализируется карта вкладов, полученная на предыдущем шаге: на карте ищутся места наиболее вероятных изменений и с учетом вероятности перехода одного класса в другой производится трансформация типа пикселя.&lt;br /&gt;
&lt;br /&gt;
=== Оценка качества модели/прогноза ===&lt;br /&gt;
Последний этап состоит в сравнении карты-прогноза с известной картой состояния территории. Пользователь может рассчитать различные каппа-статистики, расчитать карту ошибок а также визуализировать график, основанный на методе [http://www.econgeography.org/~rpontius/pontius_suedmeyer_2004_rsgisaa.pdf Error Budget].&lt;br /&gt;
&lt;br /&gt;
== Интерфейс пользователя ==&lt;br /&gt;
Интерфейс расширения представляет собой окно с несколькими вкладками. Пользователь последовательно заполняет необходимые поля и перемещается от вкладки к вкладке. При необходимости изменить что-либо пользователь может вернуться на предыдущие вкладки и ввести новые данные.&lt;br /&gt;
&lt;br /&gt;
=== Ввод начальных данных ===&lt;br /&gt;
[[Файл:molusce-Inputs.png|700px|center|Окно ввода начальных данных]]&lt;br /&gt;
При загрузке расширения открывается окно, в котором пользователь должен ввести информацию о том, какой растровый слой в каком качестве должен использоватся. Пользователь указывает карты начальных и конечных состояний, карты факторов.&lt;br /&gt;
&lt;br /&gt;
При работе расширения предполагается, что анализируемые растры сохранены в одной системе координат и их охваты совпадают. Для проверки этого условия пользователь может нажать кнопку проверки геометрических характеристик, в результате чего на экран будет выведено сообщение о том, совпадают ли границы растров и их система координат.&lt;br /&gt;
&lt;br /&gt;
=== Оценка корреляционной зависимости ===&lt;br /&gt;
[[Файл:molusce-Correlation.png|700px|center|Окно проверки корреляционных зависимостей входных данных]]&lt;br /&gt;
Некоторые методы (например, логистическая регрессия и метод значимости признака) очень чувствительны к взаимной зависимости входных данных. Для того, чтобы оценить зависимость входных переменных пользователю предоставляется возможность рассчитать силу связей между ними. Для непрерывных величин пользователь может рассчитать коэффициент корреляции, а для номинальных -- коэффициент Крамера или коэффициент JIU  (joint information uncertainty).&lt;br /&gt;
&lt;br /&gt;
=== Построение карты изменений ===&lt;br /&gt;
[[Файл:molusce-Changes.png|700px|center|Окно построения карты изменений]]&lt;br /&gt;
Для построения карты изменений отведена отдельная вкладка. При нажатии на кнопку создания карты изменений, она будет рассчитана и загружена в текущий проект. Каждый тип изменения на карте будет помечен определенным цветом.&lt;br /&gt;
&lt;br /&gt;
На данной вкладке пользователь также может расчитать статистику по количеству изменений -- определить какое количество пикселей того или иного класса было транформировано в пиксели других классов. Если исходные данные спроецированны в метрическую систему координат, то пользователь может отобразить статистику в квадратных метрах, гектарах или квадратных километрах.&lt;br /&gt;
&lt;br /&gt;
=== Настройка модели ===&lt;br /&gt;
[[Файл:molusce-ANN.png|700px|center|Окно моделирования (обучение нейронной сети)]]&lt;br /&gt;
&lt;br /&gt;
На данной влкладке пользователь может выбрать тип модели для настройки. Некоторые модели (нейронные сети, логистическая регрессия) для ускорения работы используют не все данные, а случайную выборку из них. В случае, если пользователь работает с данными моделями ему предоставляется возможность указать стратегию формирования выборки данных.&lt;br /&gt;
&lt;br /&gt;
=== Прогнозирование ===&lt;br /&gt;
[[Файл:molusce-Simulation.png|700px|center|Окно построения карты прогноза]]&lt;br /&gt;
&lt;br /&gt;
После обучения модели пользователь может применить для построения прогноза. Для этого полученная модель применяется к карте конечных состояний, в результате получается прогноз на один период вперед. При желании пользователь может указать количество периодов прогноза в строке ввода количества итераций, в этом случае будет произведено последовательное прогнозирование.&lt;br /&gt;
&lt;br /&gt;
Основным выходным значением является карта-результат прогноза, но помимо нее на этапе прогнозирования расширение формирует несколько вспомогательных карт, которые также могут быть сохранены на диске:&lt;br /&gt;
&lt;br /&gt;
* Карты потенциалов. Для каждого возможного типа трансформации (например лес-&amp;gt;застройка) строится карта потенциалов: чем больше потенциал для данного участка, тем более значимо воздействуют факторы на возможность появления данного типа транформации.&lt;br /&gt;
* Карта уверенности в прогнозе, которая измеряется в процентах: 100 = полная уверенность, другие альтернативы прогноза незначимы, 0 = полная неуверенность, есть по крайней мере еще одна альтернатива с такой же вероятностью реализации.&lt;br /&gt;
* Суммарная карта потенциальных переходов. Строится на основе карт потенциалов следующим образом: просматривается каждый пиксель и маркируется тем состоянием, переход в которое наиболее вероятен. Отличается от карты-прогноза тем, что для карты-прогноза производится трансформация не всех, а только определенного числа пикселей, определяемого статистики изменений (см. вкладку построения карты изменений).&lt;br /&gt;
&lt;br /&gt;
=== Валидация ===&lt;br /&gt;
[[Файл:molusce-Validation.png|700px|center|Оценка качества прогноза]]&lt;br /&gt;
&lt;br /&gt;
После получения прогноза пользователь получает возможность оценить его качество на основе различных оценок сходства между прогнозом и истинным состоянием территории.&lt;br /&gt;
&lt;br /&gt;
== Ссылки ==&lt;br /&gt;
* [http://plugins.qgis.org/plugins/molusce/ Страница расширения на plugins.qgis.org]&lt;br /&gt;
* [http://wiki.gis-lab.info/w/Molusce Описание расширения, содержащее информацию об устройстве расширения (англ.)]&lt;/div&gt;</summary>
		<author><name>KolesovDmitry</name></author>
	</entry>
	<entry>
		<id>https://wiki.gis-lab.info/index.php?title=%D0%A1%D0%BE%D0%B7%D0%B4%D0%B0%D0%BD%D0%B8%D0%B5_WMS_%D1%81%D0%B5%D1%80%D0%B2%D0%B5%D1%80%D0%B0_%D0%BD%D0%B0_%D0%B1%D0%B0%D0%B7%D0%B5_GRASS_GIS_%D0%B8_Pyramid&amp;diff=19450</id>
		<title>Создание WMS сервера на базе GRASS GIS и Pyramid</title>
		<link rel="alternate" type="text/html" href="https://wiki.gis-lab.info/index.php?title=%D0%A1%D0%BE%D0%B7%D0%B4%D0%B0%D0%BD%D0%B8%D0%B5_WMS_%D1%81%D0%B5%D1%80%D0%B2%D0%B5%D1%80%D0%B0_%D0%BD%D0%B0_%D0%B1%D0%B0%D0%B7%D0%B5_GRASS_GIS_%D0%B8_Pyramid&amp;diff=19450"/>
		<updated>2014-05-05T05:23:39Z</updated>

		<summary type="html">&lt;p&gt;KolesovDmitry: /* Ограничения данной реализации */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;В данной статье описывается простой пример создания [http://gis-lab.info/qa/ows.html WMS сервера] на базе геоинформационной системы GRASS. Доступ к данным организован при помощи [http://ru.wikipedia.org/wiki/Pyramid_%28%D0%BF%D1%80%D0%BE%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%BD%D1%8B%D0%B9_%D0%BA%D0%B0%D1%80%D0%BA%D0%B0%D1%81%29 фреймворка Pyramid].&lt;br /&gt;
&lt;br /&gt;
Данная статья является расширенным переводом статьи [http://www.webrian.ch/2013/12/grass-gis-web-map-service-with-pyramid.html GRASS GIS Web Map Service with Pyramid].&lt;br /&gt;
&lt;br /&gt;
== Общие сведения ==&lt;br /&gt;
Статья расчитана на читателя, который на базовом уровне знаком с геоинформационной системой GRASS и основами веб-разработки на языке программирования Python. В частности, читатель должен представлять, [http://gis-lab.info/qa/grass-external-scripting.html как происходит вызов команд GRASS на языке Python] и быть знакомым [http://docs.pylonsproject.org/projects/pyramid/en/latest/narr/introduction.html с принципами использования фреймворка Pyramid].&lt;br /&gt;
&lt;br /&gt;
В статье используется GRASS версии 6.4. Приведенный код применим и к более новым версиям GRASS, но, возможно, потребуется его незначительная правка.&lt;br /&gt;
&lt;br /&gt;
Исходный код модуля описанный в статье доступен по ссылке: [[Файл: Grass_wms.zip‎]].&lt;br /&gt;
&lt;br /&gt;
=== Архитектура системы ===&lt;br /&gt;
В разрабатываемой системе вся обработка геоданных будет возложена на GRASS, а обработка веб-запросов --- на Pyramid. &lt;br /&gt;
Основная часть WMS сервера, отвечающая за отрисовку геоданных --- модуль [http://grass.osgeo.org/grass64/manuals/d.mon.html d.mon], который будет использоваться совместно с [http://grass.osgeo.org/grass64/manuals/cairodriver.html графическим драйвером Cairo], позволяющим генерировать изображения в форматах PNG, BMP, PPM, PS, PDF и SVG.&lt;br /&gt;
&lt;br /&gt;
Для реализации сервера потребуется создать функции, служащие для:&lt;br /&gt;
&lt;br /&gt;
# Настройки путей к GRASS.&lt;br /&gt;
# Получения и анализа параметров запроса WMS.&lt;br /&gt;
# Отрисовки слоев по запросу клиента и сохранения результата в графический файл.&lt;br /&gt;
# Возвращения результата обработки запроса клиенту.&lt;br /&gt;
&lt;br /&gt;
Собственно к GRASS относятся первый и третий пункты, остальные --- обычные действия по обработке веб-запросов, которые реализуются при помощи Pyramid. Поэтому для простоты изложения и реализации объединим первый и третий пункты в виде одной функции, а второй и четвертый --- в виде другой.&lt;br /&gt;
&lt;br /&gt;
=== Зависимости и их установка ===&lt;br /&gt;
Для того, чтобы WMS сервер мог функционировать, требуется, чтобы на компьютере была установлена геоинформационная система [http://grass.osgeo.org/download/ GRASS] и [http://docs.pylonsproject.org/projects/pyramid/en/latest/narr/install.html Pyramid] (Pyramid рекомендуется устанавливать в [http://docs.pylonsproject.org/projects/pyramid/en/latest/narr/install.html#installing-the-virtualenv-package виртуальное окружение], чтобы не &amp;quot;мусорить&amp;quot; в основной системе).&lt;br /&gt;
&lt;br /&gt;
Установка этих систем обеспечит установку и настройку требуемых зависимостей.&lt;br /&gt;
&lt;br /&gt;
== Реализация ==&lt;br /&gt;
=== Настройка путей GRASS и обработка запроса клиента ===&lt;br /&gt;
Ниже приводится код функции, которая инициализирует GRASS, отрисовывает запрошенные пользователем слои и сохраняет полученное изображение во временном файле.&lt;br /&gt;
&lt;br /&gt;
На вход функция принимает &lt;br /&gt;
* список слоев (layers), которые требуется отрисовать;&lt;br /&gt;
* охват интересующего пользователя региона (bbox);&lt;br /&gt;
* ширину/высоту (width/height) изображения. &lt;br /&gt;
&lt;br /&gt;
На выходе функция возвращает имя файла, в котором будет сохранено запрошенное изображение.&lt;br /&gt;
&lt;br /&gt;
 def _grass_wms(layers=[], bbox=[], width=256, height=256):&lt;br /&gt;
    # Прописываем пути к GRASS. Исправить под свои нужды.&lt;br /&gt;
    gisdbase = &amp;quot;/home/useranme/GRASSDATA&amp;quot;&lt;br /&gt;
    location = &amp;quot;MSK_28407&amp;quot;&lt;br /&gt;
    mapset = &amp;quot;PERMANENT&amp;quot;&lt;br /&gt;
    gisbase = os.environ[&amp;quot;GISBASE&amp;quot;] = &amp;quot;/usr/lib/grass64&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
    # Добавляем путь модулям GRASS в системные пути&lt;br /&gt;
    sys.path.append(&amp;quot;%s/etc/python&amp;quot; % gisbase)&lt;br /&gt;
 &lt;br /&gt;
    # Импортируем библиотеки GRASS&lt;br /&gt;
    from grass.script import core as grass&lt;br /&gt;
    from grass.script import setup as gsetup&lt;br /&gt;
 &lt;br /&gt;
    # Инициализируем GRASS&lt;br /&gt;
    gsetup.init(gisbase, gisdbase,&lt;br /&gt;
               location, mapset)&lt;br /&gt;
 &lt;br /&gt;
    # Получаем список известных растровых и векторных слоев&lt;br /&gt;
    vector_layers = grass.list_strings(type = &amp;quot;vect&amp;quot;)&lt;br /&gt;
    raster_layers = grass.list_strings(type = &amp;quot;rast&amp;quot;)&lt;br /&gt;
 &lt;br /&gt;
    grass.run_command(&amp;quot;g.region&amp;quot;, w=bbox[0], s=bbox[1], e=bbox[2], n=bbox[3])&lt;br /&gt;
 &lt;br /&gt;
    # Создание временного файла&lt;br /&gt;
    tempfile = grass.tempfile()&lt;br /&gt;
    filename = &amp;quot;%s.png&amp;quot; % tempfile&lt;br /&gt;
 &lt;br /&gt;
    # Настраиваем параметры вывода&lt;br /&gt;
    os.environ[&amp;quot;GRASS_CAIROFILE&amp;quot;] = filename&lt;br /&gt;
    os.environ[&amp;quot;GRASS_WIDTH&amp;quot;] = width&lt;br /&gt;
    os.environ[&amp;quot;GRASS_HEIGHT&amp;quot;] = height&lt;br /&gt;
 &lt;br /&gt;
    # Отрисовка&lt;br /&gt;
    grass.run_command(&amp;quot;d.mon&amp;quot;, start=&amp;quot;cairo&amp;quot;)&lt;br /&gt;
 &lt;br /&gt;
    for layer in layers:&lt;br /&gt;
       if layer in raster_layers:&lt;br /&gt;
           grass.run_command(&amp;quot;d.rast&amp;quot;, map=layer, quiet=1)&lt;br /&gt;
       elif layer in vector_layers:&lt;br /&gt;
           grass.run_command(&amp;quot;d.vect&amp;quot;, map=layer, quiet=1, fcolor=&amp;quot;0:0:255&amp;quot;, color=None)&lt;br /&gt;
 &lt;br /&gt;
    grass.run_command(&amp;quot;d.mon&amp;quot;, stop=&amp;quot;cairo&amp;quot;)&lt;br /&gt;
 &lt;br /&gt;
    return filename&lt;br /&gt;
&lt;br /&gt;
Как видим, большая часть кода связана с первоначальной настройкой GRASS. Основной код по отрисовке запрошенных слоев использует команды GRASS и занимает всего пять строк:&lt;br /&gt;
  for layer in layers:&lt;br /&gt;
  ...&lt;br /&gt;
При этом все векторные слои будут отрисованы синим цветом, (см. параметры, передаваемые в &amp;lt;code&amp;gt;grass.run_command(&amp;quot;d.vect&amp;quot;, map=layer, quiet=1, fcolor=&amp;quot;0:0:255&amp;quot;, color=None)&amp;lt;/code&amp;gt;). Внешний вид слоя может быть изменен настройкой параметров команды [http://grass.osgeo.org/grass64/manuals/d.vect.html d.vect]. Например, данной командой можно назначить стиль отображения объекта в зависимости от его атрибутов или геометрических характеристик. &lt;br /&gt;
&lt;br /&gt;
Аналогично, растровые слои отображаются в цветовой схеме по умолчанию (или заранее назначенной пользователем вручную). При необходимости изменить стиль слоя при отрисовке следует воспользоваться командами, обрабатывающими цветовые схемы растровых карт, например [http://grass.osgeo.org/grass64/manuals/r.colors.html r.colors] или аналогичными модулями.&lt;br /&gt;
&lt;br /&gt;
Временный файл, в который сохраняется отрисованное изображение, в GRASS 6.4 задается следующими строками:&lt;br /&gt;
 # Настраиваем параметры вывода&lt;br /&gt;
 os.environ[&amp;quot;GRASS_CAIROFILE&amp;quot;] = filename&lt;br /&gt;
 os.environ[&amp;quot;GRASS_WIDTH&amp;quot;] = width&lt;br /&gt;
 os.environ[&amp;quot;GRASS_HEIGHT&amp;quot;] = height&lt;br /&gt;
Для GRASS седьмой версии можно немного упростить этот код, передавая параметры напрямую модулю &amp;lt;code&amp;gt;d.mon&amp;lt;/code&amp;gt;. Пример можно посмотреть в [http://www.webrian.ch/2013/12/grass-gis-web-map-service-with-pyramid.html исходной статье].&lt;br /&gt;
&lt;br /&gt;
=== Анализ запроса пользователя и возвращение результата ===&lt;br /&gt;
Анализ запроса пользователя производится в следующей функции:&lt;br /&gt;
 @view_config(route_name=&amp;quot;wms&amp;quot;)&lt;br /&gt;
 def wms_view(request):&lt;br /&gt;
 &lt;br /&gt;
    layers = request.params.get(&amp;quot;LAYERS&amp;quot;, &amp;quot;&amp;quot;).split(&amp;quot;,&amp;quot;)&lt;br /&gt;
    bbox = request.params.get(&amp;quot;BBOX&amp;quot;, &amp;quot;&amp;quot;).split(&amp;quot;,&amp;quot;)&lt;br /&gt;
    width = request.params.get(&amp;quot;WIDTH&amp;quot;)&lt;br /&gt;
    height = request.params.get(&amp;quot;HEIGHT&amp;quot;)&lt;br /&gt;
 &lt;br /&gt;
    try:&lt;br /&gt;
        filename = _grass_wms(layers=layers,&lt;br /&gt;
                              bbox=bbox,&lt;br /&gt;
                              width=width,&lt;br /&gt;
                              height=height)&lt;br /&gt;
        f = open(filename, &amp;quot;r+&amp;quot;)&lt;br /&gt;
        return Response(body=f.read(), content_type=&amp;quot;image/png&amp;quot;)&lt;br /&gt;
    except:&lt;br /&gt;
        pass&lt;br /&gt;
&lt;br /&gt;
Данная функция принимает запрос (request), в котором могут определяться:&lt;br /&gt;
* список слоев в запрашиваемом изображении (параметр LAYERS);&lt;br /&gt;
* охват области запрашиваемого изображения (параметр BBOX);&lt;br /&gt;
* высота и ширина запрашиваемого изображения (параметры HEIGHT и WIDTH).&lt;br /&gt;
&lt;br /&gt;
Полученные параметры анализируются и передаются в определенную выше функцию _grass_wms. Результат работы функции --- имя файла изображения --- считывается с диска и возвращается в качестве ответа на запрос.&lt;br /&gt;
&lt;br /&gt;
=== Создание веб-приложения ===&lt;br /&gt;
Еще одно действие --- создание простейшего веб-приложения, которое использует построенный WMS сервер. Воспользуемся библиотекой [http://gis-lab.info/qa/openlayers-begin.html OpenLayers] для отображения карты, возвращаемой сервером.&lt;br /&gt;
&lt;br /&gt;
Данный шаг является необязательным, но его удобно реализовать в целях отладки.&lt;br /&gt;
&lt;br /&gt;
Следующая функция создает веб-страницу с картой на базе слоев векторных слоев mo и io_15 из набора PERMANENT:&lt;br /&gt;
 @view_config(route_name=&amp;quot;index&amp;quot;)&lt;br /&gt;
 def index_view(request):&lt;br /&gt;
    body = &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
 &amp;lt;html xml:lang=&amp;quot;en&amp;quot;&lt;br /&gt;
 xmlns:tal=&amp;quot;http://xml.zope.org/namespaces/tal&amp;quot;&lt;br /&gt;
 xmlns=&amp;quot;http://www.w3.org/1999/xhtml&amp;quot;&amp;gt;&lt;br /&gt;
 &amp;lt;head&amp;gt;&lt;br /&gt;
  &amp;lt;title&amp;gt;GRASS GIS Web Map Service&amp;lt;/title&amp;gt;&lt;br /&gt;
  &amp;lt;script src=&amp;quot;http://openlayers.org/api/OpenLayers.js&amp;quot; type=&amp;quot;text/javascript&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;&lt;br /&gt;
  &amp;lt;script type=&amp;quot;text/javascript&amp;quot;&amp;gt;&lt;br /&gt;
    var map, wms_layer;&lt;br /&gt;
    function init(){&lt;br /&gt;
        var map = new OpenLayers.Map(&amp;quot;map-div&amp;quot;,{&lt;br /&gt;
            projection: &amp;quot;EPSG:28407&amp;quot;,&lt;br /&gt;
            maxExtent: new OpenLayers.Bounds(7361000, 6115000, 7435000, 6212000),&lt;br /&gt;
            numZoomLevels: 6,&lt;br /&gt;
        });&lt;br /&gt;
        var wms_layer = new OpenLayers.Layer.WMS(&amp;quot;GRASS WMS&amp;quot;, '/wms', {&lt;br /&gt;
            layers: &amp;quot;mo@PERMANENT,io_15@PERMANENT&amp;quot;&lt;br /&gt;
        },{&lt;br /&gt;
            singleTile: true,&lt;br /&gt;
        });&lt;br /&gt;
        map.addLayer(wms_layer);&lt;br /&gt;
        map.zoomToMaxExtent();&lt;br /&gt;
    }&lt;br /&gt;
  &amp;lt;/script&amp;gt;&lt;br /&gt;
 &amp;lt;/head&amp;gt;&lt;br /&gt;
 &amp;lt;body onload=&amp;quot;init()&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt; div id=&amp;quot;map-div&amp;quot; style=&amp;quot;height: 600px; width: 800px;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
 &amp;lt;/body&amp;gt;&lt;br /&gt;
 &amp;lt;/html&amp;gt;&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    return Response(body=body, content_type=&amp;quot;text/html&amp;quot;, status=200)&lt;br /&gt;
Понятно, что список доступных слоев (&amp;lt;code&amp;gt;layers: &amp;quot;mo@PERMANENT,io_15@PERMANENT&amp;quot;&amp;lt;/code&amp;gt;) и параметры области (&amp;lt;code&amp;gt;{projection: &amp;quot;EPSG:28407&amp;quot;, maxExtent: new OpenLayers.Bounds(7361000, 6115000, 7435000, 6212000), numZoomLevels: 6}&amp;lt;/code&amp;gt;) следует отредактировать под конкретный проект.&lt;br /&gt;
&lt;br /&gt;
=== Конфигурирование Pyramid ===&lt;br /&gt;
Для того, чтобы описанные выше функции можно было использовать, необходимо сконфигурировать Pyramid. Пример такой функции приведен ниже:&lt;br /&gt;
 def main():&lt;br /&gt;
    config = Configurator()&lt;br /&gt;
    config.add_static_view('static', 'static', cache_max_age=3600)&lt;br /&gt;
    config.add_route(&amp;quot;index&amp;quot;, '/')&lt;br /&gt;
    config.add_route(&amp;quot;wms&amp;quot;, '/wms')&lt;br /&gt;
    config.scan()&lt;br /&gt;
    app = config.make_wsgi_app()&lt;br /&gt;
    server = make_server('0.0.0.0', 8080, app)&lt;br /&gt;
    server.serve_forever()&lt;br /&gt;
&lt;br /&gt;
Эта функция создает сервер, который будет функционировать по адресу 0.0.0.0:8080&lt;br /&gt;
&lt;br /&gt;
=== Использование ===&lt;br /&gt;
После того, как WMS сервер будет настроен, можно его запустить командой:&lt;br /&gt;
 python grass_wms.py&lt;br /&gt;
(Здесь предполагается, что программный код хранится в файле grass_wms.py).&lt;br /&gt;
&lt;br /&gt;
Для проверки того, все ли было настроено верно, можно открыть браузер и в адресную строку внести параметры WMS-запроса, например,&lt;br /&gt;
 http://0.0.0.0:8080/wms?BBOX=7361000,6115000,7435000,6212000&amp;amp;LAYERS=mo@PERMANENT&amp;amp;WIDTH=300&amp;amp;HEIGHT=700&lt;br /&gt;
В результате в окне браузера будет показана запрошенная карта, построенная на базе слоя mo@PERMANENT.&lt;br /&gt;
Также можно загрузить сразу веб-странцу по адресу&lt;br /&gt;
 http://0.0.0.0:8080/&lt;br /&gt;
на которой при помощи OpenLayers будет отображена веб-карта, поддерживающая возможности прокрутки и масштабирования.&lt;br /&gt;
&lt;br /&gt;
== Ограничения данной реализации ==&lt;br /&gt;
Рассмотренный пример демонстрирует принцип создания сервера WMS, потому в нем опущен ряд деталей, которые должны быть реализованы в реальной системе. Например, в рассмотренном варианте в целях упрощения изложения были введены следующие ограничения:&lt;br /&gt;
* Нет перепроецирования &amp;quot;на лету&amp;quot;. Т.е. построенный сервер WMS может возвращать слои только в той проекции, в которой хранятся данные GRASS.&lt;br /&gt;
* Реализация не является потокобезопасной. Например, при одновременном запросе данных из разных областей GRASS могут проявляться неожиданные побочные эффекты (в коде производятся манипуляции с &amp;lt;code&amp;gt;g.region&amp;lt;/code&amp;gt;).&lt;br /&gt;
* Не полная поддержка [http://www.opengeospatial.org/standards/wms стандарта WMS]. Например, описанная реализация не поддерживает запрос GetCapabilities, поэтому подключить ту или иную ГИС в качестве клиента к созданному серверу не удастся. Это ограничение легко обходится --- достаточно в функцию &amp;lt;code&amp;gt;wms_view&amp;lt;/code&amp;gt; вставить обработку параметра REQUEST (и, в случае REQUEST=GetCapabilities, вернуть список доступных слоев).&lt;br /&gt;
* В функции _grass_wms жестко прописаны пути к GRASS и базе геоданных. В реальной системе нужно использовать [http://docs.pylonsproject.org/projects/pyramid/en/latest/narr/environment.html .ini файл], в котором прописать необходимую информацию.&lt;br /&gt;
&lt;br /&gt;
== Ссылки по теме ==&lt;br /&gt;
* [http://www.webrian.ch/2013/12/grass-gis-web-map-service-with-pyramid.html GRASS GIS Web Map Service with Pyramid]&lt;br /&gt;
* [http://docs.pylonsproject.org/projects/pyramid/en/latest/narr/introduction.html Документация фреймворка Pyramid]&lt;br /&gt;
* [http://grass.osgeo.org/ GRASS GIS: The world's leading Free GIS software]&lt;/div&gt;</summary>
		<author><name>KolesovDmitry</name></author>
	</entry>
	<entry>
		<id>https://wiki.gis-lab.info/index.php?title=%D0%A1%D0%BE%D0%B7%D0%B4%D0%B0%D0%BD%D0%B8%D0%B5_WMS_%D1%81%D0%B5%D1%80%D0%B2%D0%B5%D1%80%D0%B0_%D0%BD%D0%B0_%D0%B1%D0%B0%D0%B7%D0%B5_GRASS_GIS_%D0%B8_Pyramid&amp;diff=19449</id>
		<title>Создание WMS сервера на базе GRASS GIS и Pyramid</title>
		<link rel="alternate" type="text/html" href="https://wiki.gis-lab.info/index.php?title=%D0%A1%D0%BE%D0%B7%D0%B4%D0%B0%D0%BD%D0%B8%D0%B5_WMS_%D1%81%D0%B5%D1%80%D0%B2%D0%B5%D1%80%D0%B0_%D0%BD%D0%B0_%D0%B1%D0%B0%D0%B7%D0%B5_GRASS_GIS_%D0%B8_Pyramid&amp;diff=19449"/>
		<updated>2014-05-05T05:05:31Z</updated>

		<summary type="html">&lt;p&gt;KolesovDmitry: /* Ограничения данной реализации */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;В данной статье описывается простой пример создания [http://gis-lab.info/qa/ows.html WMS сервера] на базе геоинформационной системы GRASS. Доступ к данным организован при помощи [http://ru.wikipedia.org/wiki/Pyramid_%28%D0%BF%D1%80%D0%BE%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%BD%D1%8B%D0%B9_%D0%BA%D0%B0%D1%80%D0%BA%D0%B0%D1%81%29 фреймворка Pyramid].&lt;br /&gt;
&lt;br /&gt;
Данная статья является расширенным переводом статьи [http://www.webrian.ch/2013/12/grass-gis-web-map-service-with-pyramid.html GRASS GIS Web Map Service with Pyramid].&lt;br /&gt;
&lt;br /&gt;
== Общие сведения ==&lt;br /&gt;
Статья расчитана на читателя, который на базовом уровне знаком с геоинформационной системой GRASS и основами веб-разработки на языке программирования Python. В частности, читатель должен представлять, [http://gis-lab.info/qa/grass-external-scripting.html как происходит вызов команд GRASS на языке Python] и быть знакомым [http://docs.pylonsproject.org/projects/pyramid/en/latest/narr/introduction.html с принципами использования фреймворка Pyramid].&lt;br /&gt;
&lt;br /&gt;
В статье используется GRASS версии 6.4. Приведенный код применим и к более новым версиям GRASS, но, возможно, потребуется его незначительная правка.&lt;br /&gt;
&lt;br /&gt;
Исходный код модуля описанный в статье доступен по ссылке: [[Файл: Grass_wms.zip‎]].&lt;br /&gt;
&lt;br /&gt;
=== Архитектура системы ===&lt;br /&gt;
В разрабатываемой системе вся обработка геоданных будет возложена на GRASS, а обработка веб-запросов --- на Pyramid. &lt;br /&gt;
Основная часть WMS сервера, отвечающая за отрисовку геоданных --- модуль [http://grass.osgeo.org/grass64/manuals/d.mon.html d.mon], который будет использоваться совместно с [http://grass.osgeo.org/grass64/manuals/cairodriver.html графическим драйвером Cairo], позволяющим генерировать изображения в форматах PNG, BMP, PPM, PS, PDF и SVG.&lt;br /&gt;
&lt;br /&gt;
Для реализации сервера потребуется создать функции, служащие для:&lt;br /&gt;
&lt;br /&gt;
# Настройки путей к GRASS.&lt;br /&gt;
# Получения и анализа параметров запроса WMS.&lt;br /&gt;
# Отрисовки слоев по запросу клиента и сохранения результата в графический файл.&lt;br /&gt;
# Возвращения результата обработки запроса клиенту.&lt;br /&gt;
&lt;br /&gt;
Собственно к GRASS относятся первый и третий пункты, остальные --- обычные действия по обработке веб-запросов, которые реализуются при помощи Pyramid. Поэтому для простоты изложения и реализации объединим первый и третий пункты в виде одной функции, а второй и четвертый --- в виде другой.&lt;br /&gt;
&lt;br /&gt;
=== Зависимости и их установка ===&lt;br /&gt;
Для того, чтобы WMS сервер мог функционировать, требуется, чтобы на компьютере была установлена геоинформационная система [http://grass.osgeo.org/download/ GRASS] и [http://docs.pylonsproject.org/projects/pyramid/en/latest/narr/install.html Pyramid] (Pyramid рекомендуется устанавливать в [http://docs.pylonsproject.org/projects/pyramid/en/latest/narr/install.html#installing-the-virtualenv-package виртуальное окружение], чтобы не &amp;quot;мусорить&amp;quot; в основной системе).&lt;br /&gt;
&lt;br /&gt;
Установка этих систем обеспечит установку и настройку требуемых зависимостей.&lt;br /&gt;
&lt;br /&gt;
== Реализация ==&lt;br /&gt;
=== Настройка путей GRASS и обработка запроса клиента ===&lt;br /&gt;
Ниже приводится код функции, которая инициализирует GRASS, отрисовывает запрошенные пользователем слои и сохраняет полученное изображение во временном файле.&lt;br /&gt;
&lt;br /&gt;
На вход функция принимает &lt;br /&gt;
* список слоев (layers), которые требуется отрисовать;&lt;br /&gt;
* охват интересующего пользователя региона (bbox);&lt;br /&gt;
* ширину/высоту (width/height) изображения. &lt;br /&gt;
&lt;br /&gt;
На выходе функция возвращает имя файла, в котором будет сохранено запрошенное изображение.&lt;br /&gt;
&lt;br /&gt;
 def _grass_wms(layers=[], bbox=[], width=256, height=256):&lt;br /&gt;
    # Прописываем пути к GRASS. Исправить под свои нужды.&lt;br /&gt;
    gisdbase = &amp;quot;/home/useranme/GRASSDATA&amp;quot;&lt;br /&gt;
    location = &amp;quot;MSK_28407&amp;quot;&lt;br /&gt;
    mapset = &amp;quot;PERMANENT&amp;quot;&lt;br /&gt;
    gisbase = os.environ[&amp;quot;GISBASE&amp;quot;] = &amp;quot;/usr/lib/grass64&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
    # Добавляем путь модулям GRASS в системные пути&lt;br /&gt;
    sys.path.append(&amp;quot;%s/etc/python&amp;quot; % gisbase)&lt;br /&gt;
 &lt;br /&gt;
    # Импортируем библиотеки GRASS&lt;br /&gt;
    from grass.script import core as grass&lt;br /&gt;
    from grass.script import setup as gsetup&lt;br /&gt;
 &lt;br /&gt;
    # Инициализируем GRASS&lt;br /&gt;
    gsetup.init(gisbase, gisdbase,&lt;br /&gt;
               location, mapset)&lt;br /&gt;
 &lt;br /&gt;
    # Получаем список известных растровых и векторных слоев&lt;br /&gt;
    vector_layers = grass.list_strings(type = &amp;quot;vect&amp;quot;)&lt;br /&gt;
    raster_layers = grass.list_strings(type = &amp;quot;rast&amp;quot;)&lt;br /&gt;
 &lt;br /&gt;
    grass.run_command(&amp;quot;g.region&amp;quot;, w=bbox[0], s=bbox[1], e=bbox[2], n=bbox[3])&lt;br /&gt;
 &lt;br /&gt;
    # Создание временного файла&lt;br /&gt;
    tempfile = grass.tempfile()&lt;br /&gt;
    filename = &amp;quot;%s.png&amp;quot; % tempfile&lt;br /&gt;
 &lt;br /&gt;
    # Настраиваем параметры вывода&lt;br /&gt;
    os.environ[&amp;quot;GRASS_CAIROFILE&amp;quot;] = filename&lt;br /&gt;
    os.environ[&amp;quot;GRASS_WIDTH&amp;quot;] = width&lt;br /&gt;
    os.environ[&amp;quot;GRASS_HEIGHT&amp;quot;] = height&lt;br /&gt;
 &lt;br /&gt;
    # Отрисовка&lt;br /&gt;
    grass.run_command(&amp;quot;d.mon&amp;quot;, start=&amp;quot;cairo&amp;quot;)&lt;br /&gt;
 &lt;br /&gt;
    for layer in layers:&lt;br /&gt;
       if layer in raster_layers:&lt;br /&gt;
           grass.run_command(&amp;quot;d.rast&amp;quot;, map=layer, quiet=1)&lt;br /&gt;
       elif layer in vector_layers:&lt;br /&gt;
           grass.run_command(&amp;quot;d.vect&amp;quot;, map=layer, quiet=1, fcolor=&amp;quot;0:0:255&amp;quot;, color=None)&lt;br /&gt;
 &lt;br /&gt;
    grass.run_command(&amp;quot;d.mon&amp;quot;, stop=&amp;quot;cairo&amp;quot;)&lt;br /&gt;
 &lt;br /&gt;
    return filename&lt;br /&gt;
&lt;br /&gt;
Как видим, большая часть кода связана с первоначальной настройкой GRASS. Основной код по отрисовке запрошенных слоев использует команды GRASS и занимает всего пять строк:&lt;br /&gt;
  for layer in layers:&lt;br /&gt;
  ...&lt;br /&gt;
При этом все векторные слои будут отрисованы синим цветом, (см. параметры, передаваемые в &amp;lt;code&amp;gt;grass.run_command(&amp;quot;d.vect&amp;quot;, map=layer, quiet=1, fcolor=&amp;quot;0:0:255&amp;quot;, color=None)&amp;lt;/code&amp;gt;). Внешний вид слоя может быть изменен настройкой параметров команды [http://grass.osgeo.org/grass64/manuals/d.vect.html d.vect]. Например, данной командой можно назначить стиль отображения объекта в зависимости от его атрибутов или геометрических характеристик. &lt;br /&gt;
&lt;br /&gt;
Аналогично, растровые слои отображаются в цветовой схеме по умолчанию (или заранее назначенной пользователем вручную). При необходимости изменить стиль слоя при отрисовке следует воспользоваться командами, обрабатывающими цветовые схемы растровых карт, например [http://grass.osgeo.org/grass64/manuals/r.colors.html r.colors] или аналогичными модулями.&lt;br /&gt;
&lt;br /&gt;
Временный файл, в который сохраняется отрисованное изображение, в GRASS 6.4 задается следующими строками:&lt;br /&gt;
 # Настраиваем параметры вывода&lt;br /&gt;
 os.environ[&amp;quot;GRASS_CAIROFILE&amp;quot;] = filename&lt;br /&gt;
 os.environ[&amp;quot;GRASS_WIDTH&amp;quot;] = width&lt;br /&gt;
 os.environ[&amp;quot;GRASS_HEIGHT&amp;quot;] = height&lt;br /&gt;
Для GRASS седьмой версии можно немного упростить этот код, передавая параметры напрямую модулю &amp;lt;code&amp;gt;d.mon&amp;lt;/code&amp;gt;. Пример можно посмотреть в [http://www.webrian.ch/2013/12/grass-gis-web-map-service-with-pyramid.html исходной статье].&lt;br /&gt;
&lt;br /&gt;
=== Анализ запроса пользователя и возвращение результата ===&lt;br /&gt;
Анализ запроса пользователя производится в следующей функции:&lt;br /&gt;
 @view_config(route_name=&amp;quot;wms&amp;quot;)&lt;br /&gt;
 def wms_view(request):&lt;br /&gt;
 &lt;br /&gt;
    layers = request.params.get(&amp;quot;LAYERS&amp;quot;, &amp;quot;&amp;quot;).split(&amp;quot;,&amp;quot;)&lt;br /&gt;
    bbox = request.params.get(&amp;quot;BBOX&amp;quot;, &amp;quot;&amp;quot;).split(&amp;quot;,&amp;quot;)&lt;br /&gt;
    width = request.params.get(&amp;quot;WIDTH&amp;quot;)&lt;br /&gt;
    height = request.params.get(&amp;quot;HEIGHT&amp;quot;)&lt;br /&gt;
 &lt;br /&gt;
    try:&lt;br /&gt;
        filename = _grass_wms(layers=layers,&lt;br /&gt;
                              bbox=bbox,&lt;br /&gt;
                              width=width,&lt;br /&gt;
                              height=height)&lt;br /&gt;
        f = open(filename, &amp;quot;r+&amp;quot;)&lt;br /&gt;
        return Response(body=f.read(), content_type=&amp;quot;image/png&amp;quot;)&lt;br /&gt;
    except:&lt;br /&gt;
        pass&lt;br /&gt;
&lt;br /&gt;
Данная функция принимает запрос (request), в котором могут определяться:&lt;br /&gt;
* список слоев в запрашиваемом изображении (параметр LAYERS);&lt;br /&gt;
* охват области запрашиваемого изображения (параметр BBOX);&lt;br /&gt;
* высота и ширина запрашиваемого изображения (параметры HEIGHT и WIDTH).&lt;br /&gt;
&lt;br /&gt;
Полученные параметры анализируются и передаются в определенную выше функцию _grass_wms. Результат работы функции --- имя файла изображения --- считывается с диска и возвращается в качестве ответа на запрос.&lt;br /&gt;
&lt;br /&gt;
=== Создание веб-приложения ===&lt;br /&gt;
Еще одно действие --- создание простейшего веб-приложения, которое использует построенный WMS сервер. Воспользуемся библиотекой [http://gis-lab.info/qa/openlayers-begin.html OpenLayers] для отображения карты, возвращаемой сервером.&lt;br /&gt;
&lt;br /&gt;
Данный шаг является необязательным, но его удобно реализовать в целях отладки.&lt;br /&gt;
&lt;br /&gt;
Следующая функция создает веб-страницу с картой на базе слоев векторных слоев mo и io_15 из набора PERMANENT:&lt;br /&gt;
 @view_config(route_name=&amp;quot;index&amp;quot;)&lt;br /&gt;
 def index_view(request):&lt;br /&gt;
    body = &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
 &amp;lt;html xml:lang=&amp;quot;en&amp;quot;&lt;br /&gt;
 xmlns:tal=&amp;quot;http://xml.zope.org/namespaces/tal&amp;quot;&lt;br /&gt;
 xmlns=&amp;quot;http://www.w3.org/1999/xhtml&amp;quot;&amp;gt;&lt;br /&gt;
 &amp;lt;head&amp;gt;&lt;br /&gt;
  &amp;lt;title&amp;gt;GRASS GIS Web Map Service&amp;lt;/title&amp;gt;&lt;br /&gt;
  &amp;lt;script src=&amp;quot;http://openlayers.org/api/OpenLayers.js&amp;quot; type=&amp;quot;text/javascript&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;&lt;br /&gt;
  &amp;lt;script type=&amp;quot;text/javascript&amp;quot;&amp;gt;&lt;br /&gt;
    var map, wms_layer;&lt;br /&gt;
    function init(){&lt;br /&gt;
        var map = new OpenLayers.Map(&amp;quot;map-div&amp;quot;,{&lt;br /&gt;
            projection: &amp;quot;EPSG:28407&amp;quot;,&lt;br /&gt;
            maxExtent: new OpenLayers.Bounds(7361000, 6115000, 7435000, 6212000),&lt;br /&gt;
            numZoomLevels: 6,&lt;br /&gt;
        });&lt;br /&gt;
        var wms_layer = new OpenLayers.Layer.WMS(&amp;quot;GRASS WMS&amp;quot;, '/wms', {&lt;br /&gt;
            layers: &amp;quot;mo@PERMANENT,io_15@PERMANENT&amp;quot;&lt;br /&gt;
        },{&lt;br /&gt;
            singleTile: true,&lt;br /&gt;
        });&lt;br /&gt;
        map.addLayer(wms_layer);&lt;br /&gt;
        map.zoomToMaxExtent();&lt;br /&gt;
    }&lt;br /&gt;
  &amp;lt;/script&amp;gt;&lt;br /&gt;
 &amp;lt;/head&amp;gt;&lt;br /&gt;
 &amp;lt;body onload=&amp;quot;init()&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt; div id=&amp;quot;map-div&amp;quot; style=&amp;quot;height: 600px; width: 800px;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
 &amp;lt;/body&amp;gt;&lt;br /&gt;
 &amp;lt;/html&amp;gt;&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    return Response(body=body, content_type=&amp;quot;text/html&amp;quot;, status=200)&lt;br /&gt;
Понятно, что список доступных слоев (&amp;lt;code&amp;gt;layers: &amp;quot;mo@PERMANENT,io_15@PERMANENT&amp;quot;&amp;lt;/code&amp;gt;) и параметры области (&amp;lt;code&amp;gt;{projection: &amp;quot;EPSG:28407&amp;quot;, maxExtent: new OpenLayers.Bounds(7361000, 6115000, 7435000, 6212000), numZoomLevels: 6}&amp;lt;/code&amp;gt;) следует отредактировать под конкретный проект.&lt;br /&gt;
&lt;br /&gt;
=== Конфигурирование Pyramid ===&lt;br /&gt;
Для того, чтобы описанные выше функции можно было использовать, необходимо сконфигурировать Pyramid. Пример такой функции приведен ниже:&lt;br /&gt;
 def main():&lt;br /&gt;
    config = Configurator()&lt;br /&gt;
    config.add_static_view('static', 'static', cache_max_age=3600)&lt;br /&gt;
    config.add_route(&amp;quot;index&amp;quot;, '/')&lt;br /&gt;
    config.add_route(&amp;quot;wms&amp;quot;, '/wms')&lt;br /&gt;
    config.scan()&lt;br /&gt;
    app = config.make_wsgi_app()&lt;br /&gt;
    server = make_server('0.0.0.0', 8080, app)&lt;br /&gt;
    server.serve_forever()&lt;br /&gt;
&lt;br /&gt;
Эта функция создает сервер, который будет функционировать по адресу 0.0.0.0:8080&lt;br /&gt;
&lt;br /&gt;
=== Использование ===&lt;br /&gt;
После того, как WMS сервер будет настроен, можно его запустить командой:&lt;br /&gt;
 python grass_wms.py&lt;br /&gt;
(Здесь предполагается, что программный код хранится в файле grass_wms.py).&lt;br /&gt;
&lt;br /&gt;
Для проверки того, все ли было настроено верно, можно открыть браузер и в адресную строку внести параметры WMS-запроса, например,&lt;br /&gt;
 http://0.0.0.0:8080/wms?BBOX=7361000,6115000,7435000,6212000&amp;amp;LAYERS=mo@PERMANENT&amp;amp;WIDTH=300&amp;amp;HEIGHT=700&lt;br /&gt;
В результате в окне браузера будет показана запрошенная карта, построенная на базе слоя mo@PERMANENT.&lt;br /&gt;
Также можно загрузить сразу веб-странцу по адресу&lt;br /&gt;
 http://0.0.0.0:8080/&lt;br /&gt;
на которой при помощи OpenLayers будет отображена веб-карта, поддерживающая возможности прокрутки и масштабирования.&lt;br /&gt;
&lt;br /&gt;
== Ограничения данной реализации ==&lt;br /&gt;
Рассмотренный пример демонстрирует принцип создания сервера WMS, потому в нем опущен ряд деталей, которые должны быть реализованы в реальной системе. Например, в рассмотренном варианте в целях упрощения изложения были введены следующие ограничения:&lt;br /&gt;
* Нет перепроецирования &amp;quot;на лету&amp;quot;. Т.е. построенный сервер WMS может возвращать слои только в той проекции, в которой хранятся данные GRASS.&lt;br /&gt;
* Реализация не является потокобезопасной. Например, при одновременном запросе данных из разных областей GRASS могут проявляться неожиданные побочные эффекты (в коде производятся манипуляции с &amp;lt;code&amp;gt;g.region&amp;lt;/code&amp;gt;).&lt;br /&gt;
* Не полная поддержка [http://www.opengeospatial.org/standards/wms стандарта WMS]. Например, описанная реализация не поддерживает запрос GetCapabilities, поэтому подключить ту или иную ГИС в качестве клиента к созданному серверу не удастся. Это ограничение легко обходится --- достаточно в функцию &amp;lt;code&amp;gt;wms_view&amp;lt;/code&amp;gt; вставить обработку параметра REQUEST (и, в случае REQUEST=GetCapabilities, вернуть список доступных слоев).&lt;br /&gt;
&lt;br /&gt;
== Ссылки по теме ==&lt;br /&gt;
* [http://www.webrian.ch/2013/12/grass-gis-web-map-service-with-pyramid.html GRASS GIS Web Map Service with Pyramid]&lt;br /&gt;
* [http://docs.pylonsproject.org/projects/pyramid/en/latest/narr/introduction.html Документация фреймворка Pyramid]&lt;br /&gt;
* [http://grass.osgeo.org/ GRASS GIS: The world's leading Free GIS software]&lt;/div&gt;</summary>
		<author><name>KolesovDmitry</name></author>
	</entry>
	<entry>
		<id>https://wiki.gis-lab.info/index.php?title=%D0%A1%D0%BE%D0%B7%D0%B4%D0%B0%D0%BD%D0%B8%D0%B5_WMS_%D1%81%D0%B5%D1%80%D0%B2%D0%B5%D1%80%D0%B0_%D0%BD%D0%B0_%D0%B1%D0%B0%D0%B7%D0%B5_GRASS_GIS_%D0%B8_Pyramid&amp;diff=19448</id>
		<title>Создание WMS сервера на базе GRASS GIS и Pyramid</title>
		<link rel="alternate" type="text/html" href="https://wiki.gis-lab.info/index.php?title=%D0%A1%D0%BE%D0%B7%D0%B4%D0%B0%D0%BD%D0%B8%D0%B5_WMS_%D1%81%D0%B5%D1%80%D0%B2%D0%B5%D1%80%D0%B0_%D0%BD%D0%B0_%D0%B1%D0%B0%D0%B7%D0%B5_GRASS_GIS_%D0%B8_Pyramid&amp;diff=19448"/>
		<updated>2014-05-05T05:04:51Z</updated>

		<summary type="html">&lt;p&gt;KolesovDmitry: /* Ограничения данной реализации */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;В данной статье описывается простой пример создания [http://gis-lab.info/qa/ows.html WMS сервера] на базе геоинформационной системы GRASS. Доступ к данным организован при помощи [http://ru.wikipedia.org/wiki/Pyramid_%28%D0%BF%D1%80%D0%BE%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%BD%D1%8B%D0%B9_%D0%BA%D0%B0%D1%80%D0%BA%D0%B0%D1%81%29 фреймворка Pyramid].&lt;br /&gt;
&lt;br /&gt;
Данная статья является расширенным переводом статьи [http://www.webrian.ch/2013/12/grass-gis-web-map-service-with-pyramid.html GRASS GIS Web Map Service with Pyramid].&lt;br /&gt;
&lt;br /&gt;
== Общие сведения ==&lt;br /&gt;
Статья расчитана на читателя, который на базовом уровне знаком с геоинформационной системой GRASS и основами веб-разработки на языке программирования Python. В частности, читатель должен представлять, [http://gis-lab.info/qa/grass-external-scripting.html как происходит вызов команд GRASS на языке Python] и быть знакомым [http://docs.pylonsproject.org/projects/pyramid/en/latest/narr/introduction.html с принципами использования фреймворка Pyramid].&lt;br /&gt;
&lt;br /&gt;
В статье используется GRASS версии 6.4. Приведенный код применим и к более новым версиям GRASS, но, возможно, потребуется его незначительная правка.&lt;br /&gt;
&lt;br /&gt;
Исходный код модуля описанный в статье доступен по ссылке: [[Файл: Grass_wms.zip‎]].&lt;br /&gt;
&lt;br /&gt;
=== Архитектура системы ===&lt;br /&gt;
В разрабатываемой системе вся обработка геоданных будет возложена на GRASS, а обработка веб-запросов --- на Pyramid. &lt;br /&gt;
Основная часть WMS сервера, отвечающая за отрисовку геоданных --- модуль [http://grass.osgeo.org/grass64/manuals/d.mon.html d.mon], который будет использоваться совместно с [http://grass.osgeo.org/grass64/manuals/cairodriver.html графическим драйвером Cairo], позволяющим генерировать изображения в форматах PNG, BMP, PPM, PS, PDF и SVG.&lt;br /&gt;
&lt;br /&gt;
Для реализации сервера потребуется создать функции, служащие для:&lt;br /&gt;
&lt;br /&gt;
# Настройки путей к GRASS.&lt;br /&gt;
# Получения и анализа параметров запроса WMS.&lt;br /&gt;
# Отрисовки слоев по запросу клиента и сохранения результата в графический файл.&lt;br /&gt;
# Возвращения результата обработки запроса клиенту.&lt;br /&gt;
&lt;br /&gt;
Собственно к GRASS относятся первый и третий пункты, остальные --- обычные действия по обработке веб-запросов, которые реализуются при помощи Pyramid. Поэтому для простоты изложения и реализации объединим первый и третий пункты в виде одной функции, а второй и четвертый --- в виде другой.&lt;br /&gt;
&lt;br /&gt;
=== Зависимости и их установка ===&lt;br /&gt;
Для того, чтобы WMS сервер мог функционировать, требуется, чтобы на компьютере была установлена геоинформационная система [http://grass.osgeo.org/download/ GRASS] и [http://docs.pylonsproject.org/projects/pyramid/en/latest/narr/install.html Pyramid] (Pyramid рекомендуется устанавливать в [http://docs.pylonsproject.org/projects/pyramid/en/latest/narr/install.html#installing-the-virtualenv-package виртуальное окружение], чтобы не &amp;quot;мусорить&amp;quot; в основной системе).&lt;br /&gt;
&lt;br /&gt;
Установка этих систем обеспечит установку и настройку требуемых зависимостей.&lt;br /&gt;
&lt;br /&gt;
== Реализация ==&lt;br /&gt;
=== Настройка путей GRASS и обработка запроса клиента ===&lt;br /&gt;
Ниже приводится код функции, которая инициализирует GRASS, отрисовывает запрошенные пользователем слои и сохраняет полученное изображение во временном файле.&lt;br /&gt;
&lt;br /&gt;
На вход функция принимает &lt;br /&gt;
* список слоев (layers), которые требуется отрисовать;&lt;br /&gt;
* охват интересующего пользователя региона (bbox);&lt;br /&gt;
* ширину/высоту (width/height) изображения. &lt;br /&gt;
&lt;br /&gt;
На выходе функция возвращает имя файла, в котором будет сохранено запрошенное изображение.&lt;br /&gt;
&lt;br /&gt;
 def _grass_wms(layers=[], bbox=[], width=256, height=256):&lt;br /&gt;
    # Прописываем пути к GRASS. Исправить под свои нужды.&lt;br /&gt;
    gisdbase = &amp;quot;/home/useranme/GRASSDATA&amp;quot;&lt;br /&gt;
    location = &amp;quot;MSK_28407&amp;quot;&lt;br /&gt;
    mapset = &amp;quot;PERMANENT&amp;quot;&lt;br /&gt;
    gisbase = os.environ[&amp;quot;GISBASE&amp;quot;] = &amp;quot;/usr/lib/grass64&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
    # Добавляем путь модулям GRASS в системные пути&lt;br /&gt;
    sys.path.append(&amp;quot;%s/etc/python&amp;quot; % gisbase)&lt;br /&gt;
 &lt;br /&gt;
    # Импортируем библиотеки GRASS&lt;br /&gt;
    from grass.script import core as grass&lt;br /&gt;
    from grass.script import setup as gsetup&lt;br /&gt;
 &lt;br /&gt;
    # Инициализируем GRASS&lt;br /&gt;
    gsetup.init(gisbase, gisdbase,&lt;br /&gt;
               location, mapset)&lt;br /&gt;
 &lt;br /&gt;
    # Получаем список известных растровых и векторных слоев&lt;br /&gt;
    vector_layers = grass.list_strings(type = &amp;quot;vect&amp;quot;)&lt;br /&gt;
    raster_layers = grass.list_strings(type = &amp;quot;rast&amp;quot;)&lt;br /&gt;
 &lt;br /&gt;
    grass.run_command(&amp;quot;g.region&amp;quot;, w=bbox[0], s=bbox[1], e=bbox[2], n=bbox[3])&lt;br /&gt;
 &lt;br /&gt;
    # Создание временного файла&lt;br /&gt;
    tempfile = grass.tempfile()&lt;br /&gt;
    filename = &amp;quot;%s.png&amp;quot; % tempfile&lt;br /&gt;
 &lt;br /&gt;
    # Настраиваем параметры вывода&lt;br /&gt;
    os.environ[&amp;quot;GRASS_CAIROFILE&amp;quot;] = filename&lt;br /&gt;
    os.environ[&amp;quot;GRASS_WIDTH&amp;quot;] = width&lt;br /&gt;
    os.environ[&amp;quot;GRASS_HEIGHT&amp;quot;] = height&lt;br /&gt;
 &lt;br /&gt;
    # Отрисовка&lt;br /&gt;
    grass.run_command(&amp;quot;d.mon&amp;quot;, start=&amp;quot;cairo&amp;quot;)&lt;br /&gt;
 &lt;br /&gt;
    for layer in layers:&lt;br /&gt;
       if layer in raster_layers:&lt;br /&gt;
           grass.run_command(&amp;quot;d.rast&amp;quot;, map=layer, quiet=1)&lt;br /&gt;
       elif layer in vector_layers:&lt;br /&gt;
           grass.run_command(&amp;quot;d.vect&amp;quot;, map=layer, quiet=1, fcolor=&amp;quot;0:0:255&amp;quot;, color=None)&lt;br /&gt;
 &lt;br /&gt;
    grass.run_command(&amp;quot;d.mon&amp;quot;, stop=&amp;quot;cairo&amp;quot;)&lt;br /&gt;
 &lt;br /&gt;
    return filename&lt;br /&gt;
&lt;br /&gt;
Как видим, большая часть кода связана с первоначальной настройкой GRASS. Основной код по отрисовке запрошенных слоев использует команды GRASS и занимает всего пять строк:&lt;br /&gt;
  for layer in layers:&lt;br /&gt;
  ...&lt;br /&gt;
При этом все векторные слои будут отрисованы синим цветом, (см. параметры, передаваемые в &amp;lt;code&amp;gt;grass.run_command(&amp;quot;d.vect&amp;quot;, map=layer, quiet=1, fcolor=&amp;quot;0:0:255&amp;quot;, color=None)&amp;lt;/code&amp;gt;). Внешний вид слоя может быть изменен настройкой параметров команды [http://grass.osgeo.org/grass64/manuals/d.vect.html d.vect]. Например, данной командой можно назначить стиль отображения объекта в зависимости от его атрибутов или геометрических характеристик. &lt;br /&gt;
&lt;br /&gt;
Аналогично, растровые слои отображаются в цветовой схеме по умолчанию (или заранее назначенной пользователем вручную). При необходимости изменить стиль слоя при отрисовке следует воспользоваться командами, обрабатывающими цветовые схемы растровых карт, например [http://grass.osgeo.org/grass64/manuals/r.colors.html r.colors] или аналогичными модулями.&lt;br /&gt;
&lt;br /&gt;
Временный файл, в который сохраняется отрисованное изображение, в GRASS 6.4 задается следующими строками:&lt;br /&gt;
 # Настраиваем параметры вывода&lt;br /&gt;
 os.environ[&amp;quot;GRASS_CAIROFILE&amp;quot;] = filename&lt;br /&gt;
 os.environ[&amp;quot;GRASS_WIDTH&amp;quot;] = width&lt;br /&gt;
 os.environ[&amp;quot;GRASS_HEIGHT&amp;quot;] = height&lt;br /&gt;
Для GRASS седьмой версии можно немного упростить этот код, передавая параметры напрямую модулю &amp;lt;code&amp;gt;d.mon&amp;lt;/code&amp;gt;. Пример можно посмотреть в [http://www.webrian.ch/2013/12/grass-gis-web-map-service-with-pyramid.html исходной статье].&lt;br /&gt;
&lt;br /&gt;
=== Анализ запроса пользователя и возвращение результата ===&lt;br /&gt;
Анализ запроса пользователя производится в следующей функции:&lt;br /&gt;
 @view_config(route_name=&amp;quot;wms&amp;quot;)&lt;br /&gt;
 def wms_view(request):&lt;br /&gt;
 &lt;br /&gt;
    layers = request.params.get(&amp;quot;LAYERS&amp;quot;, &amp;quot;&amp;quot;).split(&amp;quot;,&amp;quot;)&lt;br /&gt;
    bbox = request.params.get(&amp;quot;BBOX&amp;quot;, &amp;quot;&amp;quot;).split(&amp;quot;,&amp;quot;)&lt;br /&gt;
    width = request.params.get(&amp;quot;WIDTH&amp;quot;)&lt;br /&gt;
    height = request.params.get(&amp;quot;HEIGHT&amp;quot;)&lt;br /&gt;
 &lt;br /&gt;
    try:&lt;br /&gt;
        filename = _grass_wms(layers=layers,&lt;br /&gt;
                              bbox=bbox,&lt;br /&gt;
                              width=width,&lt;br /&gt;
                              height=height)&lt;br /&gt;
        f = open(filename, &amp;quot;r+&amp;quot;)&lt;br /&gt;
        return Response(body=f.read(), content_type=&amp;quot;image/png&amp;quot;)&lt;br /&gt;
    except:&lt;br /&gt;
        pass&lt;br /&gt;
&lt;br /&gt;
Данная функция принимает запрос (request), в котором могут определяться:&lt;br /&gt;
* список слоев в запрашиваемом изображении (параметр LAYERS);&lt;br /&gt;
* охват области запрашиваемого изображения (параметр BBOX);&lt;br /&gt;
* высота и ширина запрашиваемого изображения (параметры HEIGHT и WIDTH).&lt;br /&gt;
&lt;br /&gt;
Полученные параметры анализируются и передаются в определенную выше функцию _grass_wms. Результат работы функции --- имя файла изображения --- считывается с диска и возвращается в качестве ответа на запрос.&lt;br /&gt;
&lt;br /&gt;
=== Создание веб-приложения ===&lt;br /&gt;
Еще одно действие --- создание простейшего веб-приложения, которое использует построенный WMS сервер. Воспользуемся библиотекой [http://gis-lab.info/qa/openlayers-begin.html OpenLayers] для отображения карты, возвращаемой сервером.&lt;br /&gt;
&lt;br /&gt;
Данный шаг является необязательным, но его удобно реализовать в целях отладки.&lt;br /&gt;
&lt;br /&gt;
Следующая функция создает веб-страницу с картой на базе слоев векторных слоев mo и io_15 из набора PERMANENT:&lt;br /&gt;
 @view_config(route_name=&amp;quot;index&amp;quot;)&lt;br /&gt;
 def index_view(request):&lt;br /&gt;
    body = &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
 &amp;lt;html xml:lang=&amp;quot;en&amp;quot;&lt;br /&gt;
 xmlns:tal=&amp;quot;http://xml.zope.org/namespaces/tal&amp;quot;&lt;br /&gt;
 xmlns=&amp;quot;http://www.w3.org/1999/xhtml&amp;quot;&amp;gt;&lt;br /&gt;
 &amp;lt;head&amp;gt;&lt;br /&gt;
  &amp;lt;title&amp;gt;GRASS GIS Web Map Service&amp;lt;/title&amp;gt;&lt;br /&gt;
  &amp;lt;script src=&amp;quot;http://openlayers.org/api/OpenLayers.js&amp;quot; type=&amp;quot;text/javascript&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;&lt;br /&gt;
  &amp;lt;script type=&amp;quot;text/javascript&amp;quot;&amp;gt;&lt;br /&gt;
    var map, wms_layer;&lt;br /&gt;
    function init(){&lt;br /&gt;
        var map = new OpenLayers.Map(&amp;quot;map-div&amp;quot;,{&lt;br /&gt;
            projection: &amp;quot;EPSG:28407&amp;quot;,&lt;br /&gt;
            maxExtent: new OpenLayers.Bounds(7361000, 6115000, 7435000, 6212000),&lt;br /&gt;
            numZoomLevels: 6,&lt;br /&gt;
        });&lt;br /&gt;
        var wms_layer = new OpenLayers.Layer.WMS(&amp;quot;GRASS WMS&amp;quot;, '/wms', {&lt;br /&gt;
            layers: &amp;quot;mo@PERMANENT,io_15@PERMANENT&amp;quot;&lt;br /&gt;
        },{&lt;br /&gt;
            singleTile: true,&lt;br /&gt;
        });&lt;br /&gt;
        map.addLayer(wms_layer);&lt;br /&gt;
        map.zoomToMaxExtent();&lt;br /&gt;
    }&lt;br /&gt;
  &amp;lt;/script&amp;gt;&lt;br /&gt;
 &amp;lt;/head&amp;gt;&lt;br /&gt;
 &amp;lt;body onload=&amp;quot;init()&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt; div id=&amp;quot;map-div&amp;quot; style=&amp;quot;height: 600px; width: 800px;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
 &amp;lt;/body&amp;gt;&lt;br /&gt;
 &amp;lt;/html&amp;gt;&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    return Response(body=body, content_type=&amp;quot;text/html&amp;quot;, status=200)&lt;br /&gt;
Понятно, что список доступных слоев (&amp;lt;code&amp;gt;layers: &amp;quot;mo@PERMANENT,io_15@PERMANENT&amp;quot;&amp;lt;/code&amp;gt;) и параметры области (&amp;lt;code&amp;gt;{projection: &amp;quot;EPSG:28407&amp;quot;, maxExtent: new OpenLayers.Bounds(7361000, 6115000, 7435000, 6212000), numZoomLevels: 6}&amp;lt;/code&amp;gt;) следует отредактировать под конкретный проект.&lt;br /&gt;
&lt;br /&gt;
=== Конфигурирование Pyramid ===&lt;br /&gt;
Для того, чтобы описанные выше функции можно было использовать, необходимо сконфигурировать Pyramid. Пример такой функции приведен ниже:&lt;br /&gt;
 def main():&lt;br /&gt;
    config = Configurator()&lt;br /&gt;
    config.add_static_view('static', 'static', cache_max_age=3600)&lt;br /&gt;
    config.add_route(&amp;quot;index&amp;quot;, '/')&lt;br /&gt;
    config.add_route(&amp;quot;wms&amp;quot;, '/wms')&lt;br /&gt;
    config.scan()&lt;br /&gt;
    app = config.make_wsgi_app()&lt;br /&gt;
    server = make_server('0.0.0.0', 8080, app)&lt;br /&gt;
    server.serve_forever()&lt;br /&gt;
&lt;br /&gt;
Эта функция создает сервер, который будет функционировать по адресу 0.0.0.0:8080&lt;br /&gt;
&lt;br /&gt;
=== Использование ===&lt;br /&gt;
После того, как WMS сервер будет настроен, можно его запустить командой:&lt;br /&gt;
 python grass_wms.py&lt;br /&gt;
(Здесь предполагается, что программный код хранится в файле grass_wms.py).&lt;br /&gt;
&lt;br /&gt;
Для проверки того, все ли было настроено верно, можно открыть браузер и в адресную строку внести параметры WMS-запроса, например,&lt;br /&gt;
 http://0.0.0.0:8080/wms?BBOX=7361000,6115000,7435000,6212000&amp;amp;LAYERS=mo@PERMANENT&amp;amp;WIDTH=300&amp;amp;HEIGHT=700&lt;br /&gt;
В результате в окне браузера будет показана запрошенная карта, построенная на базе слоя mo@PERMANENT.&lt;br /&gt;
Также можно загрузить сразу веб-странцу по адресу&lt;br /&gt;
 http://0.0.0.0:8080/&lt;br /&gt;
на которой при помощи OpenLayers будет отображена веб-карта, поддерживающая возможности прокрутки и масштабирования.&lt;br /&gt;
&lt;br /&gt;
== Ограничения данной реализации ==&lt;br /&gt;
Рассмотренный пример демонстрирует принцип создания сервера WMS, потому в нем опущен ряд деталей, которые должны быть реализованы в реальной системе. Например, в рассмотренном варианте в целях упрощения изложения были введены следующие ограничения:&lt;br /&gt;
* Нет перепроецирования &amp;quot;на лету&amp;quot;. Т.е. построенный сервер WMS может возвращать слои только в той проекции, в которой хранятся данные GRASS.&lt;br /&gt;
* Реализация не является потокобезопасной. Например, при одновременном запросе данных из разных областей GRASS могут проявляться неожиданные побочные эффекты (в коде производятся манипуляции с &amp;lt;code&amp;gt;g.region&amp;lt;/code&amp;gt;).&lt;br /&gt;
* Не полная поддержка [http://www.opengeospatial.org/standards/wms стандарта WMS]. Например, описанная реализация не поддерживает запрос GetCapabilities, поэтому подключить ту или иную ГИС в качестве клиента к серверу не удастся. Это ограничение легко обходится --- достаточно в функцию &amp;lt;code&amp;gt;wms_view&amp;lt;/code&amp;gt; вставить обработку параметра REQUEST (в случае REQUEST=GetCapabilities вернуть список доступных слоев).&lt;br /&gt;
&lt;br /&gt;
== Ссылки по теме ==&lt;br /&gt;
* [http://www.webrian.ch/2013/12/grass-gis-web-map-service-with-pyramid.html GRASS GIS Web Map Service with Pyramid]&lt;br /&gt;
* [http://docs.pylonsproject.org/projects/pyramid/en/latest/narr/introduction.html Документация фреймворка Pyramid]&lt;br /&gt;
* [http://grass.osgeo.org/ GRASS GIS: The world's leading Free GIS software]&lt;/div&gt;</summary>
		<author><name>KolesovDmitry</name></author>
	</entry>
	<entry>
		<id>https://wiki.gis-lab.info/index.php?title=%D0%A1%D0%BE%D0%B7%D0%B4%D0%B0%D0%BD%D0%B8%D0%B5_WMS_%D1%81%D0%B5%D1%80%D0%B2%D0%B5%D1%80%D0%B0_%D0%BD%D0%B0_%D0%B1%D0%B0%D0%B7%D0%B5_GRASS_GIS_%D0%B8_Pyramid&amp;diff=19447</id>
		<title>Создание WMS сервера на базе GRASS GIS и Pyramid</title>
		<link rel="alternate" type="text/html" href="https://wiki.gis-lab.info/index.php?title=%D0%A1%D0%BE%D0%B7%D0%B4%D0%B0%D0%BD%D0%B8%D0%B5_WMS_%D1%81%D0%B5%D1%80%D0%B2%D0%B5%D1%80%D0%B0_%D0%BD%D0%B0_%D0%B1%D0%B0%D0%B7%D0%B5_GRASS_GIS_%D0%B8_Pyramid&amp;diff=19447"/>
		<updated>2014-05-05T04:55:27Z</updated>

		<summary type="html">&lt;p&gt;KolesovDmitry: /* Конфигурирование Pyramid */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;В данной статье описывается простой пример создания [http://gis-lab.info/qa/ows.html WMS сервера] на базе геоинформационной системы GRASS. Доступ к данным организован при помощи [http://ru.wikipedia.org/wiki/Pyramid_%28%D0%BF%D1%80%D0%BE%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%BD%D1%8B%D0%B9_%D0%BA%D0%B0%D1%80%D0%BA%D0%B0%D1%81%29 фреймворка Pyramid].&lt;br /&gt;
&lt;br /&gt;
Данная статья является расширенным переводом статьи [http://www.webrian.ch/2013/12/grass-gis-web-map-service-with-pyramid.html GRASS GIS Web Map Service with Pyramid].&lt;br /&gt;
&lt;br /&gt;
== Общие сведения ==&lt;br /&gt;
Статья расчитана на читателя, который на базовом уровне знаком с геоинформационной системой GRASS и основами веб-разработки на языке программирования Python. В частности, читатель должен представлять, [http://gis-lab.info/qa/grass-external-scripting.html как происходит вызов команд GRASS на языке Python] и быть знакомым [http://docs.pylonsproject.org/projects/pyramid/en/latest/narr/introduction.html с принципами использования фреймворка Pyramid].&lt;br /&gt;
&lt;br /&gt;
В статье используется GRASS версии 6.4. Приведенный код применим и к более новым версиям GRASS, но, возможно, потребуется его незначительная правка.&lt;br /&gt;
&lt;br /&gt;
Исходный код модуля описанный в статье доступен по ссылке: [[Файл: Grass_wms.zip‎]].&lt;br /&gt;
&lt;br /&gt;
=== Архитектура системы ===&lt;br /&gt;
В разрабатываемой системе вся обработка геоданных будет возложена на GRASS, а обработка веб-запросов --- на Pyramid. &lt;br /&gt;
Основная часть WMS сервера, отвечающая за отрисовку геоданных --- модуль [http://grass.osgeo.org/grass64/manuals/d.mon.html d.mon], который будет использоваться совместно с [http://grass.osgeo.org/grass64/manuals/cairodriver.html графическим драйвером Cairo], позволяющим генерировать изображения в форматах PNG, BMP, PPM, PS, PDF и SVG.&lt;br /&gt;
&lt;br /&gt;
Для реализации сервера потребуется создать функции, служащие для:&lt;br /&gt;
&lt;br /&gt;
# Настройки путей к GRASS.&lt;br /&gt;
# Получения и анализа параметров запроса WMS.&lt;br /&gt;
# Отрисовки слоев по запросу клиента и сохранения результата в графический файл.&lt;br /&gt;
# Возвращения результата обработки запроса клиенту.&lt;br /&gt;
&lt;br /&gt;
Собственно к GRASS относятся первый и третий пункты, остальные --- обычные действия по обработке веб-запросов, которые реализуются при помощи Pyramid. Поэтому для простоты изложения и реализации объединим первый и третий пункты в виде одной функции, а второй и четвертый --- в виде другой.&lt;br /&gt;
&lt;br /&gt;
=== Зависимости и их установка ===&lt;br /&gt;
Для того, чтобы WMS сервер мог функционировать, требуется, чтобы на компьютере была установлена геоинформационная система [http://grass.osgeo.org/download/ GRASS] и [http://docs.pylonsproject.org/projects/pyramid/en/latest/narr/install.html Pyramid] (Pyramid рекомендуется устанавливать в [http://docs.pylonsproject.org/projects/pyramid/en/latest/narr/install.html#installing-the-virtualenv-package виртуальное окружение], чтобы не &amp;quot;мусорить&amp;quot; в основной системе).&lt;br /&gt;
&lt;br /&gt;
Установка этих систем обеспечит установку и настройку требуемых зависимостей.&lt;br /&gt;
&lt;br /&gt;
== Реализация ==&lt;br /&gt;
=== Настройка путей GRASS и обработка запроса клиента ===&lt;br /&gt;
Ниже приводится код функции, которая инициализирует GRASS, отрисовывает запрошенные пользователем слои и сохраняет полученное изображение во временном файле.&lt;br /&gt;
&lt;br /&gt;
На вход функция принимает &lt;br /&gt;
* список слоев (layers), которые требуется отрисовать;&lt;br /&gt;
* охват интересующего пользователя региона (bbox);&lt;br /&gt;
* ширину/высоту (width/height) изображения. &lt;br /&gt;
&lt;br /&gt;
На выходе функция возвращает имя файла, в котором будет сохранено запрошенное изображение.&lt;br /&gt;
&lt;br /&gt;
 def _grass_wms(layers=[], bbox=[], width=256, height=256):&lt;br /&gt;
    # Прописываем пути к GRASS. Исправить под свои нужды.&lt;br /&gt;
    gisdbase = &amp;quot;/home/useranme/GRASSDATA&amp;quot;&lt;br /&gt;
    location = &amp;quot;MSK_28407&amp;quot;&lt;br /&gt;
    mapset = &amp;quot;PERMANENT&amp;quot;&lt;br /&gt;
    gisbase = os.environ[&amp;quot;GISBASE&amp;quot;] = &amp;quot;/usr/lib/grass64&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
    # Добавляем путь модулям GRASS в системные пути&lt;br /&gt;
    sys.path.append(&amp;quot;%s/etc/python&amp;quot; % gisbase)&lt;br /&gt;
 &lt;br /&gt;
    # Импортируем библиотеки GRASS&lt;br /&gt;
    from grass.script import core as grass&lt;br /&gt;
    from grass.script import setup as gsetup&lt;br /&gt;
 &lt;br /&gt;
    # Инициализируем GRASS&lt;br /&gt;
    gsetup.init(gisbase, gisdbase,&lt;br /&gt;
               location, mapset)&lt;br /&gt;
 &lt;br /&gt;
    # Получаем список известных растровых и векторных слоев&lt;br /&gt;
    vector_layers = grass.list_strings(type = &amp;quot;vect&amp;quot;)&lt;br /&gt;
    raster_layers = grass.list_strings(type = &amp;quot;rast&amp;quot;)&lt;br /&gt;
 &lt;br /&gt;
    grass.run_command(&amp;quot;g.region&amp;quot;, w=bbox[0], s=bbox[1], e=bbox[2], n=bbox[3])&lt;br /&gt;
 &lt;br /&gt;
    # Создание временного файла&lt;br /&gt;
    tempfile = grass.tempfile()&lt;br /&gt;
    filename = &amp;quot;%s.png&amp;quot; % tempfile&lt;br /&gt;
 &lt;br /&gt;
    # Настраиваем параметры вывода&lt;br /&gt;
    os.environ[&amp;quot;GRASS_CAIROFILE&amp;quot;] = filename&lt;br /&gt;
    os.environ[&amp;quot;GRASS_WIDTH&amp;quot;] = width&lt;br /&gt;
    os.environ[&amp;quot;GRASS_HEIGHT&amp;quot;] = height&lt;br /&gt;
 &lt;br /&gt;
    # Отрисовка&lt;br /&gt;
    grass.run_command(&amp;quot;d.mon&amp;quot;, start=&amp;quot;cairo&amp;quot;)&lt;br /&gt;
 &lt;br /&gt;
    for layer in layers:&lt;br /&gt;
       if layer in raster_layers:&lt;br /&gt;
           grass.run_command(&amp;quot;d.rast&amp;quot;, map=layer, quiet=1)&lt;br /&gt;
       elif layer in vector_layers:&lt;br /&gt;
           grass.run_command(&amp;quot;d.vect&amp;quot;, map=layer, quiet=1, fcolor=&amp;quot;0:0:255&amp;quot;, color=None)&lt;br /&gt;
 &lt;br /&gt;
    grass.run_command(&amp;quot;d.mon&amp;quot;, stop=&amp;quot;cairo&amp;quot;)&lt;br /&gt;
 &lt;br /&gt;
    return filename&lt;br /&gt;
&lt;br /&gt;
Как видим, большая часть кода связана с первоначальной настройкой GRASS. Основной код по отрисовке запрошенных слоев использует команды GRASS и занимает всего пять строк:&lt;br /&gt;
  for layer in layers:&lt;br /&gt;
  ...&lt;br /&gt;
При этом все векторные слои будут отрисованы синим цветом, (см. параметры, передаваемые в &amp;lt;code&amp;gt;grass.run_command(&amp;quot;d.vect&amp;quot;, map=layer, quiet=1, fcolor=&amp;quot;0:0:255&amp;quot;, color=None)&amp;lt;/code&amp;gt;). Внешний вид слоя может быть изменен настройкой параметров команды [http://grass.osgeo.org/grass64/manuals/d.vect.html d.vect]. Например, данной командой можно назначить стиль отображения объекта в зависимости от его атрибутов или геометрических характеристик. &lt;br /&gt;
&lt;br /&gt;
Аналогично, растровые слои отображаются в цветовой схеме по умолчанию (или заранее назначенной пользователем вручную). При необходимости изменить стиль слоя при отрисовке следует воспользоваться командами, обрабатывающими цветовые схемы растровых карт, например [http://grass.osgeo.org/grass64/manuals/r.colors.html r.colors] или аналогичными модулями.&lt;br /&gt;
&lt;br /&gt;
Временный файл, в который сохраняется отрисованное изображение, в GRASS 6.4 задается следующими строками:&lt;br /&gt;
 # Настраиваем параметры вывода&lt;br /&gt;
 os.environ[&amp;quot;GRASS_CAIROFILE&amp;quot;] = filename&lt;br /&gt;
 os.environ[&amp;quot;GRASS_WIDTH&amp;quot;] = width&lt;br /&gt;
 os.environ[&amp;quot;GRASS_HEIGHT&amp;quot;] = height&lt;br /&gt;
Для GRASS седьмой версии можно немного упростить этот код, передавая параметры напрямую модулю &amp;lt;code&amp;gt;d.mon&amp;lt;/code&amp;gt;. Пример можно посмотреть в [http://www.webrian.ch/2013/12/grass-gis-web-map-service-with-pyramid.html исходной статье].&lt;br /&gt;
&lt;br /&gt;
=== Анализ запроса пользователя и возвращение результата ===&lt;br /&gt;
Анализ запроса пользователя производится в следующей функции:&lt;br /&gt;
 @view_config(route_name=&amp;quot;wms&amp;quot;)&lt;br /&gt;
 def wms_view(request):&lt;br /&gt;
 &lt;br /&gt;
    layers = request.params.get(&amp;quot;LAYERS&amp;quot;, &amp;quot;&amp;quot;).split(&amp;quot;,&amp;quot;)&lt;br /&gt;
    bbox = request.params.get(&amp;quot;BBOX&amp;quot;, &amp;quot;&amp;quot;).split(&amp;quot;,&amp;quot;)&lt;br /&gt;
    width = request.params.get(&amp;quot;WIDTH&amp;quot;)&lt;br /&gt;
    height = request.params.get(&amp;quot;HEIGHT&amp;quot;)&lt;br /&gt;
 &lt;br /&gt;
    try:&lt;br /&gt;
        filename = _grass_wms(layers=layers,&lt;br /&gt;
                              bbox=bbox,&lt;br /&gt;
                              width=width,&lt;br /&gt;
                              height=height)&lt;br /&gt;
        f = open(filename, &amp;quot;r+&amp;quot;)&lt;br /&gt;
        return Response(body=f.read(), content_type=&amp;quot;image/png&amp;quot;)&lt;br /&gt;
    except:&lt;br /&gt;
        pass&lt;br /&gt;
&lt;br /&gt;
Данная функция принимает запрос (request), в котором могут определяться:&lt;br /&gt;
* список слоев в запрашиваемом изображении (параметр LAYERS);&lt;br /&gt;
* охват области запрашиваемого изображения (параметр BBOX);&lt;br /&gt;
* высота и ширина запрашиваемого изображения (параметры HEIGHT и WIDTH).&lt;br /&gt;
&lt;br /&gt;
Полученные параметры анализируются и передаются в определенную выше функцию _grass_wms. Результат работы функции --- имя файла изображения --- считывается с диска и возвращается в качестве ответа на запрос.&lt;br /&gt;
&lt;br /&gt;
=== Создание веб-приложения ===&lt;br /&gt;
Еще одно действие --- создание простейшего веб-приложения, которое использует построенный WMS сервер. Воспользуемся библиотекой [http://gis-lab.info/qa/openlayers-begin.html OpenLayers] для отображения карты, возвращаемой сервером.&lt;br /&gt;
&lt;br /&gt;
Данный шаг является необязательным, но его удобно реализовать в целях отладки.&lt;br /&gt;
&lt;br /&gt;
Следующая функция создает веб-страницу с картой на базе слоев векторных слоев mo и io_15 из набора PERMANENT:&lt;br /&gt;
 @view_config(route_name=&amp;quot;index&amp;quot;)&lt;br /&gt;
 def index_view(request):&lt;br /&gt;
    body = &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
 &amp;lt;html xml:lang=&amp;quot;en&amp;quot;&lt;br /&gt;
 xmlns:tal=&amp;quot;http://xml.zope.org/namespaces/tal&amp;quot;&lt;br /&gt;
 xmlns=&amp;quot;http://www.w3.org/1999/xhtml&amp;quot;&amp;gt;&lt;br /&gt;
 &amp;lt;head&amp;gt;&lt;br /&gt;
  &amp;lt;title&amp;gt;GRASS GIS Web Map Service&amp;lt;/title&amp;gt;&lt;br /&gt;
  &amp;lt;script src=&amp;quot;http://openlayers.org/api/OpenLayers.js&amp;quot; type=&amp;quot;text/javascript&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;&lt;br /&gt;
  &amp;lt;script type=&amp;quot;text/javascript&amp;quot;&amp;gt;&lt;br /&gt;
    var map, wms_layer;&lt;br /&gt;
    function init(){&lt;br /&gt;
        var map = new OpenLayers.Map(&amp;quot;map-div&amp;quot;,{&lt;br /&gt;
            projection: &amp;quot;EPSG:28407&amp;quot;,&lt;br /&gt;
            maxExtent: new OpenLayers.Bounds(7361000, 6115000, 7435000, 6212000),&lt;br /&gt;
            numZoomLevels: 6,&lt;br /&gt;
        });&lt;br /&gt;
        var wms_layer = new OpenLayers.Layer.WMS(&amp;quot;GRASS WMS&amp;quot;, '/wms', {&lt;br /&gt;
            layers: &amp;quot;mo@PERMANENT,io_15@PERMANENT&amp;quot;&lt;br /&gt;
        },{&lt;br /&gt;
            singleTile: true,&lt;br /&gt;
        });&lt;br /&gt;
        map.addLayer(wms_layer);&lt;br /&gt;
        map.zoomToMaxExtent();&lt;br /&gt;
    }&lt;br /&gt;
  &amp;lt;/script&amp;gt;&lt;br /&gt;
 &amp;lt;/head&amp;gt;&lt;br /&gt;
 &amp;lt;body onload=&amp;quot;init()&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt; div id=&amp;quot;map-div&amp;quot; style=&amp;quot;height: 600px; width: 800px;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
 &amp;lt;/body&amp;gt;&lt;br /&gt;
 &amp;lt;/html&amp;gt;&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    return Response(body=body, content_type=&amp;quot;text/html&amp;quot;, status=200)&lt;br /&gt;
Понятно, что список доступных слоев (&amp;lt;code&amp;gt;layers: &amp;quot;mo@PERMANENT,io_15@PERMANENT&amp;quot;&amp;lt;/code&amp;gt;) и параметры области (&amp;lt;code&amp;gt;{projection: &amp;quot;EPSG:28407&amp;quot;, maxExtent: new OpenLayers.Bounds(7361000, 6115000, 7435000, 6212000), numZoomLevels: 6}&amp;lt;/code&amp;gt;) следует отредактировать под конкретный проект.&lt;br /&gt;
&lt;br /&gt;
=== Конфигурирование Pyramid ===&lt;br /&gt;
Для того, чтобы описанные выше функции можно было использовать, необходимо сконфигурировать Pyramid. Пример такой функции приведен ниже:&lt;br /&gt;
 def main():&lt;br /&gt;
    config = Configurator()&lt;br /&gt;
    config.add_static_view('static', 'static', cache_max_age=3600)&lt;br /&gt;
    config.add_route(&amp;quot;index&amp;quot;, '/')&lt;br /&gt;
    config.add_route(&amp;quot;wms&amp;quot;, '/wms')&lt;br /&gt;
    config.scan()&lt;br /&gt;
    app = config.make_wsgi_app()&lt;br /&gt;
    server = make_server('0.0.0.0', 8080, app)&lt;br /&gt;
    server.serve_forever()&lt;br /&gt;
&lt;br /&gt;
Эта функция создает сервер, который будет функционировать по адресу 0.0.0.0:8080&lt;br /&gt;
&lt;br /&gt;
=== Использование ===&lt;br /&gt;
После того, как WMS сервер будет настроен, можно его запустить командой:&lt;br /&gt;
 python grass_wms.py&lt;br /&gt;
(Здесь предполагается, что программный код хранится в файле grass_wms.py).&lt;br /&gt;
&lt;br /&gt;
Для проверки того, все ли было настроено верно, можно открыть браузер и в адресную строку внести параметры WMS-запроса, например,&lt;br /&gt;
 http://0.0.0.0:8080/wms?BBOX=7361000,6115000,7435000,6212000&amp;amp;LAYERS=mo@PERMANENT&amp;amp;WIDTH=300&amp;amp;HEIGHT=700&lt;br /&gt;
В результате в окне браузера будет показана запрошенная карта, построенная на базе слоя mo@PERMANENT.&lt;br /&gt;
Также можно загрузить сразу веб-странцу по адресу&lt;br /&gt;
 http://0.0.0.0:8080/&lt;br /&gt;
на которой при помощи OpenLayers будет отображена веб-карта, поддерживающая возможности прокрутки и масштабирования.&lt;br /&gt;
&lt;br /&gt;
== Ограничения данной реализации ==&lt;br /&gt;
Рассмотренный пример демонстрирует принцип создания сервера WMS, потому в нем опущен ряд деталей, которые должны быть реализованы в реальной системе. Например, в рассмотренном варианте присутствуют следующие ограничения:&lt;br /&gt;
* Нет перепроецирования &amp;quot;на лету&amp;quot;. Т.е. построенный сервер WMS может возвращать слои только в той проекции, в которой хранятся данные GRASS.&lt;br /&gt;
* Реализация не является потокобезопасной. Например, при одновременном запросе данных из разных областей GRASS могут проявляться неожиданные побочные эффекты.&lt;br /&gt;
&lt;br /&gt;
== Ссылки по теме ==&lt;br /&gt;
* [http://www.webrian.ch/2013/12/grass-gis-web-map-service-with-pyramid.html GRASS GIS Web Map Service with Pyramid]&lt;br /&gt;
* [http://docs.pylonsproject.org/projects/pyramid/en/latest/narr/introduction.html Документация фреймворка Pyramid]&lt;br /&gt;
* [http://grass.osgeo.org/ GRASS GIS: The world's leading Free GIS software]&lt;/div&gt;</summary>
		<author><name>KolesovDmitry</name></author>
	</entry>
	<entry>
		<id>https://wiki.gis-lab.info/index.php?title=%D0%A1%D0%BE%D0%B7%D0%B4%D0%B0%D0%BD%D0%B8%D0%B5_WMS_%D1%81%D0%B5%D1%80%D0%B2%D0%B5%D1%80%D0%B0_%D0%BD%D0%B0_%D0%B1%D0%B0%D0%B7%D0%B5_GRASS_GIS_%D0%B8_Pyramid&amp;diff=19446</id>
		<title>Создание WMS сервера на базе GRASS GIS и Pyramid</title>
		<link rel="alternate" type="text/html" href="https://wiki.gis-lab.info/index.php?title=%D0%A1%D0%BE%D0%B7%D0%B4%D0%B0%D0%BD%D0%B8%D0%B5_WMS_%D1%81%D0%B5%D1%80%D0%B2%D0%B5%D1%80%D0%B0_%D0%BD%D0%B0_%D0%B1%D0%B0%D0%B7%D0%B5_GRASS_GIS_%D0%B8_Pyramid&amp;diff=19446"/>
		<updated>2014-05-05T04:25:24Z</updated>

		<summary type="html">&lt;p&gt;KolesovDmitry: /* Создание веб-приложения */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;В данной статье описывается простой пример создания [http://gis-lab.info/qa/ows.html WMS сервера] на базе геоинформационной системы GRASS. Доступ к данным организован при помощи [http://ru.wikipedia.org/wiki/Pyramid_%28%D0%BF%D1%80%D0%BE%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%BD%D1%8B%D0%B9_%D0%BA%D0%B0%D1%80%D0%BA%D0%B0%D1%81%29 фреймворка Pyramid].&lt;br /&gt;
&lt;br /&gt;
Данная статья является расширенным переводом статьи [http://www.webrian.ch/2013/12/grass-gis-web-map-service-with-pyramid.html GRASS GIS Web Map Service with Pyramid].&lt;br /&gt;
&lt;br /&gt;
== Общие сведения ==&lt;br /&gt;
Статья расчитана на читателя, который на базовом уровне знаком с геоинформационной системой GRASS и основами веб-разработки на языке программирования Python. В частности, читатель должен представлять, [http://gis-lab.info/qa/grass-external-scripting.html как происходит вызов команд GRASS на языке Python] и быть знакомым [http://docs.pylonsproject.org/projects/pyramid/en/latest/narr/introduction.html с принципами использования фреймворка Pyramid].&lt;br /&gt;
&lt;br /&gt;
В статье используется GRASS версии 6.4. Приведенный код применим и к более новым версиям GRASS, но, возможно, потребуется его незначительная правка.&lt;br /&gt;
&lt;br /&gt;
Исходный код модуля описанный в статье доступен по ссылке: [[Файл: Grass_wms.zip‎]].&lt;br /&gt;
&lt;br /&gt;
=== Архитектура системы ===&lt;br /&gt;
В разрабатываемой системе вся обработка геоданных будет возложена на GRASS, а обработка веб-запросов --- на Pyramid. &lt;br /&gt;
Основная часть WMS сервера, отвечающая за отрисовку геоданных --- модуль [http://grass.osgeo.org/grass64/manuals/d.mon.html d.mon], который будет использоваться совместно с [http://grass.osgeo.org/grass64/manuals/cairodriver.html графическим драйвером Cairo], позволяющим генерировать изображения в форматах PNG, BMP, PPM, PS, PDF и SVG.&lt;br /&gt;
&lt;br /&gt;
Для реализации сервера потребуется создать функции, служащие для:&lt;br /&gt;
&lt;br /&gt;
# Настройки путей к GRASS.&lt;br /&gt;
# Получения и анализа параметров запроса WMS.&lt;br /&gt;
# Отрисовки слоев по запросу клиента и сохранения результата в графический файл.&lt;br /&gt;
# Возвращения результата обработки запроса клиенту.&lt;br /&gt;
&lt;br /&gt;
Собственно к GRASS относятся первый и третий пункты, остальные --- обычные действия по обработке веб-запросов, которые реализуются при помощи Pyramid. Поэтому для простоты изложения и реализации объединим первый и третий пункты в виде одной функции, а второй и четвертый --- в виде другой.&lt;br /&gt;
&lt;br /&gt;
=== Зависимости и их установка ===&lt;br /&gt;
Для того, чтобы WMS сервер мог функционировать, требуется, чтобы на компьютере была установлена геоинформационная система [http://grass.osgeo.org/download/ GRASS] и [http://docs.pylonsproject.org/projects/pyramid/en/latest/narr/install.html Pyramid] (Pyramid рекомендуется устанавливать в [http://docs.pylonsproject.org/projects/pyramid/en/latest/narr/install.html#installing-the-virtualenv-package виртуальное окружение], чтобы не &amp;quot;мусорить&amp;quot; в основной системе).&lt;br /&gt;
&lt;br /&gt;
Установка этих систем обеспечит установку и настройку требуемых зависимостей.&lt;br /&gt;
&lt;br /&gt;
== Реализация ==&lt;br /&gt;
=== Настройка путей GRASS и обработка запроса клиента ===&lt;br /&gt;
Ниже приводится код функции, которая инициализирует GRASS, отрисовывает запрошенные пользователем слои и сохраняет полученное изображение во временном файле.&lt;br /&gt;
&lt;br /&gt;
На вход функция принимает &lt;br /&gt;
* список слоев (layers), которые требуется отрисовать;&lt;br /&gt;
* охват интересующего пользователя региона (bbox);&lt;br /&gt;
* ширину/высоту (width/height) изображения. &lt;br /&gt;
&lt;br /&gt;
На выходе функция возвращает имя файла, в котором будет сохранено запрошенное изображение.&lt;br /&gt;
&lt;br /&gt;
 def _grass_wms(layers=[], bbox=[], width=256, height=256):&lt;br /&gt;
    # Прописываем пути к GRASS. Исправить под свои нужды.&lt;br /&gt;
    gisdbase = &amp;quot;/home/useranme/GRASSDATA&amp;quot;&lt;br /&gt;
    location = &amp;quot;MSK_28407&amp;quot;&lt;br /&gt;
    mapset = &amp;quot;PERMANENT&amp;quot;&lt;br /&gt;
    gisbase = os.environ[&amp;quot;GISBASE&amp;quot;] = &amp;quot;/usr/lib/grass64&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
    # Добавляем путь модулям GRASS в системные пути&lt;br /&gt;
    sys.path.append(&amp;quot;%s/etc/python&amp;quot; % gisbase)&lt;br /&gt;
 &lt;br /&gt;
    # Импортируем библиотеки GRASS&lt;br /&gt;
    from grass.script import core as grass&lt;br /&gt;
    from grass.script import setup as gsetup&lt;br /&gt;
 &lt;br /&gt;
    # Инициализируем GRASS&lt;br /&gt;
    gsetup.init(gisbase, gisdbase,&lt;br /&gt;
               location, mapset)&lt;br /&gt;
 &lt;br /&gt;
    # Получаем список известных растровых и векторных слоев&lt;br /&gt;
    vector_layers = grass.list_strings(type = &amp;quot;vect&amp;quot;)&lt;br /&gt;
    raster_layers = grass.list_strings(type = &amp;quot;rast&amp;quot;)&lt;br /&gt;
 &lt;br /&gt;
    grass.run_command(&amp;quot;g.region&amp;quot;, w=bbox[0], s=bbox[1], e=bbox[2], n=bbox[3])&lt;br /&gt;
 &lt;br /&gt;
    # Создание временного файла&lt;br /&gt;
    tempfile = grass.tempfile()&lt;br /&gt;
    filename = &amp;quot;%s.png&amp;quot; % tempfile&lt;br /&gt;
 &lt;br /&gt;
    # Настраиваем параметры вывода&lt;br /&gt;
    os.environ[&amp;quot;GRASS_CAIROFILE&amp;quot;] = filename&lt;br /&gt;
    os.environ[&amp;quot;GRASS_WIDTH&amp;quot;] = width&lt;br /&gt;
    os.environ[&amp;quot;GRASS_HEIGHT&amp;quot;] = height&lt;br /&gt;
 &lt;br /&gt;
    # Отрисовка&lt;br /&gt;
    grass.run_command(&amp;quot;d.mon&amp;quot;, start=&amp;quot;cairo&amp;quot;)&lt;br /&gt;
 &lt;br /&gt;
    for layer in layers:&lt;br /&gt;
       if layer in raster_layers:&lt;br /&gt;
           grass.run_command(&amp;quot;d.rast&amp;quot;, map=layer, quiet=1)&lt;br /&gt;
       elif layer in vector_layers:&lt;br /&gt;
           grass.run_command(&amp;quot;d.vect&amp;quot;, map=layer, quiet=1, fcolor=&amp;quot;0:0:255&amp;quot;, color=None)&lt;br /&gt;
 &lt;br /&gt;
    grass.run_command(&amp;quot;d.mon&amp;quot;, stop=&amp;quot;cairo&amp;quot;)&lt;br /&gt;
 &lt;br /&gt;
    return filename&lt;br /&gt;
&lt;br /&gt;
Как видим, большая часть кода связана с первоначальной настройкой GRASS. Основной код по отрисовке запрошенных слоев использует команды GRASS и занимает всего пять строк:&lt;br /&gt;
  for layer in layers:&lt;br /&gt;
  ...&lt;br /&gt;
При этом все векторные слои будут отрисованы синим цветом, (см. параметры, передаваемые в &amp;lt;code&amp;gt;grass.run_command(&amp;quot;d.vect&amp;quot;, map=layer, quiet=1, fcolor=&amp;quot;0:0:255&amp;quot;, color=None)&amp;lt;/code&amp;gt;). Внешний вид слоя может быть изменен настройкой параметров команды [http://grass.osgeo.org/grass64/manuals/d.vect.html d.vect]. Например, данной командой можно назначить стиль отображения объекта в зависимости от его атрибутов или геометрических характеристик. &lt;br /&gt;
&lt;br /&gt;
Аналогично, растровые слои отображаются в цветовой схеме по умолчанию (или заранее назначенной пользователем вручную). При необходимости изменить стиль слоя при отрисовке следует воспользоваться командами, обрабатывающими цветовые схемы растровых карт, например [http://grass.osgeo.org/grass64/manuals/r.colors.html r.colors] или аналогичными модулями.&lt;br /&gt;
&lt;br /&gt;
Временный файл, в который сохраняется отрисованное изображение, в GRASS 6.4 задается следующими строками:&lt;br /&gt;
 # Настраиваем параметры вывода&lt;br /&gt;
 os.environ[&amp;quot;GRASS_CAIROFILE&amp;quot;] = filename&lt;br /&gt;
 os.environ[&amp;quot;GRASS_WIDTH&amp;quot;] = width&lt;br /&gt;
 os.environ[&amp;quot;GRASS_HEIGHT&amp;quot;] = height&lt;br /&gt;
Для GRASS седьмой версии можно немного упростить этот код, передавая параметры напрямую модулю &amp;lt;code&amp;gt;d.mon&amp;lt;/code&amp;gt;. Пример можно посмотреть в [http://www.webrian.ch/2013/12/grass-gis-web-map-service-with-pyramid.html исходной статье].&lt;br /&gt;
&lt;br /&gt;
=== Анализ запроса пользователя и возвращение результата ===&lt;br /&gt;
Анализ запроса пользователя производится в следующей функции:&lt;br /&gt;
 @view_config(route_name=&amp;quot;wms&amp;quot;)&lt;br /&gt;
 def wms_view(request):&lt;br /&gt;
 &lt;br /&gt;
    layers = request.params.get(&amp;quot;LAYERS&amp;quot;, &amp;quot;&amp;quot;).split(&amp;quot;,&amp;quot;)&lt;br /&gt;
    bbox = request.params.get(&amp;quot;BBOX&amp;quot;, &amp;quot;&amp;quot;).split(&amp;quot;,&amp;quot;)&lt;br /&gt;
    width = request.params.get(&amp;quot;WIDTH&amp;quot;)&lt;br /&gt;
    height = request.params.get(&amp;quot;HEIGHT&amp;quot;)&lt;br /&gt;
 &lt;br /&gt;
    try:&lt;br /&gt;
        filename = _grass_wms(layers=layers,&lt;br /&gt;
                              bbox=bbox,&lt;br /&gt;
                              width=width,&lt;br /&gt;
                              height=height)&lt;br /&gt;
        f = open(filename, &amp;quot;r+&amp;quot;)&lt;br /&gt;
        return Response(body=f.read(), content_type=&amp;quot;image/png&amp;quot;)&lt;br /&gt;
    except:&lt;br /&gt;
        pass&lt;br /&gt;
&lt;br /&gt;
Данная функция принимает запрос (request), в котором могут определяться:&lt;br /&gt;
* список слоев в запрашиваемом изображении (параметр LAYERS);&lt;br /&gt;
* охват области запрашиваемого изображения (параметр BBOX);&lt;br /&gt;
* высота и ширина запрашиваемого изображения (параметры HEIGHT и WIDTH).&lt;br /&gt;
&lt;br /&gt;
Полученные параметры анализируются и передаются в определенную выше функцию _grass_wms. Результат работы функции --- имя файла изображения --- считывается с диска и возвращается в качестве ответа на запрос.&lt;br /&gt;
&lt;br /&gt;
=== Создание веб-приложения ===&lt;br /&gt;
Еще одно действие --- создание простейшего веб-приложения, которое использует построенный WMS сервер. Воспользуемся библиотекой [http://gis-lab.info/qa/openlayers-begin.html OpenLayers] для отображения карты, возвращаемой сервером.&lt;br /&gt;
&lt;br /&gt;
Данный шаг является необязательным, но его удобно реализовать в целях отладки.&lt;br /&gt;
&lt;br /&gt;
Следующая функция создает веб-страницу с картой на базе слоев векторных слоев mo и io_15 из набора PERMANENT:&lt;br /&gt;
 @view_config(route_name=&amp;quot;index&amp;quot;)&lt;br /&gt;
 def index_view(request):&lt;br /&gt;
    body = &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
 &amp;lt;html xml:lang=&amp;quot;en&amp;quot;&lt;br /&gt;
 xmlns:tal=&amp;quot;http://xml.zope.org/namespaces/tal&amp;quot;&lt;br /&gt;
 xmlns=&amp;quot;http://www.w3.org/1999/xhtml&amp;quot;&amp;gt;&lt;br /&gt;
 &amp;lt;head&amp;gt;&lt;br /&gt;
  &amp;lt;title&amp;gt;GRASS GIS Web Map Service&amp;lt;/title&amp;gt;&lt;br /&gt;
  &amp;lt;script src=&amp;quot;http://openlayers.org/api/OpenLayers.js&amp;quot; type=&amp;quot;text/javascript&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;&lt;br /&gt;
  &amp;lt;script type=&amp;quot;text/javascript&amp;quot;&amp;gt;&lt;br /&gt;
    var map, wms_layer;&lt;br /&gt;
    function init(){&lt;br /&gt;
        var map = new OpenLayers.Map(&amp;quot;map-div&amp;quot;,{&lt;br /&gt;
            projection: &amp;quot;EPSG:28407&amp;quot;,&lt;br /&gt;
            maxExtent: new OpenLayers.Bounds(7361000, 6115000, 7435000, 6212000),&lt;br /&gt;
            numZoomLevels: 6,&lt;br /&gt;
        });&lt;br /&gt;
        var wms_layer = new OpenLayers.Layer.WMS(&amp;quot;GRASS WMS&amp;quot;, '/wms', {&lt;br /&gt;
            layers: &amp;quot;mo@PERMANENT,io_15@PERMANENT&amp;quot;&lt;br /&gt;
        },{&lt;br /&gt;
            singleTile: true,&lt;br /&gt;
        });&lt;br /&gt;
        map.addLayer(wms_layer);&lt;br /&gt;
        map.zoomToMaxExtent();&lt;br /&gt;
    }&lt;br /&gt;
  &amp;lt;/script&amp;gt;&lt;br /&gt;
 &amp;lt;/head&amp;gt;&lt;br /&gt;
 &amp;lt;body onload=&amp;quot;init()&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt; div id=&amp;quot;map-div&amp;quot; style=&amp;quot;height: 600px; width: 800px;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
 &amp;lt;/body&amp;gt;&lt;br /&gt;
 &amp;lt;/html&amp;gt;&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    return Response(body=body, content_type=&amp;quot;text/html&amp;quot;, status=200)&lt;br /&gt;
Понятно, что список доступных слоев (&amp;lt;code&amp;gt;layers: &amp;quot;mo@PERMANENT,io_15@PERMANENT&amp;quot;&amp;lt;/code&amp;gt;) и параметры области (&amp;lt;code&amp;gt;{projection: &amp;quot;EPSG:28407&amp;quot;, maxExtent: new OpenLayers.Bounds(7361000, 6115000, 7435000, 6212000), numZoomLevels: 6}&amp;lt;/code&amp;gt;) следует отредактировать под конкретный проект.&lt;br /&gt;
&lt;br /&gt;
=== Конфигурирование Pyramid ===&lt;br /&gt;
Для того, чтобы описанные выше функции можно было использовать, необходимо сконфигурировать Pyramid. Пример такой функции приведен ниже:&lt;br /&gt;
 def main():&lt;br /&gt;
    config = Configurator()&lt;br /&gt;
    config.add_static_view('static', 'static', cache_max_age=3600)&lt;br /&gt;
    config.add_route(&amp;quot;index&amp;quot;, '/')&lt;br /&gt;
    config.add_route(&amp;quot;wms&amp;quot;, '/wms')&lt;br /&gt;
    config.scan()&lt;br /&gt;
    app = config.make_wsgi_app()&lt;br /&gt;
    server = make_server('0.0.0.0', 8080, app)&lt;br /&gt;
    server.serve_forever()&lt;br /&gt;
&lt;br /&gt;
== Ограничения данной реализации ==&lt;br /&gt;
Рассмотренный пример демонстрирует принцип создания сервера WMS, потому в нем опущен ряд деталей, которые должны быть реализованы в реальной системе. Например, в рассмотренном варианте присутствуют следующие ограничения:&lt;br /&gt;
* Нет перепроецирования &amp;quot;на лету&amp;quot;. Т.е. построенный сервер WMS может возвращать слои только в той проекции, в которой хранятся данные GRASS.&lt;br /&gt;
* Реализация не является потокобезопасной. Например, при одновременном запросе данных из разных областей GRASS могут проявляться неожиданные побочные эффекты.&lt;br /&gt;
&lt;br /&gt;
== Ссылки по теме ==&lt;br /&gt;
* [http://www.webrian.ch/2013/12/grass-gis-web-map-service-with-pyramid.html GRASS GIS Web Map Service with Pyramid]&lt;br /&gt;
* [http://docs.pylonsproject.org/projects/pyramid/en/latest/narr/introduction.html Документация фреймворка Pyramid]&lt;br /&gt;
* [http://grass.osgeo.org/ GRASS GIS: The world's leading Free GIS software]&lt;/div&gt;</summary>
		<author><name>KolesovDmitry</name></author>
	</entry>
	<entry>
		<id>https://wiki.gis-lab.info/index.php?title=%D0%A1%D0%BE%D0%B7%D0%B4%D0%B0%D0%BD%D0%B8%D0%B5_WMS_%D1%81%D0%B5%D1%80%D0%B2%D0%B5%D1%80%D0%B0_%D0%BD%D0%B0_%D0%B1%D0%B0%D0%B7%D0%B5_GRASS_GIS_%D0%B8_Pyramid&amp;diff=19445</id>
		<title>Создание WMS сервера на базе GRASS GIS и Pyramid</title>
		<link rel="alternate" type="text/html" href="https://wiki.gis-lab.info/index.php?title=%D0%A1%D0%BE%D0%B7%D0%B4%D0%B0%D0%BD%D0%B8%D0%B5_WMS_%D1%81%D0%B5%D1%80%D0%B2%D0%B5%D1%80%D0%B0_%D0%BD%D0%B0_%D0%B1%D0%B0%D0%B7%D0%B5_GRASS_GIS_%D0%B8_Pyramid&amp;diff=19445"/>
		<updated>2014-05-05T04:17:13Z</updated>

		<summary type="html">&lt;p&gt;KolesovDmitry: /* Зависимости и их установка */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;В данной статье описывается простой пример создания [http://gis-lab.info/qa/ows.html WMS сервера] на базе геоинформационной системы GRASS. Доступ к данным организован при помощи [http://ru.wikipedia.org/wiki/Pyramid_%28%D0%BF%D1%80%D0%BE%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%BD%D1%8B%D0%B9_%D0%BA%D0%B0%D1%80%D0%BA%D0%B0%D1%81%29 фреймворка Pyramid].&lt;br /&gt;
&lt;br /&gt;
Данная статья является расширенным переводом статьи [http://www.webrian.ch/2013/12/grass-gis-web-map-service-with-pyramid.html GRASS GIS Web Map Service with Pyramid].&lt;br /&gt;
&lt;br /&gt;
== Общие сведения ==&lt;br /&gt;
Статья расчитана на читателя, который на базовом уровне знаком с геоинформационной системой GRASS и основами веб-разработки на языке программирования Python. В частности, читатель должен представлять, [http://gis-lab.info/qa/grass-external-scripting.html как происходит вызов команд GRASS на языке Python] и быть знакомым [http://docs.pylonsproject.org/projects/pyramid/en/latest/narr/introduction.html с принципами использования фреймворка Pyramid].&lt;br /&gt;
&lt;br /&gt;
В статье используется GRASS версии 6.4. Приведенный код применим и к более новым версиям GRASS, но, возможно, потребуется его незначительная правка.&lt;br /&gt;
&lt;br /&gt;
Исходный код модуля описанный в статье доступен по ссылке: [[Файл: Grass_wms.zip‎]].&lt;br /&gt;
&lt;br /&gt;
=== Архитектура системы ===&lt;br /&gt;
В разрабатываемой системе вся обработка геоданных будет возложена на GRASS, а обработка веб-запросов --- на Pyramid. &lt;br /&gt;
Основная часть WMS сервера, отвечающая за отрисовку геоданных --- модуль [http://grass.osgeo.org/grass64/manuals/d.mon.html d.mon], который будет использоваться совместно с [http://grass.osgeo.org/grass64/manuals/cairodriver.html графическим драйвером Cairo], позволяющим генерировать изображения в форматах PNG, BMP, PPM, PS, PDF и SVG.&lt;br /&gt;
&lt;br /&gt;
Для реализации сервера потребуется создать функции, служащие для:&lt;br /&gt;
&lt;br /&gt;
# Настройки путей к GRASS.&lt;br /&gt;
# Получения и анализа параметров запроса WMS.&lt;br /&gt;
# Отрисовки слоев по запросу клиента и сохранения результата в графический файл.&lt;br /&gt;
# Возвращения результата обработки запроса клиенту.&lt;br /&gt;
&lt;br /&gt;
Собственно к GRASS относятся первый и третий пункты, остальные --- обычные действия по обработке веб-запросов, которые реализуются при помощи Pyramid. Поэтому для простоты изложения и реализации объединим первый и третий пункты в виде одной функции, а второй и четвертый --- в виде другой.&lt;br /&gt;
&lt;br /&gt;
=== Зависимости и их установка ===&lt;br /&gt;
Для того, чтобы WMS сервер мог функционировать, требуется, чтобы на компьютере была установлена геоинформационная система [http://grass.osgeo.org/download/ GRASS] и [http://docs.pylonsproject.org/projects/pyramid/en/latest/narr/install.html Pyramid] (Pyramid рекомендуется устанавливать в [http://docs.pylonsproject.org/projects/pyramid/en/latest/narr/install.html#installing-the-virtualenv-package виртуальное окружение], чтобы не &amp;quot;мусорить&amp;quot; в основной системе).&lt;br /&gt;
&lt;br /&gt;
Установка этих систем обеспечит установку и настройку требуемых зависимостей.&lt;br /&gt;
&lt;br /&gt;
== Реализация ==&lt;br /&gt;
=== Настройка путей GRASS и обработка запроса клиента ===&lt;br /&gt;
Ниже приводится код функции, которая инициализирует GRASS, отрисовывает запрошенные пользователем слои и сохраняет полученное изображение во временном файле.&lt;br /&gt;
&lt;br /&gt;
На вход функция принимает &lt;br /&gt;
* список слоев (layers), которые требуется отрисовать;&lt;br /&gt;
* охват интересующего пользователя региона (bbox);&lt;br /&gt;
* ширину/высоту (width/height) изображения. &lt;br /&gt;
&lt;br /&gt;
На выходе функция возвращает имя файла, в котором будет сохранено запрошенное изображение.&lt;br /&gt;
&lt;br /&gt;
 def _grass_wms(layers=[], bbox=[], width=256, height=256):&lt;br /&gt;
    # Прописываем пути к GRASS. Исправить под свои нужды.&lt;br /&gt;
    gisdbase = &amp;quot;/home/useranme/GRASSDATA&amp;quot;&lt;br /&gt;
    location = &amp;quot;MSK_28407&amp;quot;&lt;br /&gt;
    mapset = &amp;quot;PERMANENT&amp;quot;&lt;br /&gt;
    gisbase = os.environ[&amp;quot;GISBASE&amp;quot;] = &amp;quot;/usr/lib/grass64&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
    # Добавляем путь модулям GRASS в системные пути&lt;br /&gt;
    sys.path.append(&amp;quot;%s/etc/python&amp;quot; % gisbase)&lt;br /&gt;
 &lt;br /&gt;
    # Импортируем библиотеки GRASS&lt;br /&gt;
    from grass.script import core as grass&lt;br /&gt;
    from grass.script import setup as gsetup&lt;br /&gt;
 &lt;br /&gt;
    # Инициализируем GRASS&lt;br /&gt;
    gsetup.init(gisbase, gisdbase,&lt;br /&gt;
               location, mapset)&lt;br /&gt;
 &lt;br /&gt;
    # Получаем список известных растровых и векторных слоев&lt;br /&gt;
    vector_layers = grass.list_strings(type = &amp;quot;vect&amp;quot;)&lt;br /&gt;
    raster_layers = grass.list_strings(type = &amp;quot;rast&amp;quot;)&lt;br /&gt;
 &lt;br /&gt;
    grass.run_command(&amp;quot;g.region&amp;quot;, w=bbox[0], s=bbox[1], e=bbox[2], n=bbox[3])&lt;br /&gt;
 &lt;br /&gt;
    # Создание временного файла&lt;br /&gt;
    tempfile = grass.tempfile()&lt;br /&gt;
    filename = &amp;quot;%s.png&amp;quot; % tempfile&lt;br /&gt;
 &lt;br /&gt;
    # Настраиваем параметры вывода&lt;br /&gt;
    os.environ[&amp;quot;GRASS_CAIROFILE&amp;quot;] = filename&lt;br /&gt;
    os.environ[&amp;quot;GRASS_WIDTH&amp;quot;] = width&lt;br /&gt;
    os.environ[&amp;quot;GRASS_HEIGHT&amp;quot;] = height&lt;br /&gt;
 &lt;br /&gt;
    # Отрисовка&lt;br /&gt;
    grass.run_command(&amp;quot;d.mon&amp;quot;, start=&amp;quot;cairo&amp;quot;)&lt;br /&gt;
 &lt;br /&gt;
    for layer in layers:&lt;br /&gt;
       if layer in raster_layers:&lt;br /&gt;
           grass.run_command(&amp;quot;d.rast&amp;quot;, map=layer, quiet=1)&lt;br /&gt;
       elif layer in vector_layers:&lt;br /&gt;
           grass.run_command(&amp;quot;d.vect&amp;quot;, map=layer, quiet=1, fcolor=&amp;quot;0:0:255&amp;quot;, color=None)&lt;br /&gt;
 &lt;br /&gt;
    grass.run_command(&amp;quot;d.mon&amp;quot;, stop=&amp;quot;cairo&amp;quot;)&lt;br /&gt;
 &lt;br /&gt;
    return filename&lt;br /&gt;
&lt;br /&gt;
Как видим, большая часть кода связана с первоначальной настройкой GRASS. Основной код по отрисовке запрошенных слоев использует команды GRASS и занимает всего пять строк:&lt;br /&gt;
  for layer in layers:&lt;br /&gt;
  ...&lt;br /&gt;
При этом все векторные слои будут отрисованы синим цветом, (см. параметры, передаваемые в &amp;lt;code&amp;gt;grass.run_command(&amp;quot;d.vect&amp;quot;, map=layer, quiet=1, fcolor=&amp;quot;0:0:255&amp;quot;, color=None)&amp;lt;/code&amp;gt;). Внешний вид слоя может быть изменен настройкой параметров команды [http://grass.osgeo.org/grass64/manuals/d.vect.html d.vect]. Например, данной командой можно назначить стиль отображения объекта в зависимости от его атрибутов или геометрических характеристик. &lt;br /&gt;
&lt;br /&gt;
Аналогично, растровые слои отображаются в цветовой схеме по умолчанию (или заранее назначенной пользователем вручную). При необходимости изменить стиль слоя при отрисовке следует воспользоваться командами, обрабатывающими цветовые схемы растровых карт, например [http://grass.osgeo.org/grass64/manuals/r.colors.html r.colors] или аналогичными модулями.&lt;br /&gt;
&lt;br /&gt;
Временный файл, в который сохраняется отрисованное изображение, в GRASS 6.4 задается следующими строками:&lt;br /&gt;
 # Настраиваем параметры вывода&lt;br /&gt;
 os.environ[&amp;quot;GRASS_CAIROFILE&amp;quot;] = filename&lt;br /&gt;
 os.environ[&amp;quot;GRASS_WIDTH&amp;quot;] = width&lt;br /&gt;
 os.environ[&amp;quot;GRASS_HEIGHT&amp;quot;] = height&lt;br /&gt;
Для GRASS седьмой версии можно немного упростить этот код, передавая параметры напрямую модулю &amp;lt;code&amp;gt;d.mon&amp;lt;/code&amp;gt;. Пример можно посмотреть в [http://www.webrian.ch/2013/12/grass-gis-web-map-service-with-pyramid.html исходной статье].&lt;br /&gt;
&lt;br /&gt;
=== Анализ запроса пользователя и возвращение результата ===&lt;br /&gt;
Анализ запроса пользователя производится в следующей функции:&lt;br /&gt;
 @view_config(route_name=&amp;quot;wms&amp;quot;)&lt;br /&gt;
 def wms_view(request):&lt;br /&gt;
 &lt;br /&gt;
    layers = request.params.get(&amp;quot;LAYERS&amp;quot;, &amp;quot;&amp;quot;).split(&amp;quot;,&amp;quot;)&lt;br /&gt;
    bbox = request.params.get(&amp;quot;BBOX&amp;quot;, &amp;quot;&amp;quot;).split(&amp;quot;,&amp;quot;)&lt;br /&gt;
    width = request.params.get(&amp;quot;WIDTH&amp;quot;)&lt;br /&gt;
    height = request.params.get(&amp;quot;HEIGHT&amp;quot;)&lt;br /&gt;
 &lt;br /&gt;
    try:&lt;br /&gt;
        filename = _grass_wms(layers=layers,&lt;br /&gt;
                              bbox=bbox,&lt;br /&gt;
                              width=width,&lt;br /&gt;
                              height=height)&lt;br /&gt;
        f = open(filename, &amp;quot;r+&amp;quot;)&lt;br /&gt;
        return Response(body=f.read(), content_type=&amp;quot;image/png&amp;quot;)&lt;br /&gt;
    except:&lt;br /&gt;
        pass&lt;br /&gt;
&lt;br /&gt;
Данная функция принимает запрос (request), в котором могут определяться:&lt;br /&gt;
* список слоев в запрашиваемом изображении (параметр LAYERS);&lt;br /&gt;
* охват области запрашиваемого изображения (параметр BBOX);&lt;br /&gt;
* высота и ширина запрашиваемого изображения (параметры HEIGHT и WIDTH).&lt;br /&gt;
&lt;br /&gt;
Полученные параметры анализируются и передаются в определенную выше функцию _grass_wms. Результат работы функции --- имя файла изображения --- считывается с диска и возвращается в качестве ответа на запрос.&lt;br /&gt;
&lt;br /&gt;
=== Создание веб-приложения ===&lt;br /&gt;
Еще одно действие --- создание простейшего веб-приложения, которое использует построенный WMS сервер. Воспользуемся библиотекой [http://gis-lab.info/qa/openlayers-begin.html OpenLayers] для отображения карты, возвращаемой сервером.&lt;br /&gt;
&lt;br /&gt;
Данный шаг является необязательным, но его удобно реализовать в целях отладки.&lt;br /&gt;
&lt;br /&gt;
Следующая функция создает веб-страницу с картой на базе слоев векторных слоев mo и io_15:&lt;br /&gt;
 @view_config(route_name=&amp;quot;index&amp;quot;)&lt;br /&gt;
 def index_view(request):&lt;br /&gt;
    body = &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
 &amp;lt;html xml:lang=&amp;quot;en&amp;quot;&lt;br /&gt;
 xmlns:tal=&amp;quot;http://xml.zope.org/namespaces/tal&amp;quot;&lt;br /&gt;
 xmlns=&amp;quot;http://www.w3.org/1999/xhtml&amp;quot;&amp;gt;&lt;br /&gt;
 &amp;lt;head&amp;gt;&lt;br /&gt;
  &amp;lt;title&amp;gt;GRASS GIS Web Map Service&amp;lt;/title&amp;gt;&lt;br /&gt;
  &amp;lt;script src=&amp;quot;http://openlayers.org/api/OpenLayers.js&amp;quot; type=&amp;quot;text/javascript&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;&lt;br /&gt;
  &amp;lt;script type=&amp;quot;text/javascript&amp;quot;&amp;gt;&lt;br /&gt;
    var map, wms_layer;&lt;br /&gt;
    function init(){&lt;br /&gt;
        var map = new OpenLayers.Map(&amp;quot;map-div&amp;quot;,{&lt;br /&gt;
            projection: &amp;quot;EPSG:28407&amp;quot;,&lt;br /&gt;
            maxExtent: new OpenLayers.Bounds(7361000, 6115000, 7435000, 6212000),&lt;br /&gt;
            numZoomLevels: 6,&lt;br /&gt;
        });&lt;br /&gt;
        var wms_layer = new OpenLayers.Layer.WMS(&amp;quot;GRASS WMS&amp;quot;, '/wms', {&lt;br /&gt;
            layers: &amp;quot;mo,io_15&amp;quot;&lt;br /&gt;
        },{&lt;br /&gt;
            singleTile: true,&lt;br /&gt;
        });&lt;br /&gt;
        map.addLayer(wms_layer);&lt;br /&gt;
        map.zoomToMaxExtent();&lt;br /&gt;
    }&lt;br /&gt;
  &amp;lt;/script&amp;gt;&lt;br /&gt;
 &amp;lt;/head&amp;gt;&lt;br /&gt;
 &amp;lt;body onload=&amp;quot;init()&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt; div id=&amp;quot;map-div&amp;quot; style=&amp;quot;height: 600px; width: 800px;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
 &amp;lt;/body&amp;gt;&lt;br /&gt;
 &amp;lt;/html&amp;gt;&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    return Response(body=body, content_type=&amp;quot;text/html&amp;quot;, status=200)&lt;br /&gt;
&lt;br /&gt;
=== Конфигурирование Pyramid ===&lt;br /&gt;
Для того, чтобы описанные выше функции можно было использовать, необходимо сконфигурировать Pyramid. Пример такой функции приведен ниже:&lt;br /&gt;
 def main():&lt;br /&gt;
    config = Configurator()&lt;br /&gt;
    config.add_static_view('static', 'static', cache_max_age=3600)&lt;br /&gt;
    config.add_route(&amp;quot;index&amp;quot;, '/')&lt;br /&gt;
    config.add_route(&amp;quot;wms&amp;quot;, '/wms')&lt;br /&gt;
    config.scan()&lt;br /&gt;
    app = config.make_wsgi_app()&lt;br /&gt;
    server = make_server('0.0.0.0', 8080, app)&lt;br /&gt;
    server.serve_forever()&lt;br /&gt;
&lt;br /&gt;
== Ограничения данной реализации ==&lt;br /&gt;
Рассмотренный пример демонстрирует принцип создания сервера WMS, потому в нем опущен ряд деталей, которые должны быть реализованы в реальной системе. Например, в рассмотренном варианте присутствуют следующие ограничения:&lt;br /&gt;
* Нет перепроецирования &amp;quot;на лету&amp;quot;. Т.е. построенный сервер WMS может возвращать слои только в той проекции, в которой хранятся данные GRASS.&lt;br /&gt;
* Реализация не является потокобезопасной. Например, при одновременном запросе данных из разных областей GRASS могут проявляться неожиданные побочные эффекты.&lt;br /&gt;
&lt;br /&gt;
== Ссылки по теме ==&lt;br /&gt;
* [http://www.webrian.ch/2013/12/grass-gis-web-map-service-with-pyramid.html GRASS GIS Web Map Service with Pyramid]&lt;br /&gt;
* [http://docs.pylonsproject.org/projects/pyramid/en/latest/narr/introduction.html Документация фреймворка Pyramid]&lt;br /&gt;
* [http://grass.osgeo.org/ GRASS GIS: The world's leading Free GIS software]&lt;/div&gt;</summary>
		<author><name>KolesovDmitry</name></author>
	</entry>
	<entry>
		<id>https://wiki.gis-lab.info/index.php?title=%D0%A1%D0%BE%D0%B7%D0%B4%D0%B0%D0%BD%D0%B8%D0%B5_WMS_%D1%81%D0%B5%D1%80%D0%B2%D0%B5%D1%80%D0%B0_%D0%BD%D0%B0_%D0%B1%D0%B0%D0%B7%D0%B5_GRASS_GIS_%D0%B8_Pyramid&amp;diff=19444</id>
		<title>Создание WMS сервера на базе GRASS GIS и Pyramid</title>
		<link rel="alternate" type="text/html" href="https://wiki.gis-lab.info/index.php?title=%D0%A1%D0%BE%D0%B7%D0%B4%D0%B0%D0%BD%D0%B8%D0%B5_WMS_%D1%81%D0%B5%D1%80%D0%B2%D0%B5%D1%80%D0%B0_%D0%BD%D0%B0_%D0%B1%D0%B0%D0%B7%D0%B5_GRASS_GIS_%D0%B8_Pyramid&amp;diff=19444"/>
		<updated>2014-05-05T04:15:33Z</updated>

		<summary type="html">&lt;p&gt;KolesovDmitry: /* Архитектура системы */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;В данной статье описывается простой пример создания [http://gis-lab.info/qa/ows.html WMS сервера] на базе геоинформационной системы GRASS. Доступ к данным организован при помощи [http://ru.wikipedia.org/wiki/Pyramid_%28%D0%BF%D1%80%D0%BE%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%BD%D1%8B%D0%B9_%D0%BA%D0%B0%D1%80%D0%BA%D0%B0%D1%81%29 фреймворка Pyramid].&lt;br /&gt;
&lt;br /&gt;
Данная статья является расширенным переводом статьи [http://www.webrian.ch/2013/12/grass-gis-web-map-service-with-pyramid.html GRASS GIS Web Map Service with Pyramid].&lt;br /&gt;
&lt;br /&gt;
== Общие сведения ==&lt;br /&gt;
Статья расчитана на читателя, который на базовом уровне знаком с геоинформационной системой GRASS и основами веб-разработки на языке программирования Python. В частности, читатель должен представлять, [http://gis-lab.info/qa/grass-external-scripting.html как происходит вызов команд GRASS на языке Python] и быть знакомым [http://docs.pylonsproject.org/projects/pyramid/en/latest/narr/introduction.html с принципами использования фреймворка Pyramid].&lt;br /&gt;
&lt;br /&gt;
В статье используется GRASS версии 6.4. Приведенный код применим и к более новым версиям GRASS, но, возможно, потребуется его незначительная правка.&lt;br /&gt;
&lt;br /&gt;
Исходный код модуля описанный в статье доступен по ссылке: [[Файл: Grass_wms.zip‎]].&lt;br /&gt;
&lt;br /&gt;
=== Архитектура системы ===&lt;br /&gt;
В разрабатываемой системе вся обработка геоданных будет возложена на GRASS, а обработка веб-запросов --- на Pyramid. &lt;br /&gt;
Основная часть WMS сервера, отвечающая за отрисовку геоданных --- модуль [http://grass.osgeo.org/grass64/manuals/d.mon.html d.mon], который будет использоваться совместно с [http://grass.osgeo.org/grass64/manuals/cairodriver.html графическим драйвером Cairo], позволяющим генерировать изображения в форматах PNG, BMP, PPM, PS, PDF и SVG.&lt;br /&gt;
&lt;br /&gt;
Для реализации сервера потребуется создать функции, служащие для:&lt;br /&gt;
&lt;br /&gt;
# Настройки путей к GRASS.&lt;br /&gt;
# Получения и анализа параметров запроса WMS.&lt;br /&gt;
# Отрисовки слоев по запросу клиента и сохранения результата в графический файл.&lt;br /&gt;
# Возвращения результата обработки запроса клиенту.&lt;br /&gt;
&lt;br /&gt;
Собственно к GRASS относятся первый и третий пункты, остальные --- обычные действия по обработке веб-запросов, которые реализуются при помощи Pyramid. Поэтому для простоты изложения и реализации объединим первый и третий пункты в виде одной функции, а второй и четвертый --- в виде другой.&lt;br /&gt;
&lt;br /&gt;
=== Зависимости и их установка ===&lt;br /&gt;
Для того, чтобы WMS сервер мог функционировать, требуется, на компьютере была установлена геоинформационная система [http://grass.osgeo.org/download/ GRASS] и [http://docs.pylonsproject.org/projects/pyramid/en/latest/narr/install.html Pyramid] (Pyramid рекомендуется устанавливать в [http://docs.pylonsproject.org/projects/pyramid/en/latest/narr/install.html#installing-the-virtualenv-package виртуальное окружение], чтобы не &amp;quot;мусорить&amp;quot; в основной системе).&lt;br /&gt;
&lt;br /&gt;
Установка этих систем обеспечит установку и настройку требуемых зависимостей, поэтому никаких дополнительных .&lt;br /&gt;
&lt;br /&gt;
== Реализация ==&lt;br /&gt;
=== Настройка путей GRASS и обработка запроса клиента ===&lt;br /&gt;
Ниже приводится код функции, которая инициализирует GRASS, отрисовывает запрошенные пользователем слои и сохраняет полученное изображение во временном файле.&lt;br /&gt;
&lt;br /&gt;
На вход функция принимает &lt;br /&gt;
* список слоев (layers), которые требуется отрисовать;&lt;br /&gt;
* охват интересующего пользователя региона (bbox);&lt;br /&gt;
* ширину/высоту (width/height) изображения. &lt;br /&gt;
&lt;br /&gt;
На выходе функция возвращает имя файла, в котором будет сохранено запрошенное изображение.&lt;br /&gt;
&lt;br /&gt;
 def _grass_wms(layers=[], bbox=[], width=256, height=256):&lt;br /&gt;
    # Прописываем пути к GRASS. Исправить под свои нужды.&lt;br /&gt;
    gisdbase = &amp;quot;/home/useranme/GRASSDATA&amp;quot;&lt;br /&gt;
    location = &amp;quot;MSK_28407&amp;quot;&lt;br /&gt;
    mapset = &amp;quot;PERMANENT&amp;quot;&lt;br /&gt;
    gisbase = os.environ[&amp;quot;GISBASE&amp;quot;] = &amp;quot;/usr/lib/grass64&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
    # Добавляем путь модулям GRASS в системные пути&lt;br /&gt;
    sys.path.append(&amp;quot;%s/etc/python&amp;quot; % gisbase)&lt;br /&gt;
 &lt;br /&gt;
    # Импортируем библиотеки GRASS&lt;br /&gt;
    from grass.script import core as grass&lt;br /&gt;
    from grass.script import setup as gsetup&lt;br /&gt;
 &lt;br /&gt;
    # Инициализируем GRASS&lt;br /&gt;
    gsetup.init(gisbase, gisdbase,&lt;br /&gt;
               location, mapset)&lt;br /&gt;
 &lt;br /&gt;
    # Получаем список известных растровых и векторных слоев&lt;br /&gt;
    vector_layers = grass.list_strings(type = &amp;quot;vect&amp;quot;)&lt;br /&gt;
    raster_layers = grass.list_strings(type = &amp;quot;rast&amp;quot;)&lt;br /&gt;
 &lt;br /&gt;
    grass.run_command(&amp;quot;g.region&amp;quot;, w=bbox[0], s=bbox[1], e=bbox[2], n=bbox[3])&lt;br /&gt;
 &lt;br /&gt;
    # Создание временного файла&lt;br /&gt;
    tempfile = grass.tempfile()&lt;br /&gt;
    filename = &amp;quot;%s.png&amp;quot; % tempfile&lt;br /&gt;
 &lt;br /&gt;
    # Настраиваем параметры вывода&lt;br /&gt;
    os.environ[&amp;quot;GRASS_CAIROFILE&amp;quot;] = filename&lt;br /&gt;
    os.environ[&amp;quot;GRASS_WIDTH&amp;quot;] = width&lt;br /&gt;
    os.environ[&amp;quot;GRASS_HEIGHT&amp;quot;] = height&lt;br /&gt;
 &lt;br /&gt;
    # Отрисовка&lt;br /&gt;
    grass.run_command(&amp;quot;d.mon&amp;quot;, start=&amp;quot;cairo&amp;quot;)&lt;br /&gt;
 &lt;br /&gt;
    for layer in layers:&lt;br /&gt;
       if layer in raster_layers:&lt;br /&gt;
           grass.run_command(&amp;quot;d.rast&amp;quot;, map=layer, quiet=1)&lt;br /&gt;
       elif layer in vector_layers:&lt;br /&gt;
           grass.run_command(&amp;quot;d.vect&amp;quot;, map=layer, quiet=1, fcolor=&amp;quot;0:0:255&amp;quot;, color=None)&lt;br /&gt;
 &lt;br /&gt;
    grass.run_command(&amp;quot;d.mon&amp;quot;, stop=&amp;quot;cairo&amp;quot;)&lt;br /&gt;
 &lt;br /&gt;
    return filename&lt;br /&gt;
&lt;br /&gt;
Как видим, большая часть кода связана с первоначальной настройкой GRASS. Основной код по отрисовке запрошенных слоев использует команды GRASS и занимает всего пять строк:&lt;br /&gt;
  for layer in layers:&lt;br /&gt;
  ...&lt;br /&gt;
При этом все векторные слои будут отрисованы синим цветом, (см. параметры, передаваемые в &amp;lt;code&amp;gt;grass.run_command(&amp;quot;d.vect&amp;quot;, map=layer, quiet=1, fcolor=&amp;quot;0:0:255&amp;quot;, color=None)&amp;lt;/code&amp;gt;). Внешний вид слоя может быть изменен настройкой параметров команды [http://grass.osgeo.org/grass64/manuals/d.vect.html d.vect]. Например, данной командой можно назначить стиль отображения объекта в зависимости от его атрибутов или геометрических характеристик. &lt;br /&gt;
&lt;br /&gt;
Аналогично, растровые слои отображаются в цветовой схеме по умолчанию (или заранее назначенной пользователем вручную). При необходимости изменить стиль слоя при отрисовке следует воспользоваться командами, обрабатывающими цветовые схемы растровых карт, например [http://grass.osgeo.org/grass64/manuals/r.colors.html r.colors] или аналогичными модулями.&lt;br /&gt;
&lt;br /&gt;
Временный файл, в который сохраняется отрисованное изображение, в GRASS 6.4 задается следующими строками:&lt;br /&gt;
 # Настраиваем параметры вывода&lt;br /&gt;
 os.environ[&amp;quot;GRASS_CAIROFILE&amp;quot;] = filename&lt;br /&gt;
 os.environ[&amp;quot;GRASS_WIDTH&amp;quot;] = width&lt;br /&gt;
 os.environ[&amp;quot;GRASS_HEIGHT&amp;quot;] = height&lt;br /&gt;
Для GRASS седьмой версии можно немного упростить этот код, передавая параметры напрямую модулю &amp;lt;code&amp;gt;d.mon&amp;lt;/code&amp;gt;. Пример можно посмотреть в [http://www.webrian.ch/2013/12/grass-gis-web-map-service-with-pyramid.html исходной статье].&lt;br /&gt;
&lt;br /&gt;
=== Анализ запроса пользователя и возвращение результата ===&lt;br /&gt;
Анализ запроса пользователя производится в следующей функции:&lt;br /&gt;
 @view_config(route_name=&amp;quot;wms&amp;quot;)&lt;br /&gt;
 def wms_view(request):&lt;br /&gt;
 &lt;br /&gt;
    layers = request.params.get(&amp;quot;LAYERS&amp;quot;, &amp;quot;&amp;quot;).split(&amp;quot;,&amp;quot;)&lt;br /&gt;
    bbox = request.params.get(&amp;quot;BBOX&amp;quot;, &amp;quot;&amp;quot;).split(&amp;quot;,&amp;quot;)&lt;br /&gt;
    width = request.params.get(&amp;quot;WIDTH&amp;quot;)&lt;br /&gt;
    height = request.params.get(&amp;quot;HEIGHT&amp;quot;)&lt;br /&gt;
 &lt;br /&gt;
    try:&lt;br /&gt;
        filename = _grass_wms(layers=layers,&lt;br /&gt;
                              bbox=bbox,&lt;br /&gt;
                              width=width,&lt;br /&gt;
                              height=height)&lt;br /&gt;
        f = open(filename, &amp;quot;r+&amp;quot;)&lt;br /&gt;
        return Response(body=f.read(), content_type=&amp;quot;image/png&amp;quot;)&lt;br /&gt;
    except:&lt;br /&gt;
        pass&lt;br /&gt;
&lt;br /&gt;
Данная функция принимает запрос (request), в котором могут определяться:&lt;br /&gt;
* список слоев в запрашиваемом изображении (параметр LAYERS);&lt;br /&gt;
* охват области запрашиваемого изображения (параметр BBOX);&lt;br /&gt;
* высота и ширина запрашиваемого изображения (параметры HEIGHT и WIDTH).&lt;br /&gt;
&lt;br /&gt;
Полученные параметры анализируются и передаются в определенную выше функцию _grass_wms. Результат работы функции --- имя файла изображения --- считывается с диска и возвращается в качестве ответа на запрос.&lt;br /&gt;
&lt;br /&gt;
=== Создание веб-приложения ===&lt;br /&gt;
Еще одно действие --- создание простейшего веб-приложения, которое использует построенный WMS сервер. Воспользуемся библиотекой [http://gis-lab.info/qa/openlayers-begin.html OpenLayers] для отображения карты, возвращаемой сервером.&lt;br /&gt;
&lt;br /&gt;
Данный шаг является необязательным, но его удобно реализовать в целях отладки.&lt;br /&gt;
&lt;br /&gt;
Следующая функция создает веб-страницу с картой на базе слоев векторных слоев mo и io_15:&lt;br /&gt;
 @view_config(route_name=&amp;quot;index&amp;quot;)&lt;br /&gt;
 def index_view(request):&lt;br /&gt;
    body = &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
 &amp;lt;html xml:lang=&amp;quot;en&amp;quot;&lt;br /&gt;
 xmlns:tal=&amp;quot;http://xml.zope.org/namespaces/tal&amp;quot;&lt;br /&gt;
 xmlns=&amp;quot;http://www.w3.org/1999/xhtml&amp;quot;&amp;gt;&lt;br /&gt;
 &amp;lt;head&amp;gt;&lt;br /&gt;
  &amp;lt;title&amp;gt;GRASS GIS Web Map Service&amp;lt;/title&amp;gt;&lt;br /&gt;
  &amp;lt;script src=&amp;quot;http://openlayers.org/api/OpenLayers.js&amp;quot; type=&amp;quot;text/javascript&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;&lt;br /&gt;
  &amp;lt;script type=&amp;quot;text/javascript&amp;quot;&amp;gt;&lt;br /&gt;
    var map, wms_layer;&lt;br /&gt;
    function init(){&lt;br /&gt;
        var map = new OpenLayers.Map(&amp;quot;map-div&amp;quot;,{&lt;br /&gt;
            projection: &amp;quot;EPSG:28407&amp;quot;,&lt;br /&gt;
            maxExtent: new OpenLayers.Bounds(7361000, 6115000, 7435000, 6212000),&lt;br /&gt;
            numZoomLevels: 6,&lt;br /&gt;
        });&lt;br /&gt;
        var wms_layer = new OpenLayers.Layer.WMS(&amp;quot;GRASS WMS&amp;quot;, '/wms', {&lt;br /&gt;
            layers: &amp;quot;mo,io_15&amp;quot;&lt;br /&gt;
        },{&lt;br /&gt;
            singleTile: true,&lt;br /&gt;
        });&lt;br /&gt;
        map.addLayer(wms_layer);&lt;br /&gt;
        map.zoomToMaxExtent();&lt;br /&gt;
    }&lt;br /&gt;
  &amp;lt;/script&amp;gt;&lt;br /&gt;
 &amp;lt;/head&amp;gt;&lt;br /&gt;
 &amp;lt;body onload=&amp;quot;init()&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt; div id=&amp;quot;map-div&amp;quot; style=&amp;quot;height: 600px; width: 800px;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
 &amp;lt;/body&amp;gt;&lt;br /&gt;
 &amp;lt;/html&amp;gt;&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    return Response(body=body, content_type=&amp;quot;text/html&amp;quot;, status=200)&lt;br /&gt;
&lt;br /&gt;
=== Конфигурирование Pyramid ===&lt;br /&gt;
Для того, чтобы описанные выше функции можно было использовать, необходимо сконфигурировать Pyramid. Пример такой функции приведен ниже:&lt;br /&gt;
 def main():&lt;br /&gt;
    config = Configurator()&lt;br /&gt;
    config.add_static_view('static', 'static', cache_max_age=3600)&lt;br /&gt;
    config.add_route(&amp;quot;index&amp;quot;, '/')&lt;br /&gt;
    config.add_route(&amp;quot;wms&amp;quot;, '/wms')&lt;br /&gt;
    config.scan()&lt;br /&gt;
    app = config.make_wsgi_app()&lt;br /&gt;
    server = make_server('0.0.0.0', 8080, app)&lt;br /&gt;
    server.serve_forever()&lt;br /&gt;
&lt;br /&gt;
== Ограничения данной реализации ==&lt;br /&gt;
Рассмотренный пример демонстрирует принцип создания сервера WMS, потому в нем опущен ряд деталей, которые должны быть реализованы в реальной системе. Например, в рассмотренном варианте присутствуют следующие ограничения:&lt;br /&gt;
* Нет перепроецирования &amp;quot;на лету&amp;quot;. Т.е. построенный сервер WMS может возвращать слои только в той проекции, в которой хранятся данные GRASS.&lt;br /&gt;
* Реализация не является потокобезопасной. Например, при одновременном запросе данных из разных областей GRASS могут проявляться неожиданные побочные эффекты.&lt;br /&gt;
&lt;br /&gt;
== Ссылки по теме ==&lt;br /&gt;
* [http://www.webrian.ch/2013/12/grass-gis-web-map-service-with-pyramid.html GRASS GIS Web Map Service with Pyramid]&lt;br /&gt;
* [http://docs.pylonsproject.org/projects/pyramid/en/latest/narr/introduction.html Документация фреймворка Pyramid]&lt;br /&gt;
* [http://grass.osgeo.org/ GRASS GIS: The world's leading Free GIS software]&lt;/div&gt;</summary>
		<author><name>KolesovDmitry</name></author>
	</entry>
	<entry>
		<id>https://wiki.gis-lab.info/index.php?title=%D0%A1%D0%BE%D0%B7%D0%B4%D0%B0%D0%BD%D0%B8%D0%B5_WMS_%D1%81%D0%B5%D1%80%D0%B2%D0%B5%D1%80%D0%B0_%D0%BD%D0%B0_%D0%B1%D0%B0%D0%B7%D0%B5_GRASS_GIS_%D0%B8_Pyramid&amp;diff=19435</id>
		<title>Создание WMS сервера на базе GRASS GIS и Pyramid</title>
		<link rel="alternate" type="text/html" href="https://wiki.gis-lab.info/index.php?title=%D0%A1%D0%BE%D0%B7%D0%B4%D0%B0%D0%BD%D0%B8%D0%B5_WMS_%D1%81%D0%B5%D1%80%D0%B2%D0%B5%D1%80%D0%B0_%D0%BD%D0%B0_%D0%B1%D0%B0%D0%B7%D0%B5_GRASS_GIS_%D0%B8_Pyramid&amp;diff=19435"/>
		<updated>2014-05-04T17:38:31Z</updated>

		<summary type="html">&lt;p&gt;KolesovDmitry: /* Архитектура системы */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;В данной статье описывается простой пример создания [http://gis-lab.info/qa/ows.html WMS сервера] на базе геоинформационной системы GRASS. Доступ к данным организован при помощи [http://ru.wikipedia.org/wiki/Pyramid_%28%D0%BF%D1%80%D0%BE%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%BD%D1%8B%D0%B9_%D0%BA%D0%B0%D1%80%D0%BA%D0%B0%D1%81%29 фреймворка Pyramid].&lt;br /&gt;
&lt;br /&gt;
Данная статья является расширенным переводом статьи [http://www.webrian.ch/2013/12/grass-gis-web-map-service-with-pyramid.html GRASS GIS Web Map Service with Pyramid].&lt;br /&gt;
&lt;br /&gt;
== Общие сведения ==&lt;br /&gt;
Статья расчитана на читателя, который на базовом уровне знаком с геоинформационной системой GRASS и основами веб-разработки на языке программирования Python. В частности, читатель должен представлять, [http://gis-lab.info/qa/grass-external-scripting.html как происходит вызов команд GRASS на языке Python] и быть знакомым [http://docs.pylonsproject.org/projects/pyramid/en/latest/narr/introduction.html с принципами использования фреймворка Pyramid].&lt;br /&gt;
&lt;br /&gt;
В статье используется GRASS версии 6.4. Приведенный код применим и к более новым версиям GRASS, но, возможно, потребуется его незначительная правка.&lt;br /&gt;
&lt;br /&gt;
Исходный код модуля описанный в статье доступен по ссылке: [[Файл: Grass_wms.zip‎]].&lt;br /&gt;
&lt;br /&gt;
=== Архитектура системы ===&lt;br /&gt;
В разрабатываемой системе вся обработка геоданных будет возложена на GRASS, а обработка веб-запросов --- на Pyramid. &lt;br /&gt;
Основная часть WMS сервера, отвечающая за отрисовку геоданных --- модуль [http://grass.osgeo.org/grass64/manuals/d.mon.html d.mon], который будет использоваться совместно с [http://grass.osgeo.org/grass64/manuals/cairodriver.html графическим драйвером Cairo], позволяющим генерировать изображения в форматах PNG, BMP, PPM, PS, PDF и SVG.&lt;br /&gt;
&lt;br /&gt;
Для реализации сервера потребуется создать функции, служащие для:&lt;br /&gt;
&lt;br /&gt;
# Настройки путей к GRASS.&lt;br /&gt;
# Получения и анализа параметров запроса WMS.&lt;br /&gt;
# Отрисовки слоев по запросу клиента и сохранения результата в графический файл.&lt;br /&gt;
# Возвращения результата обработки запроса клиенту.&lt;br /&gt;
&lt;br /&gt;
Собственно к GRASS относятся первый и третий пункты, остальные --- обычные действия по обработке веб-запросов, которые реализуются при помощи Pyramid. Поэтому для простоты изложения и реализации объединим первый и третий пункты в виде одной функции, а второй и четвертый --- в виде другой.&lt;br /&gt;
&lt;br /&gt;
== Реализация ==&lt;br /&gt;
=== Настройка путей GRASS и обработка запроса клиента ===&lt;br /&gt;
Ниже приводится код функции, которая инициализирует GRASS, отрисовывает запрошенные пользователем слои и сохраняет полученное изображение во временном файле.&lt;br /&gt;
&lt;br /&gt;
На вход функция принимает &lt;br /&gt;
* список слоев (layers), которые требуется отрисовать;&lt;br /&gt;
* охват интересующего пользователя региона (bbox);&lt;br /&gt;
* ширину/высоту (width/height) изображения. &lt;br /&gt;
&lt;br /&gt;
На выходе функция возвращает имя файла, в котором будет сохранено запрошенное изображение.&lt;br /&gt;
&lt;br /&gt;
 def _grass_wms(layers=[], bbox=[], width=256, height=256):&lt;br /&gt;
    # Прописываем пути к GRASS. Исправить под свои нужды.&lt;br /&gt;
    gisdbase = &amp;quot;/home/useranme/GRASSDATA&amp;quot;&lt;br /&gt;
    location = &amp;quot;MSK_28407&amp;quot;&lt;br /&gt;
    mapset = &amp;quot;PERMANENT&amp;quot;&lt;br /&gt;
    gisbase = os.environ[&amp;quot;GISBASE&amp;quot;] = &amp;quot;/usr/lib/grass64&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
    # Добавляем путь модулям GRASS в системные пути&lt;br /&gt;
    sys.path.append(&amp;quot;%s/etc/python&amp;quot; % gisbase)&lt;br /&gt;
 &lt;br /&gt;
    # Импортируем библиотеки GRASS&lt;br /&gt;
    from grass.script import core as grass&lt;br /&gt;
    from grass.script import setup as gsetup&lt;br /&gt;
 &lt;br /&gt;
    # Инициализируем GRASS&lt;br /&gt;
    gsetup.init(gisbase, gisdbase,&lt;br /&gt;
               location, mapset)&lt;br /&gt;
 &lt;br /&gt;
    # Получаем список известных растровых и векторных слоев&lt;br /&gt;
    vector_layers = grass.list_strings(type = &amp;quot;vect&amp;quot;)&lt;br /&gt;
    raster_layers = grass.list_strings(type = &amp;quot;rast&amp;quot;)&lt;br /&gt;
 &lt;br /&gt;
    grass.run_command(&amp;quot;g.region&amp;quot;, w=bbox[0], s=bbox[1], e=bbox[2], n=bbox[3])&lt;br /&gt;
 &lt;br /&gt;
    # Создание временного файла&lt;br /&gt;
    tempfile = grass.tempfile()&lt;br /&gt;
    filename = &amp;quot;%s.png&amp;quot; % tempfile&lt;br /&gt;
 &lt;br /&gt;
    # Настраиваем параметры вывода&lt;br /&gt;
    os.environ[&amp;quot;GRASS_CAIROFILE&amp;quot;] = filename&lt;br /&gt;
    os.environ[&amp;quot;GRASS_WIDTH&amp;quot;] = width&lt;br /&gt;
    os.environ[&amp;quot;GRASS_HEIGHT&amp;quot;] = height&lt;br /&gt;
 &lt;br /&gt;
    # Отрисовка&lt;br /&gt;
    grass.run_command(&amp;quot;d.mon&amp;quot;, start=&amp;quot;cairo&amp;quot;)&lt;br /&gt;
 &lt;br /&gt;
    for layer in layers:&lt;br /&gt;
       if layer in raster_layers:&lt;br /&gt;
           grass.run_command(&amp;quot;d.rast&amp;quot;, map=layer, quiet=1)&lt;br /&gt;
       elif layer in vector_layers:&lt;br /&gt;
           grass.run_command(&amp;quot;d.vect&amp;quot;, map=layer, quiet=1, fcolor=&amp;quot;0:0:255&amp;quot;, color=None)&lt;br /&gt;
 &lt;br /&gt;
    grass.run_command(&amp;quot;d.mon&amp;quot;, stop=&amp;quot;cairo&amp;quot;)&lt;br /&gt;
 &lt;br /&gt;
    return filename&lt;br /&gt;
&lt;br /&gt;
Как видим, большая часть кода связана с первоначальной настройкой GRASS. Основной код по отрисовке запрошенных слоев использует команды GRASS и занимает всего пять строк:&lt;br /&gt;
  for layer in layers:&lt;br /&gt;
  ...&lt;br /&gt;
При этом все векторные слои будут отрисованы синим цветом, (см. параметры, передаваемые в &amp;lt;code&amp;gt;grass.run_command(&amp;quot;d.vect&amp;quot;, map=layer, quiet=1, fcolor=&amp;quot;0:0:255&amp;quot;, color=None)&amp;lt;/code&amp;gt;). Внешний вид слоя может быть изменен настройкой параметров команды [http://grass.osgeo.org/grass64/manuals/d.vect.html d.vect]. Например, данной командой можно назначить стиль отображения объекта в зависимости от его атрибутов или геометрических характеристик. &lt;br /&gt;
&lt;br /&gt;
Аналогично, растровые слои отображаются в цветовой схеме по умолчанию (или заранее назначенной пользователем вручную). При необходимости изменить стиль слоя при отрисовке следует воспользоваться командами, обрабатывающими цветовые схемы растровых карт, например [http://grass.osgeo.org/grass64/manuals/r.colors.html r.colors] или аналогичными модулями.&lt;br /&gt;
&lt;br /&gt;
Временный файл, в который сохраняется отрисованное изображение, в GRASS 6.4 задается следующими строками:&lt;br /&gt;
 # Настраиваем параметры вывода&lt;br /&gt;
 os.environ[&amp;quot;GRASS_CAIROFILE&amp;quot;] = filename&lt;br /&gt;
 os.environ[&amp;quot;GRASS_WIDTH&amp;quot;] = width&lt;br /&gt;
 os.environ[&amp;quot;GRASS_HEIGHT&amp;quot;] = height&lt;br /&gt;
Для GRASS седьмой версии можно немного упростить этот код, передавая параметры напрямую модулю &amp;lt;code&amp;gt;d.mon&amp;lt;/code&amp;gt;. Пример можно посмотреть в [http://www.webrian.ch/2013/12/grass-gis-web-map-service-with-pyramid.html исходной статье].&lt;br /&gt;
&lt;br /&gt;
=== Анализ запроса пользователя и возвращение результата ===&lt;br /&gt;
Анализ запроса пользователя производится в следующей функции:&lt;br /&gt;
 @view_config(route_name=&amp;quot;wms&amp;quot;)&lt;br /&gt;
 def wms_view(request):&lt;br /&gt;
 &lt;br /&gt;
    layers = request.params.get(&amp;quot;LAYERS&amp;quot;, &amp;quot;&amp;quot;).split(&amp;quot;,&amp;quot;)&lt;br /&gt;
    bbox = request.params.get(&amp;quot;BBOX&amp;quot;, &amp;quot;&amp;quot;).split(&amp;quot;,&amp;quot;)&lt;br /&gt;
    width = request.params.get(&amp;quot;WIDTH&amp;quot;)&lt;br /&gt;
    height = request.params.get(&amp;quot;HEIGHT&amp;quot;)&lt;br /&gt;
 &lt;br /&gt;
    try:&lt;br /&gt;
        filename = _grass_wms(layers=layers,&lt;br /&gt;
                              bbox=bbox,&lt;br /&gt;
                              width=width,&lt;br /&gt;
                              height=height)&lt;br /&gt;
        f = open(filename, &amp;quot;r+&amp;quot;)&lt;br /&gt;
        return Response(body=f.read(), content_type=&amp;quot;image/png&amp;quot;)&lt;br /&gt;
    except:&lt;br /&gt;
        pass&lt;br /&gt;
&lt;br /&gt;
Данная функция принимает запрос (request), в котором могут определяться:&lt;br /&gt;
* список слоев в запрашиваемом изображении (параметр LAYERS);&lt;br /&gt;
* охват области запрашиваемого изображения (параметр BBOX);&lt;br /&gt;
* высота и ширина запрашиваемого изображения (параметры HEIGHT и WIDTH).&lt;br /&gt;
&lt;br /&gt;
Полученные параметры анализируются и передаются в определенную выше функцию _grass_wms. Результат работы функции --- имя файла изображения --- считывается с диска и возвращается в качестве ответа на запрос.&lt;br /&gt;
&lt;br /&gt;
=== Создание веб-приложения ===&lt;br /&gt;
Еще одно действие --- создание простейшего веб-приложения, которое использует построенный WMS сервер. Воспользуемся библиотекой [http://gis-lab.info/qa/openlayers-begin.html OpenLayers] для отображения карты, возвращаемой сервером.&lt;br /&gt;
&lt;br /&gt;
Данный шаг является необязательным, но его удобно реализовать в целях отладки.&lt;br /&gt;
&lt;br /&gt;
Следующая функция создает веб-страницу с картой на базе слоев векторных слоев mo и io_15:&lt;br /&gt;
 @view_config(route_name=&amp;quot;index&amp;quot;)&lt;br /&gt;
 def index_view(request):&lt;br /&gt;
    body = &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
 &amp;lt;html xml:lang=&amp;quot;en&amp;quot;&lt;br /&gt;
 xmlns:tal=&amp;quot;http://xml.zope.org/namespaces/tal&amp;quot;&lt;br /&gt;
 xmlns=&amp;quot;http://www.w3.org/1999/xhtml&amp;quot;&amp;gt;&lt;br /&gt;
 &amp;lt;head&amp;gt;&lt;br /&gt;
  &amp;lt;title&amp;gt;GRASS GIS Web Map Service&amp;lt;/title&amp;gt;&lt;br /&gt;
  &amp;lt;script src=&amp;quot;http://openlayers.org/api/OpenLayers.js&amp;quot; type=&amp;quot;text/javascript&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;&lt;br /&gt;
  &amp;lt;script type=&amp;quot;text/javascript&amp;quot;&amp;gt;&lt;br /&gt;
    var map, wms_layer;&lt;br /&gt;
    function init(){&lt;br /&gt;
        var map = new OpenLayers.Map(&amp;quot;map-div&amp;quot;,{&lt;br /&gt;
            projection: &amp;quot;EPSG:28407&amp;quot;,&lt;br /&gt;
            maxExtent: new OpenLayers.Bounds(7361000, 6115000, 7435000, 6212000),&lt;br /&gt;
            numZoomLevels: 6,&lt;br /&gt;
        });&lt;br /&gt;
        var wms_layer = new OpenLayers.Layer.WMS(&amp;quot;GRASS WMS&amp;quot;, '/wms', {&lt;br /&gt;
            layers: &amp;quot;mo,io_15&amp;quot;&lt;br /&gt;
        },{&lt;br /&gt;
            singleTile: true,&lt;br /&gt;
        });&lt;br /&gt;
        map.addLayer(wms_layer);&lt;br /&gt;
        map.zoomToMaxExtent();&lt;br /&gt;
    }&lt;br /&gt;
  &amp;lt;/script&amp;gt;&lt;br /&gt;
 &amp;lt;/head&amp;gt;&lt;br /&gt;
 &amp;lt;body onload=&amp;quot;init()&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt; div id=&amp;quot;map-div&amp;quot; style=&amp;quot;height: 600px; width: 800px;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
 &amp;lt;/body&amp;gt;&lt;br /&gt;
 &amp;lt;/html&amp;gt;&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    return Response(body=body, content_type=&amp;quot;text/html&amp;quot;, status=200)&lt;br /&gt;
&lt;br /&gt;
=== Конфигурирование Pyramid ===&lt;br /&gt;
Для того, чтобы описанные выше функции можно было использовать, необходимо сконфигурировать Pyramid. Пример такой функции приведен ниже:&lt;br /&gt;
 def main():&lt;br /&gt;
    config = Configurator()&lt;br /&gt;
    config.add_static_view('static', 'static', cache_max_age=3600)&lt;br /&gt;
    config.add_route(&amp;quot;index&amp;quot;, '/')&lt;br /&gt;
    config.add_route(&amp;quot;wms&amp;quot;, '/wms')&lt;br /&gt;
    config.scan()&lt;br /&gt;
    app = config.make_wsgi_app()&lt;br /&gt;
    server = make_server('0.0.0.0', 8080, app)&lt;br /&gt;
    server.serve_forever()&lt;br /&gt;
&lt;br /&gt;
== Ограничения данной реализации ==&lt;br /&gt;
Рассмотренный пример демонстрирует принцип создания WMS сервера, потому в нем опущен ряд деталей, которые должны быть реализованы в реальной системе. Например, в рассмотренном варианте присутствуют следующие ограничения:&lt;br /&gt;
* Нет перпроецирования &amp;quot;на лету&amp;quot;. Т.е. построенный WMS сервер может возвращать слои только в той проекции, в которой хранятся данные GRASS.&lt;br /&gt;
* Реализация не является потокобезопасной. Например, при одновременном запросе данных из разных областей GRASS могут проявляться неожиданные побочные эффекты.&lt;br /&gt;
&lt;br /&gt;
== Ссылки по теме ==&lt;br /&gt;
* [http://www.webrian.ch/2013/12/grass-gis-web-map-service-with-pyramid.html GRASS GIS Web Map Service with Pyramid]&lt;br /&gt;
* [http://docs.pylonsproject.org/projects/pyramid/en/latest/narr/introduction.html Документация фреймворка Pyramid]&lt;br /&gt;
* [http://grass.osgeo.org/ GRASS GIS: The world's leading Free GIS software]&lt;/div&gt;</summary>
		<author><name>KolesovDmitry</name></author>
	</entry>
	<entry>
		<id>https://wiki.gis-lab.info/index.php?title=%D0%A1%D0%BE%D0%B7%D0%B4%D0%B0%D0%BD%D0%B8%D0%B5_WMS_%D1%81%D0%B5%D1%80%D0%B2%D0%B5%D1%80%D0%B0_%D0%BD%D0%B0_%D0%B1%D0%B0%D0%B7%D0%B5_GRASS_GIS_%D0%B8_Pyramid&amp;diff=19434</id>
		<title>Создание WMS сервера на базе GRASS GIS и Pyramid</title>
		<link rel="alternate" type="text/html" href="https://wiki.gis-lab.info/index.php?title=%D0%A1%D0%BE%D0%B7%D0%B4%D0%B0%D0%BD%D0%B8%D0%B5_WMS_%D1%81%D0%B5%D1%80%D0%B2%D0%B5%D1%80%D0%B0_%D0%BD%D0%B0_%D0%B1%D0%B0%D0%B7%D0%B5_GRASS_GIS_%D0%B8_Pyramid&amp;diff=19434"/>
		<updated>2014-05-04T17:38:17Z</updated>

		<summary type="html">&lt;p&gt;KolesovDmitry: /* Общие сведения */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;В данной статье описывается простой пример создания [http://gis-lab.info/qa/ows.html WMS сервера] на базе геоинформационной системы GRASS. Доступ к данным организован при помощи [http://ru.wikipedia.org/wiki/Pyramid_%28%D0%BF%D1%80%D0%BE%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%BD%D1%8B%D0%B9_%D0%BA%D0%B0%D1%80%D0%BA%D0%B0%D1%81%29 фреймворка Pyramid].&lt;br /&gt;
&lt;br /&gt;
Данная статья является расширенным переводом статьи [http://www.webrian.ch/2013/12/grass-gis-web-map-service-with-pyramid.html GRASS GIS Web Map Service with Pyramid].&lt;br /&gt;
&lt;br /&gt;
== Общие сведения ==&lt;br /&gt;
Статья расчитана на читателя, который на базовом уровне знаком с геоинформационной системой GRASS и основами веб-разработки на языке программирования Python. В частности, читатель должен представлять, [http://gis-lab.info/qa/grass-external-scripting.html как происходит вызов команд GRASS на языке Python] и быть знакомым [http://docs.pylonsproject.org/projects/pyramid/en/latest/narr/introduction.html с принципами использования фреймворка Pyramid].&lt;br /&gt;
&lt;br /&gt;
В статье используется GRASS версии 6.4. Приведенный код применим и к более новым версиям GRASS, но, возможно, потребуется его незначительная правка.&lt;br /&gt;
&lt;br /&gt;
Исходный код модуля описанный в статье доступен по ссылке: [[Файл: Grass_wms.zip‎]].&lt;br /&gt;
&lt;br /&gt;
=== Архитектура системы ===&lt;br /&gt;
В разрабатываемой системе вся обработка геоданных будет возложена на GRASS, а обработка веб-запросов --- на Pyramid. &lt;br /&gt;
Основная часть WMS сервера, отвечающая за отрисовку геоданных --- модуль [http://grass.osgeo.org/grass64/manuals/d.mon.html d.mon], который будет использоваться совместно с [http://grass.osgeo.org/grass64/manuals/cairodriver.html графическим драйвером Cairo], позволяющим генерировать изображения в форматах PNG, BMP, PPM, PS, PDF и SVG.&lt;br /&gt;
&lt;br /&gt;
Для реализации сервера потребуется создать функции, служащие для:&lt;br /&gt;
&lt;br /&gt;
# Настройки путей к GRASS.&lt;br /&gt;
# Получения и анализа параметров запроса WMS.&lt;br /&gt;
# Отрисовки слоев по запросу клиента и сохранения результата в графический файл.&lt;br /&gt;
# Возвращения результата обработки запроса клиенту.&lt;br /&gt;
&lt;br /&gt;
Собственно к GRASS относятся первый и третий пункты, остальные --- обычные действия по обработке веб-запросов, которые реализуются при помощи Pyramid. Поэтому для простоты изложения и реализации объединим первый и третий пункты в виде одной функции, а второй и четверый --- в виде другой.&lt;br /&gt;
&lt;br /&gt;
== Реализация ==&lt;br /&gt;
=== Настройка путей GRASS и обработка запроса клиента ===&lt;br /&gt;
Ниже приводится код функции, которая инициализирует GRASS, отрисовывает запрошенные пользователем слои и сохраняет полученное изображение во временном файле.&lt;br /&gt;
&lt;br /&gt;
На вход функция принимает &lt;br /&gt;
* список слоев (layers), которые требуется отрисовать;&lt;br /&gt;
* охват интересующего пользователя региона (bbox);&lt;br /&gt;
* ширину/высоту (width/height) изображения. &lt;br /&gt;
&lt;br /&gt;
На выходе функция возвращает имя файла, в котором будет сохранено запрошенное изображение.&lt;br /&gt;
&lt;br /&gt;
 def _grass_wms(layers=[], bbox=[], width=256, height=256):&lt;br /&gt;
    # Прописываем пути к GRASS. Исправить под свои нужды.&lt;br /&gt;
    gisdbase = &amp;quot;/home/useranme/GRASSDATA&amp;quot;&lt;br /&gt;
    location = &amp;quot;MSK_28407&amp;quot;&lt;br /&gt;
    mapset = &amp;quot;PERMANENT&amp;quot;&lt;br /&gt;
    gisbase = os.environ[&amp;quot;GISBASE&amp;quot;] = &amp;quot;/usr/lib/grass64&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
    # Добавляем путь модулям GRASS в системные пути&lt;br /&gt;
    sys.path.append(&amp;quot;%s/etc/python&amp;quot; % gisbase)&lt;br /&gt;
 &lt;br /&gt;
    # Импортируем библиотеки GRASS&lt;br /&gt;
    from grass.script import core as grass&lt;br /&gt;
    from grass.script import setup as gsetup&lt;br /&gt;
 &lt;br /&gt;
    # Инициализируем GRASS&lt;br /&gt;
    gsetup.init(gisbase, gisdbase,&lt;br /&gt;
               location, mapset)&lt;br /&gt;
 &lt;br /&gt;
    # Получаем список известных растровых и векторных слоев&lt;br /&gt;
    vector_layers = grass.list_strings(type = &amp;quot;vect&amp;quot;)&lt;br /&gt;
    raster_layers = grass.list_strings(type = &amp;quot;rast&amp;quot;)&lt;br /&gt;
 &lt;br /&gt;
    grass.run_command(&amp;quot;g.region&amp;quot;, w=bbox[0], s=bbox[1], e=bbox[2], n=bbox[3])&lt;br /&gt;
 &lt;br /&gt;
    # Создание временного файла&lt;br /&gt;
    tempfile = grass.tempfile()&lt;br /&gt;
    filename = &amp;quot;%s.png&amp;quot; % tempfile&lt;br /&gt;
 &lt;br /&gt;
    # Настраиваем параметры вывода&lt;br /&gt;
    os.environ[&amp;quot;GRASS_CAIROFILE&amp;quot;] = filename&lt;br /&gt;
    os.environ[&amp;quot;GRASS_WIDTH&amp;quot;] = width&lt;br /&gt;
    os.environ[&amp;quot;GRASS_HEIGHT&amp;quot;] = height&lt;br /&gt;
 &lt;br /&gt;
    # Отрисовка&lt;br /&gt;
    grass.run_command(&amp;quot;d.mon&amp;quot;, start=&amp;quot;cairo&amp;quot;)&lt;br /&gt;
 &lt;br /&gt;
    for layer in layers:&lt;br /&gt;
       if layer in raster_layers:&lt;br /&gt;
           grass.run_command(&amp;quot;d.rast&amp;quot;, map=layer, quiet=1)&lt;br /&gt;
       elif layer in vector_layers:&lt;br /&gt;
           grass.run_command(&amp;quot;d.vect&amp;quot;, map=layer, quiet=1, fcolor=&amp;quot;0:0:255&amp;quot;, color=None)&lt;br /&gt;
 &lt;br /&gt;
    grass.run_command(&amp;quot;d.mon&amp;quot;, stop=&amp;quot;cairo&amp;quot;)&lt;br /&gt;
 &lt;br /&gt;
    return filename&lt;br /&gt;
&lt;br /&gt;
Как видим, большая часть кода связана с первоначальной настройкой GRASS. Основной код по отрисовке запрошенных слоев использует команды GRASS и занимает всего пять строк:&lt;br /&gt;
  for layer in layers:&lt;br /&gt;
  ...&lt;br /&gt;
При этом все векторные слои будут отрисованы синим цветом, (см. параметры, передаваемые в &amp;lt;code&amp;gt;grass.run_command(&amp;quot;d.vect&amp;quot;, map=layer, quiet=1, fcolor=&amp;quot;0:0:255&amp;quot;, color=None)&amp;lt;/code&amp;gt;). Внешний вид слоя может быть изменен настройкой параметров команды [http://grass.osgeo.org/grass64/manuals/d.vect.html d.vect]. Например, данной командой можно назначить стиль отображения объекта в зависимости от его атрибутов или геометрических характеристик. &lt;br /&gt;
&lt;br /&gt;
Аналогично, растровые слои отображаются в цветовой схеме по умолчанию (или заранее назначенной пользователем вручную). При необходимости изменить стиль слоя при отрисовке следует воспользоваться командами, обрабатывающими цветовые схемы растровых карт, например [http://grass.osgeo.org/grass64/manuals/r.colors.html r.colors] или аналогичными модулями.&lt;br /&gt;
&lt;br /&gt;
Временный файл, в который сохраняется отрисованное изображение, в GRASS 6.4 задается следующими строками:&lt;br /&gt;
 # Настраиваем параметры вывода&lt;br /&gt;
 os.environ[&amp;quot;GRASS_CAIROFILE&amp;quot;] = filename&lt;br /&gt;
 os.environ[&amp;quot;GRASS_WIDTH&amp;quot;] = width&lt;br /&gt;
 os.environ[&amp;quot;GRASS_HEIGHT&amp;quot;] = height&lt;br /&gt;
Для GRASS седьмой версии можно немного упростить этот код, передавая параметры напрямую модулю &amp;lt;code&amp;gt;d.mon&amp;lt;/code&amp;gt;. Пример можно посмотреть в [http://www.webrian.ch/2013/12/grass-gis-web-map-service-with-pyramid.html исходной статье].&lt;br /&gt;
&lt;br /&gt;
=== Анализ запроса пользователя и возвращение результата ===&lt;br /&gt;
Анализ запроса пользователя производится в следующей функции:&lt;br /&gt;
 @view_config(route_name=&amp;quot;wms&amp;quot;)&lt;br /&gt;
 def wms_view(request):&lt;br /&gt;
 &lt;br /&gt;
    layers = request.params.get(&amp;quot;LAYERS&amp;quot;, &amp;quot;&amp;quot;).split(&amp;quot;,&amp;quot;)&lt;br /&gt;
    bbox = request.params.get(&amp;quot;BBOX&amp;quot;, &amp;quot;&amp;quot;).split(&amp;quot;,&amp;quot;)&lt;br /&gt;
    width = request.params.get(&amp;quot;WIDTH&amp;quot;)&lt;br /&gt;
    height = request.params.get(&amp;quot;HEIGHT&amp;quot;)&lt;br /&gt;
 &lt;br /&gt;
    try:&lt;br /&gt;
        filename = _grass_wms(layers=layers,&lt;br /&gt;
                              bbox=bbox,&lt;br /&gt;
                              width=width,&lt;br /&gt;
                              height=height)&lt;br /&gt;
        f = open(filename, &amp;quot;r+&amp;quot;)&lt;br /&gt;
        return Response(body=f.read(), content_type=&amp;quot;image/png&amp;quot;)&lt;br /&gt;
    except:&lt;br /&gt;
        pass&lt;br /&gt;
&lt;br /&gt;
Данная функция принимает запрос (request), в котором могут определяться:&lt;br /&gt;
* список слоев в запрашиваемом изображении (параметр LAYERS);&lt;br /&gt;
* охват области запрашиваемого изображения (параметр BBOX);&lt;br /&gt;
* высота и ширина запрашиваемого изображения (параметры HEIGHT и WIDTH).&lt;br /&gt;
&lt;br /&gt;
Полученные параметры анализируются и передаются в определенную выше функцию _grass_wms. Результат работы функции --- имя файла изображения --- считывается с диска и возвращается в качестве ответа на запрос.&lt;br /&gt;
&lt;br /&gt;
=== Создание веб-приложения ===&lt;br /&gt;
Еще одно действие --- создание простейшего веб-приложения, которое использует построенный WMS сервер. Воспользуемся библиотекой [http://gis-lab.info/qa/openlayers-begin.html OpenLayers] для отображения карты, возвращаемой сервером.&lt;br /&gt;
&lt;br /&gt;
Данный шаг является необязательным, но его удобно реализовать в целях отладки.&lt;br /&gt;
&lt;br /&gt;
Следующая функция создает веб-страницу с картой на базе слоев векторных слоев mo и io_15:&lt;br /&gt;
 @view_config(route_name=&amp;quot;index&amp;quot;)&lt;br /&gt;
 def index_view(request):&lt;br /&gt;
    body = &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
 &amp;lt;html xml:lang=&amp;quot;en&amp;quot;&lt;br /&gt;
 xmlns:tal=&amp;quot;http://xml.zope.org/namespaces/tal&amp;quot;&lt;br /&gt;
 xmlns=&amp;quot;http://www.w3.org/1999/xhtml&amp;quot;&amp;gt;&lt;br /&gt;
 &amp;lt;head&amp;gt;&lt;br /&gt;
  &amp;lt;title&amp;gt;GRASS GIS Web Map Service&amp;lt;/title&amp;gt;&lt;br /&gt;
  &amp;lt;script src=&amp;quot;http://openlayers.org/api/OpenLayers.js&amp;quot; type=&amp;quot;text/javascript&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;&lt;br /&gt;
  &amp;lt;script type=&amp;quot;text/javascript&amp;quot;&amp;gt;&lt;br /&gt;
    var map, wms_layer;&lt;br /&gt;
    function init(){&lt;br /&gt;
        var map = new OpenLayers.Map(&amp;quot;map-div&amp;quot;,{&lt;br /&gt;
            projection: &amp;quot;EPSG:28407&amp;quot;,&lt;br /&gt;
            maxExtent: new OpenLayers.Bounds(7361000, 6115000, 7435000, 6212000),&lt;br /&gt;
            numZoomLevels: 6,&lt;br /&gt;
        });&lt;br /&gt;
        var wms_layer = new OpenLayers.Layer.WMS(&amp;quot;GRASS WMS&amp;quot;, '/wms', {&lt;br /&gt;
            layers: &amp;quot;mo,io_15&amp;quot;&lt;br /&gt;
        },{&lt;br /&gt;
            singleTile: true,&lt;br /&gt;
        });&lt;br /&gt;
        map.addLayer(wms_layer);&lt;br /&gt;
        map.zoomToMaxExtent();&lt;br /&gt;
    }&lt;br /&gt;
  &amp;lt;/script&amp;gt;&lt;br /&gt;
 &amp;lt;/head&amp;gt;&lt;br /&gt;
 &amp;lt;body onload=&amp;quot;init()&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt; div id=&amp;quot;map-div&amp;quot; style=&amp;quot;height: 600px; width: 800px;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
 &amp;lt;/body&amp;gt;&lt;br /&gt;
 &amp;lt;/html&amp;gt;&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    return Response(body=body, content_type=&amp;quot;text/html&amp;quot;, status=200)&lt;br /&gt;
&lt;br /&gt;
=== Конфигурирование Pyramid ===&lt;br /&gt;
Для того, чтобы описанные выше функции можно было использовать, необходимо сконфигурировать Pyramid. Пример такой функции приведен ниже:&lt;br /&gt;
 def main():&lt;br /&gt;
    config = Configurator()&lt;br /&gt;
    config.add_static_view('static', 'static', cache_max_age=3600)&lt;br /&gt;
    config.add_route(&amp;quot;index&amp;quot;, '/')&lt;br /&gt;
    config.add_route(&amp;quot;wms&amp;quot;, '/wms')&lt;br /&gt;
    config.scan()&lt;br /&gt;
    app = config.make_wsgi_app()&lt;br /&gt;
    server = make_server('0.0.0.0', 8080, app)&lt;br /&gt;
    server.serve_forever()&lt;br /&gt;
&lt;br /&gt;
== Ограничения данной реализации ==&lt;br /&gt;
Рассмотренный пример демонстрирует принцип создания WMS сервера, потому в нем опущен ряд деталей, которые должны быть реализованы в реальной системе. Например, в рассмотренном варианте присутствуют следующие ограничения:&lt;br /&gt;
* Нет перпроецирования &amp;quot;на лету&amp;quot;. Т.е. построенный WMS сервер может возвращать слои только в той проекции, в которой хранятся данные GRASS.&lt;br /&gt;
* Реализация не является потокобезопасной. Например, при одновременном запросе данных из разных областей GRASS могут проявляться неожиданные побочные эффекты.&lt;br /&gt;
&lt;br /&gt;
== Ссылки по теме ==&lt;br /&gt;
* [http://www.webrian.ch/2013/12/grass-gis-web-map-service-with-pyramid.html GRASS GIS Web Map Service with Pyramid]&lt;br /&gt;
* [http://docs.pylonsproject.org/projects/pyramid/en/latest/narr/introduction.html Документация фреймворка Pyramid]&lt;br /&gt;
* [http://grass.osgeo.org/ GRASS GIS: The world's leading Free GIS software]&lt;/div&gt;</summary>
		<author><name>KolesovDmitry</name></author>
	</entry>
</feed>