<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://grasswiki.osgeo.org/w/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=%E2%9A%A0%EF%B8%8FPierreRoudier</id>
	<title>GRASS-Wiki - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="https://grasswiki.osgeo.org/w/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=%E2%9A%A0%EF%B8%8FPierreRoudier"/>
	<link rel="alternate" type="text/html" href="https://grasswiki.osgeo.org/wiki/Special:Contributions/%E2%9A%A0%EF%B8%8FPierreRoudier"/>
	<updated>2026-05-30T15:00:18Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.41.0</generator>
	<entry>
		<id>https://grasswiki.osgeo.org/w/index.php?title=GRASS_SoC_Ideas_2013&amp;diff=17911</id>
		<title>GRASS SoC Ideas 2013</title>
		<link rel="alternate" type="text/html" href="https://grasswiki.osgeo.org/w/index.php?title=GRASS_SoC_Ideas_2013&amp;diff=17911"/>
		<updated>2013-02-15T01:51:12Z</updated>

		<summary type="html">&lt;p&gt;⚠️PierreRoudier: Added &amp;quot;interface to OTB&amp;quot; as a suggestion&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== About ==&lt;br /&gt;
&lt;br /&gt;
This is the GRASS page for [http://wiki.osgeo.org/index.php/Google_Summer_of_Code Google Summer of Code 2013]. Here we will list project ideas and and other information related to the GRASS GSoC projects.&lt;br /&gt;
&lt;br /&gt;
== Ideas ==&lt;br /&gt;
&lt;br /&gt;
* Also review ideas from [[GRASS SoC Ideas 2009#Ideas|2009]], [[GRASS SoC Ideas 2010#Ideas|2010]], [[GRASS SoC Ideas 2011#Ideas|2011]] and [[GRASS SoC Ideas 2012#Ideas|2012]]  which are still open.&lt;br /&gt;
&lt;br /&gt;
* Project ideas of '''your own''' are also most welcome and often the best.&lt;br /&gt;
&lt;br /&gt;
=== Symbology / Cartography ===&lt;br /&gt;
&lt;br /&gt;
* Allow display of a vector legend in the map display (equivalent to current {{cmd|d.legend}} implementation for rasters)&lt;br /&gt;
&lt;br /&gt;
* Expand [[IconSymbols|symbology]]&lt;br /&gt;
: ''HB: note that SoC only accepts coding projects, not graphics design or documentation projects. Adding svg/eps support to a d.* module and ps.map would be quite helpful. See the {{Cmd|d.graph}} help page and {{Cmd|ps.map}}'s &amp;quot;eps&amp;quot; and &amp;quot;vpoints&amp;quot; instructions.''&lt;br /&gt;
&lt;br /&gt;
* Rework the complete set of thematic cartography tools such as {{Cmd|d.vect.thematic}} and {{Cmd|d.thematic.area}} and the related classification routines&lt;br /&gt;
&lt;br /&gt;
=== Imagery ===&lt;br /&gt;
&lt;br /&gt;
* Based on the work on [[GRASS_GSoC_2012_Image_Segmentation|segmentation]] in GSoC 2012 develop routines for object-based (ore region-based) image classification. This probably entails:&lt;br /&gt;
** Characterizing segments. Thsi includes producing statistics such as mean, median, variance of the segmented data within each delineated segment.&lt;br /&gt;
** Classifying segments based on the characteristics and (possibly) training areas&lt;br /&gt;
** Interface with other modules in a consistent workflow (i.cluster, r.fuzzy, etc)&lt;br /&gt;
&lt;br /&gt;
* Implement hierarchical classification tools (e.g. being able to create a large class &amp;quot;forest&amp;quot;, with subclasses of different types of forests)&lt;br /&gt;
&lt;br /&gt;
* Interface with the [http://www.orfeo-toolbox.org/otb/ Orfeo toolbox (OTB)], which is an open source, [http://www.itk.org ITK]-based, C++ library of (spatial) image processing library. OTB implements a very wide set of interesting features for anybody working with raster data - in particular satellite imagery: radiometric corrections, orthorectification, filtering, feature extraction, image segmentation , classification, change detection, etc.&lt;br /&gt;
&lt;br /&gt;
{{GSoC}}&lt;/div&gt;</summary>
		<author><name>⚠️PierreRoudier</name></author>
	</entry>
	<entry>
		<id>https://grasswiki.osgeo.org/w/index.php?title=GRASS_GSoC_2012_Image_Segmentation&amp;diff=16111</id>
		<title>GRASS GSoC 2012 Image Segmentation</title>
		<link rel="alternate" type="text/html" href="https://grasswiki.osgeo.org/w/index.php?title=GRASS_GSoC_2012_Image_Segmentation&amp;diff=16111"/>
		<updated>2012-07-12T00:03:36Z</updated>

		<summary type="html">&lt;p&gt;⚠️PierreRoudier: Added a Results section to showcase i.segment results and keep track of performance&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{GSoC}}&lt;br /&gt;
''(See also other [[GRASS_SoC_Ideas_2012#Accepted_Ideas|GRASS GSoC 2012 projects]])''&lt;br /&gt;
&lt;br /&gt;
{| {{table}}&lt;br /&gt;
|Student Name: || Eric Momsen&lt;br /&gt;
|-&lt;br /&gt;
|Organization: || [http://www.osgeo.org OSGeo - Open Source Geospatial Foundation]&lt;br /&gt;
|-&lt;br /&gt;
| Mentor Name: ||     Mentor: Markus Metz (backup mentors: M Lennert, P Roudier)&lt;br /&gt;
|-&lt;br /&gt;
| Title: || '''Image Segmentation'''&lt;br /&gt;
|-&lt;br /&gt;
|-&lt;br /&gt;
| Repository: || AddOns, browse at: [https://trac.osgeo.org/grass/browser/grass-addons/grass7/imagery/i.segment i.segment]&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
=Abstract=&lt;br /&gt;
&lt;br /&gt;
GRASS GIS has many imagery related processing capabilities, but the field is rapidly developing and many techniques are not yet implemented. The goal of this GSoC project is to implement the region growing image segmentation algorithm.&lt;br /&gt;
&lt;br /&gt;
Input: Raster map(s) to be segmented (plus optional vector map for a constraint)&lt;br /&gt;
&lt;br /&gt;
Output: To include segmented regions with statistics. This information can be directly used or taken as input to existing image classification modules.&lt;br /&gt;
&lt;br /&gt;
Update: This process will be split into two modules, the first will output a raster map with segments, the second will compute statistics for the segments.&lt;br /&gt;
&lt;br /&gt;
=Background=&lt;br /&gt;
&lt;br /&gt;
Image classification techniques already implemented in GRASS GIS include supervised and unsupervised classification. Classification of images based on pixels can often be very noisy. By first segmenting the image, later classification of 'objects' can be more effective. Noise is reduced, classification speed is increased, and most importantly the classification is performed on objects instead of pixels. The {{cmd|i.smap}} module does include a segmentation step (based on Gaussian mixture distribution), but there does not exist a module intended to segment the image and provide segment data for general use. A summary of the existing methods implemented in GRASS are at [[Image classification]]. Furthermore, the module {{AddonCmd|r.seg}} in GRASS-addons uses internally the Mumford-Shah variational model for image segmentation.&lt;br /&gt;
&lt;br /&gt;
== Segmentation Methods ==&lt;br /&gt;
&lt;br /&gt;
* Boundary Based&lt;br /&gt;
** optimal edge detector +&lt;br /&gt;
** watershed +&lt;br /&gt;
* Region Based&lt;br /&gt;
** multilevel thresholding technique +&lt;br /&gt;
** region growing + &lt;br /&gt;
* Combined boundary/region (is this a correct category for these two?)&lt;br /&gt;
** mean-shift&lt;br /&gt;
** watershed&lt;br /&gt;
&lt;br /&gt;
Carleer et.al. [1] reviewed 4 methods (marked with + above).  Boundary based methods are sensitive to noise and texture, and usually depend on good pre-processing.  (Does GRASS already have this pre-processing/filtering?)  Good results with urban zones, high contrast.  Both region based methods had difficulty with transition zones.  Region growing was less sensitive to texture (good for high resolution (1m) images).  Multi-level techniques are the only way to get all objects without over-segmentation.&lt;br /&gt;
&lt;br /&gt;
I don't recall the source, but I read in one place that mean-shift could be difficult to apply to very large images, and elsewhere it was mentioned watershed sees more use in greyscale images.&lt;br /&gt;
&lt;br /&gt;
As additional algorithms are added to the module, attention should be given to diversify so algorithms with different strengths are implemented first.&lt;br /&gt;
&lt;br /&gt;
=== Region Growing Variations ===&lt;br /&gt;
&lt;br /&gt;
Even within the region growing label, there are a number of approaches.  Here are two described in [5].&lt;br /&gt;
&lt;br /&gt;
1.  Growing&lt;br /&gt;
&lt;br /&gt;
Seeds (as a subset of the pixels) are selected (using image histogram, previous knowledge, or other methods).  Region growing is done by adding adjacent pixels.  No merging of segments is done, only unassigned pixels can be assigned to adjacent regions.&lt;br /&gt;
&lt;br /&gt;
2.  Growing and Merging&lt;br /&gt;
&lt;br /&gt;
Use all pixels as seeds, no need to have user figure out a reasonable starting seed selection.  Now adjacent segments can be merged.&lt;br /&gt;
&lt;br /&gt;
Is there ever a case where someone may want to start with seeds, but still allow segment merging?  Or does that fall into the realm of classification to be done in the next step?&lt;br /&gt;
&lt;br /&gt;
At this point, it seems both variations should be implemented.&lt;br /&gt;
&lt;br /&gt;
== Segmentation Considerations ==&lt;br /&gt;
&lt;br /&gt;
All(?) methods have some input parameter(s) that can be set.  These parameters influence if the algorithm will over-segment (one expected region is divided into 2 or more segments) or under-segment (putting two expected regions into one segment).  If the segments are used for later classification, over-segmentation should usually get preference to under-segmentation.  With extensive over-segmentation, some of the advantages provided by segmentation can be lost, but at least the classification can combine the segments into the expected region.  Under-segmentation is more critical, as the classification step will not divide the segment to recover the different regions.  (Based on a summary of a number of papers from [1])&lt;br /&gt;
&lt;br /&gt;
In order to respond to the issue of over/under-segmentation, a multiscalar approach would be interesting. This would mean either a top-down approach with a first coarse segmentation (under-segmentation) and the finer segmentation in selected segments, or a bottom-up approach with first a very fine-grained segmentation (over-segmentation) and the regrouping of segments to form higher levels. The first approach can be solved by doing a first segmentation, using certain segments as masks and then relaunching a second segmentation.  {Or by using a vector map of the first segmentation as a boundary constraint in the second segmentation.} The second approach requires an algorithm to decide which segments should be combined in a larger higher-level segments. A simple nearest neighbor or kmeans approach based on spectral mean can be used here. In terms of implementation in GRASS, this would probably call for several modules, one for the segmentation, and another for grouping of segments. The latter could be an all-purpose clustering module (and can also be emulated by simple data analysis in the attribute table + {{cmd|v.dissolve}}).&lt;br /&gt;
&lt;br /&gt;
It can sometimes be interesting to do a first segmentation on one band (e.g. panchromatic with higher resolution) and then regroup segments based on multispectral data (possibly weighting bands).&lt;br /&gt;
&lt;br /&gt;
=Main Goal=&lt;br /&gt;
&lt;br /&gt;
Implement an image segmentation method to extend the available options for image processing in GRASS. The region growing method has been selected as a robust general purpose method. An important contribution of the new method will be to include vector maps (for example road networks) as a constraint in growing the segments. Output from the module will include Spectral (mean/variance/range/ect) and Spatial (area/shape/location/etc) data for each region.&lt;br /&gt;
&lt;br /&gt;
=Specifications=&lt;br /&gt;
&lt;br /&gt;
* General considerations&lt;br /&gt;
** The general principle in GRASS is KISS, with each module doing one thing. It is to be seen if the result of this project is one single module or rather more than one module each specialised in one task in a segmentation workflow.&lt;br /&gt;
** As soon as code is to be (potentially) used in several modules, the use of a library should be envisaged.&lt;br /&gt;
** Be able to process large images while being considerate of system memory&lt;br /&gt;
* Input&lt;br /&gt;
** in the GRASS logic, input should be an image group, &amp;lt;del&amp;gt;or even image subgroup&amp;lt;/del&amp;gt;, which can contain any number of raster maps, but generally satellite or areal images that are pre-processed and ready for analysis (i.e. no pre-processing in the module) (Update: subgroups are not often used, there use will not be implemented unless someone asks.)&lt;br /&gt;
*** This input group will define the feature space which can include spectral and other continuous (elevation, PCA layers, slope aspect...) and possibly (probably not initially) even discrete data (soil type, land cover...)&lt;br /&gt;
*** Default action will be to normalize/scale all input rasters to a 0-1 range.  The allows bands (0-255), NDVI, and other numbers to be compared on an equal basis in the distance formula without any preprocessing steps.  Since it gives equal weights to all rasters in the input group, a flag will give the user the option to skip this normalization step in case they want to use the actual values.&lt;br /&gt;
** optionally vector maps of existing features&lt;br /&gt;
*** lines (be it linear features or boundary lines of polygons) should be used as constraints meaning that no segment boundary should cross such a line&lt;br /&gt;
*** centroids/points to be used as initial seeds&lt;br /&gt;
** What segmentation algorithm to use&lt;br /&gt;
** Parameters for that algorithm&lt;br /&gt;
* Algorithm of segmentation&lt;br /&gt;
** in GSoC implementation of only one algorithm&lt;br /&gt;
** code should be structured to allow easy implementation of additional algorithms&lt;br /&gt;
** multi-scalar segmentation can significantly improve results and should thus be implemented if possible (see i.smap code for example)&lt;br /&gt;
* Similarity measurement&lt;br /&gt;
** The squared euclidean distance will be the default similarity measurement.  If time allows, Manhattan distance will be added as an option.  (Using the square will give same results, we will also square the similarity threshold so the user doesn't need to worry about this detail.&lt;br /&gt;
** For the default scaling of the input, the similarity threshold will be 0 to 1.  This should be a good intuitive range for the user, 0 being the entire image is one segment and 1 being no segments can be formed.  (Internally, this number must be multiplied by the number of rasters in the image group, but again the user doesn't need to worry about the details.)  If the user selects the option to skip the normalization function, they will need to be careful how to select this parameter.&lt;br /&gt;
* Output&lt;br /&gt;
** first (segmentation) module: raster map of segments (i.e. each pixel value represents id of segment the pixel belongs to)&lt;br /&gt;
** second (stats) module: one vector map of segments per hierarchy level with a series of attributes (not all of these attributes should probably be calculated directly be the segmentation module)&lt;br /&gt;
*** spectral attributes: &lt;br /&gt;
**** per spectral band: mean, min, max, skewness&lt;br /&gt;
**** combination of bands: brightness, indices (i.e. results of multi-band calculations)&lt;br /&gt;
*** textural attributes: stdev (per-band and/or multi-band), mean difference to neighbor, Haralick texture features cf {{cmd|r.texture}}&lt;br /&gt;
*** geometric/morphological attributes: area, perimeter, length/width measures, see also {{cmd|r.li}}&lt;br /&gt;
*** context attributes: mean difference to all other regions in the same upper hierarchical level, relative localisation within upper hierarchical level, absolute localisation, number of objects in lower level&lt;br /&gt;
** depending on segmentation algorithm: raster map indicating for each pixel the probability of belonging to the segment it was put into, i.e. some measure of reliability of results&lt;br /&gt;
&lt;br /&gt;
=== Questions ===&lt;br /&gt;
&lt;br /&gt;
Number of modules:  Should the user run one module to create the segments (raster output), then if they are interested, run r.to.vect and run a second module (vector input/output) if they want to get the statistics.  (GUI glue to put them in one screen would be a low priority task for time remaining at the end of the summer.)  (I wonder if the stats module should take vector or raster as the input, it will also need the original raster.)&lt;br /&gt;
&lt;br /&gt;
&amp;quot;Probability of belonging to the segment&amp;quot;: For region growing - should this be the similarity measure when it was merged?  Or similarity measure of the pixel compared to the average?&lt;br /&gt;
/*ML: Not sure, but I would think that similarity between pixel and average of region it belongs to might be a good choice. Am not a specialist in statistics, but maybe it is possible to translate this into some form of probability of really &amp;quot;belonging&amp;quot; to that region (cf i.maxlik)*/&lt;br /&gt;
So this would be a comparison of the pixel to the final segment.  Does anyone have a standard measurement that should be used?&lt;br /&gt;
&lt;br /&gt;
4 vs. 8 neighbors:  Should this be a user input option?  It seems 4 neighbors (no diagonals) is the normal definition for segmentation, but not for other GRASS modules.  Update: Using 4 neighbors as default, with optional flag to select 8 neighbors.&lt;br /&gt;
&lt;br /&gt;
Null cells: Is it possible for some pixels inside the image to have null values?  If yes, should they just be excluded from the calculation, or merged into the nearest segment?  Update: current plan is to ignore all NULL values in the calculations.&lt;br /&gt;
&lt;br /&gt;
Are there any examples of using linear features to constraint segment growth, or will it usually be polygons?&lt;br /&gt;
&lt;br /&gt;
=== Lower priority ===&lt;br /&gt;
&lt;br /&gt;
Add shape characteristics (smoothness, compactness) to the similarity measurement.  Similar to eCognition &amp;quot;Multiresolution Segmentation&amp;quot;&lt;br /&gt;
&lt;br /&gt;
It may be useful to do some calculations for the color space (RGB, HSI, L*u*v*, L*a*b*)?  (I saw one paper [3] discussing pro/con of different systems, &amp;quot;best&amp;quot; answer is application dependent.)&lt;br /&gt;
&lt;br /&gt;
ML: I would say leave decisions on color space (which is just one portion of feature space) to the user: one can group any kind raster maps with i.group and submit that to segmentation, and so the user can decide whether to use an image represented by different bands in a specific color space, plus any kind of other bands, indices, etc.&lt;br /&gt;
&lt;br /&gt;
= Test Images =&lt;br /&gt;
&lt;br /&gt;
The results of the implemented algorithm should be compared against the results of a similar algorithm implement in other software.  The North Carolina GRASS sample location will be used for documentation and manuals.&lt;br /&gt;
&lt;br /&gt;
Carleer [1] used images with 1m resolution from Ikonos, panchromatic band from 08 June 2000, Brussels area.&lt;br /&gt;
&lt;br /&gt;
Should check segmentation results on images from a few different resolutions and different numbers of bands against what is obtained in other software.&lt;br /&gt;
&lt;br /&gt;
Is there a benchmark for processing speed that should be considered? [4]&lt;br /&gt;
&lt;br /&gt;
=Project Plan=&lt;br /&gt;
&lt;br /&gt;
Preparation: Gather ideas from the community!  Feature requests, image segmentation literature, and any other ideas and suggestions.&lt;br /&gt;
&lt;br /&gt;
* May 21: Start coding, 8 weeks until Midterm Evaluation &lt;br /&gt;
* Week 1: Develop pseudocode to outline the work [http://lists.osgeo.org/pipermail/soc/2012-May/001747.html Report 1]&lt;br /&gt;
* Week 2-4: Implement the main algorithm [http://lists.osgeo.org/pipermail/soc/2012-June/001779.html Report 2] [http://lists.osgeo.org/pipermail/soc/2012-June/001804.html Report 3] [http://lists.osgeo.org/pipermail/soc/2012-June/001826.html Report 4]&lt;br /&gt;
* Week 5: Add vector maps as a constraint to the segmentation&lt;br /&gt;
* Week 6: Validation &lt;br /&gt;
* Week 7: Debugging &lt;br /&gt;
* Week 8: Contingency time for finishing the above, ensure a solid main program. &lt;br /&gt;
* July 9: Midterm Evaluation: Evaluate the existing program, determine the plan for the remaining 3-4 weeks. Options include:&lt;br /&gt;
* Improving the main algorithm&lt;br /&gt;
* Adding control for what scale the segmentation is performed at&lt;br /&gt;
* Providing updates to {{cmd|i.maxlik}} to ensure the segmentation output can be used as input for the existing classification functionality&lt;br /&gt;
* GUI&lt;br /&gt;
* Adding a second image segmentation algorithm&lt;br /&gt;
&lt;br /&gt;
= Region Growing Algorithm =&lt;br /&gt;
&lt;br /&gt;
Here is (a start!) for the processing steps, based on SPRING [2]&lt;br /&gt;
&lt;br /&gt;
Region Growing, bottom up processing.  Main improvement compared to simple algorithm is to slowly lower the similarity function, so only best matches are made first.  This prevents the &amp;quot;first&amp;quot; segment from taking over any unclear areas between it and the next clear segment.&lt;br /&gt;
&lt;br /&gt;
1. Input:&lt;br /&gt;
** Seeds:  all pixels  (Later addition can be alternate seeding methods)&lt;br /&gt;
** Similarity Threshold T(t)... as t increases, threshold for similarity is lower.  SPRING used:  &amp;lt;math&amp;gt;T(t) = T(0) alpha^t   &amp;lt;/math&amp;gt;, where T(0) &amp;gt; 0, t =0,1,2... and alpha &amp;lt;1&lt;br /&gt;
** Size of smallest allowed area  (Is this wanted or needed ???)&lt;br /&gt;
2. Loop for t&lt;br /&gt;
** initialize candidate regions, save mean value vector and neighboring regions  (Not sure why this needs to be calculated/saved ahead of time ??)&lt;br /&gt;
3. For each region i in candidate region set (first pass this equals the seeds):&lt;br /&gt;
** Compare Ri with neighbors  (Question: should neighbors include or exclude those regions that were already matched?&lt;br /&gt;
** If it exists, Rk is best neighbor if smallest D of all neighbors and and D &amp;lt; T.&lt;br /&gt;
** Check Rk's neighbors.&lt;br /&gt;
** Merge IF Ri is Rk's best neighbor&lt;br /&gt;
** remove from candidate region set.  (give all &amp;quot;small&amp;quot; regions a chance to merge with best neighbor before growing larger regions)&lt;br /&gt;
** update segment values&lt;br /&gt;
** next i&lt;br /&gt;
3. next t, with all segments returned to candidate region set, until no regions can be merged&lt;br /&gt;
&lt;br /&gt;
4. Force a merge of regions that are too small&lt;br /&gt;
&lt;br /&gt;
= ToDo List =&lt;br /&gt;
&lt;br /&gt;
The following list was developed at the &amp;quot;mid&amp;quot; point review, with about 1 month left.  Rating system is 1: must do, 2: would be nice, 3: probably only will be finished if it is a quick task.&lt;br /&gt;
&lt;br /&gt;
== Functionality ==&lt;br /&gt;
&lt;br /&gt;
1: Implement the 8 neighbor option (currenly only the 4 pixel neighbors are considered).&lt;br /&gt;
&lt;br /&gt;
1: Starting seed pixels for the segments&lt;br /&gt;
&lt;br /&gt;
1: handle null cells in the optional boundary constraints raster.&lt;br /&gt;
&lt;br /&gt;
2: Current input limit is 2 billion starting segments, constrained by &amp;quot;int&amp;quot; data type for segment ID.  Consider long int, and/or dynamic allocation of different storage depending on what is needed. (MM: Unfortunately you are stuck with the largest integer type that a GRASS raster supports with is 32 bit integer. Internally you could use larger integer types, but then you can not save the results... EM: Hmm, if the segments are renumbered sequenctial at the end, it would be possible to then save them if the resulting number of segments is less then 2 billion...  Does anyone want to segment a raster with more than 2 billion pixels?  As a work around, larger maps could be processed, if a random selection of pixels are used as seeds... At a minimum, put this limitation in as error checking and the documents.)&lt;br /&gt;
&lt;br /&gt;
2: Check input parameters for mean-shift and other segmentation algorithms, try to make input parameters &amp;quot;generic&amp;quot; so they could be used for any/other algorithms.&lt;br /&gt;
&lt;br /&gt;
2: Add shape characteristics (smoothness, compactness) to the similarity measurement. Similar to eCognition &amp;quot;Multiresolution Segmentation&amp;quot;.  Check Baatz and Shape paper.  Adds two input parameters (weight of radiometric to shape, and weight of compactness to smoothness.) (Maybe use the ratio of the number of edge cells to the total number of cells as a proxy for compactness, which could be easily obtained as a side-product when finding neighbors.)&lt;br /&gt;
&lt;br /&gt;
2: Alternate similarity measurements (Manhattan, Malahanobis)&lt;br /&gt;
&lt;br /&gt;
3: Adding a parameter to make it easier to merge smaller segments and harder to merge large segments. (Preliminary testing is not promising, low priority)&lt;br /&gt;
&lt;br /&gt;
3: Estimating the threshold value. (at least add to docs) (1 to 5% of the max difference gave me (MM) subjectively good results.)&lt;br /&gt;
&lt;br /&gt;
?: Adding control for what scale the segmentation is performed at.  (EM: I'm not certain what is meant/needed for this, but I think it is a different concept from just using g.region.)&lt;br /&gt;
&lt;br /&gt;
== Statistics/metrics ==&lt;br /&gt;
&lt;br /&gt;
1: i.segment.stats&lt;br /&gt;
(It should do more then just statistics...  .evaluation .metrics .data  Maybe i.segment.metrics?)&lt;br /&gt;
(Will need to evaulate what is already available from other GRASS modules, what is easy, what is hard.  Start from the specifications for what is desired.)&lt;br /&gt;
&lt;br /&gt;
1: Providing updates to i.maxlik to ensure the segmentation output can be used as input for the existing classification functionality.&lt;br /&gt;
&lt;br /&gt;
1: Integration/workflow for r.fuzzy.&lt;br /&gt;
&lt;br /&gt;
== Speed ==&lt;br /&gt;
&lt;br /&gt;
2: Neighbor finding, keep a tree structure of found neighbor segments to reduce the number of neighbor pixels that the similarity function will be run on.&lt;br /&gt;
&lt;br /&gt;
2: Search continuation.  If Ri isn't Rk's best neighbor, then use Rk as the next Ri.  (Skips one neighbor finding routine.)&lt;br /&gt;
&lt;br /&gt;
2: Consider peano or other ordering for pixel processing (instead of row major order), should help processing time if an entire &amp;quot;row&amp;quot; of segments are not in RAM.&lt;br /&gt;
&lt;br /&gt;
3: neighbor finding: When checking for Rk's neighbors, account for already knowing Ri and skip those pixels.&lt;br /&gt;
&lt;br /&gt;
?: change candidate flag to int (compare with pass number) to avoid resetting each time. (32x RAM requirement for the flag, is it worth it?)&lt;br /&gt;
&lt;br /&gt;
?: RAM storage of the segment membership and the neighboring segments (calculate first the requirements, if this is even possible for reasonable (what size?) maps).  (check what % of the processing time is spent finding neighbors.)&lt;br /&gt;
&lt;br /&gt;
== Memory ==&lt;br /&gt;
&lt;br /&gt;
1: Put segment ID in SEG instead of RAM. (Possibly make this dependent on available RAM?)&lt;br /&gt;
&lt;br /&gt;
1: User input for how much RAM can be used.&lt;br /&gt;
&lt;br /&gt;
2: Consider putting the optional boundary constraints raster into RAM (dependent on available RAM).&lt;br /&gt;
&lt;br /&gt;
2: Use &amp;quot;zero&amp;quot; for segment ID's of Null cells, discard the NULL flag.  (Need to check speed impact with Seg ID in SEG storage.)&lt;br /&gt;
&lt;br /&gt;
3: Check input map type(s), currently storing in DCELL sized SEG file, could reduce this dynamically depending on input map time. (Could only reduce to FCELL, since will be storing mean we can't use CELL.  Might not be worth the added code complexity.)&lt;br /&gt;
&lt;br /&gt;
== Polish ==&lt;br /&gt;
&lt;br /&gt;
1: Add error traps.  (Certainly for memory allocation, Minimum number of non-NULL cells in the input bands?anything else?)&lt;br /&gt;
&lt;br /&gt;
2: Make the output segment ID's sequential (currently they have what ID the &amp;quot;first&amp;quot; pixel in the segment had).&lt;br /&gt;
&lt;br /&gt;
2: There are many small TODO scattered in the code. Resolve some easy questions to clean up the code.&lt;br /&gt;
&lt;br /&gt;
2: Change G_percentage: estimate total number of passes expected from histogram and threshold.  (If this isn't reliabe, maybe change to show 1% for each pass, i.e. % complete out of first 100 passes, then % complete out of next 100 passes, etc.)&lt;br /&gt;
&lt;br /&gt;
3: GUI (to combine i.segment with the stats module)&lt;br /&gt;
&lt;br /&gt;
== Documentation ==&lt;br /&gt;
&lt;br /&gt;
How to choose parameters, what their impact is.&lt;br /&gt;
&lt;br /&gt;
Typical workflow:&lt;br /&gt;
&lt;br /&gt;
* i.group&lt;br /&gt;
* i.segment&lt;br /&gt;
* r.to.vect&lt;br /&gt;
* i.segment.metrics and/or i.maxlik and/or r.fuzzy&lt;br /&gt;
&lt;br /&gt;
= Workflow =&lt;br /&gt;
&lt;br /&gt;
Todo: Some typical workflow examples, type of data, GRASS modules used before and after the image segmentation.&lt;br /&gt;
&lt;br /&gt;
= Results =&lt;br /&gt;
&lt;br /&gt;
== Ortho-photo ==&lt;br /&gt;
&lt;br /&gt;
The data has 3 bands, and the computational region is 1,120,080 cells, at 1-m resolution.&lt;br /&gt;
&lt;br /&gt;
Here's the code used to generate this segmentation result:&lt;br /&gt;
&lt;br /&gt;
i.segment group=ortho output=ortho_segs_ha threshold=0.02 endt=10000 final_mean=ortho_segs_mean_ha min=20 --o&lt;br /&gt;
&lt;br /&gt;
The segmentation performed in 22m53.255s on a Intel i5 laptop with 4Go RAM. The memory consumption was around 38 Mo.&lt;br /&gt;
&lt;br /&gt;
[[File:Raglan_ortho_seg.png]]&lt;br /&gt;
&lt;br /&gt;
== SPOT5 scene ==&lt;br /&gt;
&lt;br /&gt;
The data has 4 bands, and the computational region is 4,444,517 cells, at 10-m resolution.&lt;br /&gt;
&lt;br /&gt;
Here's the code used to generate this segmentation result:&lt;br /&gt;
&lt;br /&gt;
i.segment group=spot output=spot_seg threshold=0.01 endt=10000 min=30 --o&lt;br /&gt;
&lt;br /&gt;
The segmentation performed in 87m3.870s on a Intel Core 2 workstation with 8Go RAM. The memory consumption was around 170 Mo.&lt;br /&gt;
&lt;br /&gt;
[[File:Taranaki spot seg.png]]&lt;br /&gt;
&lt;br /&gt;
= References =&lt;br /&gt;
&lt;br /&gt;
TODO: complete references with links.&lt;br /&gt;
&lt;br /&gt;
[http://www.armurs.ulb.ac.be/images/8/86/PERS_Carleer_05.pdf] Carleer, et al: Assessment of Very High Spatial Resolution Satellite Image Segmentations, 2005 (Evaluates 2 boundary and 2 region based algorithms.)&lt;br /&gt;
&lt;br /&gt;
[http://marte.dpi.inpe.br/col/sid.inpe.br/deise/1999/02.05.09.30/doc/T205.pdf] Bins, et al: Satellite Imagery Segmentation: A Region Growing Approach, 1996  (Describes approach taken in SPRING software.)&lt;br /&gt;
&lt;br /&gt;
[http://www.sciencedirect.com/science/article/pii/S0031320300001497] Cheng et. al.: Color image segmentation: advances and prospect, 2000  (survey of segmentation methods and color spaces)&lt;br /&gt;
&lt;br /&gt;
[http://www.isprs.org/proceedings/XXXV/congress/comm4/papers/506.pdf] G. Meinel, M. Neubert: A Comparison of Segmentation Programs for High Resolution Remote Sensing Data, 20?? (Includes timing to complete segmentation)&lt;br /&gt;
&lt;br /&gt;
[http://www.wiley.com/WileyCDA/WileyTitle/productCd-0471377392.html?0471377392=] Pitas, I:  Digital Image Processing Algorithms and Applications, 2000 (Textbook, including 1 chapter on segmentation methods.)&lt;br /&gt;
&lt;br /&gt;
eCognition Reference Manual&lt;br /&gt;
&lt;br /&gt;
Kurtz et. al: Hierarchical Segmentation of Multiresolution Remote Sensing Images, 2011&lt;br /&gt;
&lt;br /&gt;
Comaniciu, Dorin: Mean Shift: A Robust Approach Toward Feature Space Analysis, 2002&lt;/div&gt;</summary>
		<author><name>⚠️PierreRoudier</name></author>
	</entry>
	<entry>
		<id>https://grasswiki.osgeo.org/w/index.php?title=File:Taranaki_spot_seg.png&amp;diff=16110</id>
		<title>File:Taranaki spot seg.png</title>
		<link rel="alternate" type="text/html" href="https://grasswiki.osgeo.org/w/index.php?title=File:Taranaki_spot_seg.png&amp;diff=16110"/>
		<updated>2012-07-11T23:55:24Z</updated>

		<summary type="html">&lt;p&gt;⚠️PierreRoudier: Test of i.segment (as at 12/07/2012) on an cropped SPOT 5 scene.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Test of i.segment (as at 12/07/2012) on an cropped SPOT 5 scene.&lt;/div&gt;</summary>
		<author><name>⚠️PierreRoudier</name></author>
	</entry>
	<entry>
		<id>https://grasswiki.osgeo.org/w/index.php?title=File:Raglan_ortho_seg.png&amp;diff=16109</id>
		<title>File:Raglan ortho seg.png</title>
		<link rel="alternate" type="text/html" href="https://grasswiki.osgeo.org/w/index.php?title=File:Raglan_ortho_seg.png&amp;diff=16109"/>
		<updated>2012-07-11T23:52:06Z</updated>

		<summary type="html">&lt;p&gt;⚠️PierreRoudier: Test of i.segment (as at 12/07/2012) on an orthophoto.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Test of i.segment (as at 12/07/2012) on an orthophoto.&lt;/div&gt;</summary>
		<author><name>⚠️PierreRoudier</name></author>
	</entry>
	<entry>
		<id>https://grasswiki.osgeo.org/w/index.php?title=Computational_region&amp;diff=15439</id>
		<title>Computational region</title>
		<link rel="alternate" type="text/html" href="https://grasswiki.osgeo.org/w/index.php?title=Computational_region&amp;diff=15439"/>
		<updated>2012-04-29T23:56:28Z</updated>

		<summary type="html">&lt;p&gt;⚠️PierreRoudier: Added FAQ entry on the -a flag&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;The current region or computational region is the actual setting of the region boundaries and the actual raster resolution. &lt;br /&gt;
&lt;br /&gt;
As a general rule in GRASS: &lt;br /&gt;
&lt;br /&gt;
#Raster maps are always '''imported completely''' at their own resolution (exception: WMS imported layers). &lt;br /&gt;
#Vector maps are always '''imported completely'''. &lt;br /&gt;
#In computations, &lt;br /&gt;
##raster '''input''' maps are automatically cropped/padded and rescaled (using nearest neighbour resampling) to match the current region in order to produce the output raster map or to query values. &lt;br /&gt;
##Raster '''output''' maps have their bounds and resolution equal to those of the current computational region.&lt;br /&gt;
##Vector maps are always '''considered completely'''. &lt;br /&gt;
&lt;br /&gt;
=== FAQs  ===&lt;br /&gt;
&lt;br /&gt;
'''Q:''' I don't see anything! &lt;br /&gt;
&lt;br /&gt;
'''A:''' Typically the computational region is set to an area not covering the raster map of interest. Use {{cmd|g.region}} to adjust the computational region settings, e.g. by setting it to the raster map: &lt;br /&gt;
&lt;br /&gt;
  g.region rast=myrastermap -p&lt;br /&gt;
&lt;br /&gt;
'''Using the graphical user interface:'''&lt;br /&gt;
&lt;br /&gt;
Set display to selected map:&lt;br /&gt;
&lt;br /&gt;
[[Image:Wxgui zoom to raster.png|350px|center|thumb|wxGUI: set map display to selected map (right mouse button context menu on map name)]]&lt;br /&gt;
&lt;br /&gt;
Set computational region to selected map:&lt;br /&gt;
&lt;br /&gt;
[[Image:Wxgui computat region to raster.png|350px|center|thumb|wxGUI: set computational region to selected map (right mouse button context menu on map name)]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt; '''Q:''' The resolution of my region is not the one I asked for! &lt;br /&gt;
&lt;br /&gt;
'''A:'''  Sometimes, the resolution of the computational region is not matching exactly the resolution entered to {{cmd|g.region}}. Here's an example:&lt;br /&gt;
  g.region rast=myrastermap res=1 -p&lt;br /&gt;
  (...)&lt;br /&gt;
  nsres:      0.9993515&lt;br /&gt;
  ewres:      1.00025576&lt;br /&gt;
  (...)&lt;br /&gt;
&lt;br /&gt;
To force the computational region to match the resolution entered, you need to use the -a flag:&lt;br /&gt;
  g.region rast=myrastermap res=1 -ap&lt;br /&gt;
  (...)&lt;br /&gt;
  nsres:      1&lt;br /&gt;
  ewres:      1&lt;br /&gt;
  (...)&lt;br /&gt;
&lt;br /&gt;
  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt; '''Q:''' The raster map looks ugly. &lt;br /&gt;
&lt;br /&gt;
'''A:''' The resolution of the computational region does not match the resolution of the raster map. Use {{cmd|g.region}} to adjust the resolution settings of the computational region or set it to the raster map (see above). &lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt; '''Q:''' I get &amp;quot;xyz module: G_malloc error&amp;quot;&lt;br /&gt;
&lt;br /&gt;
'''A:''' You likely try to use more memory than your computer offers which is commonly caused by a too high raster resolution (or too large computational region). E.g., it is pointless to calculate common DEM data at nanometer raster resolution. Set the region extent and raster resolution properly with {{cmd|g.region}} (in the wxGUI: menu Settings -&amp;gt; Region -&amp;gt; Display Region | Set Region).&lt;br /&gt;
&lt;br /&gt;
[[Category: Documentation]]&lt;br /&gt;
[[Category: FAQ]]&lt;br /&gt;
[[Category: Tutorial]]&lt;/div&gt;</summary>
		<author><name>⚠️PierreRoudier</name></author>
	</entry>
	<entry>
		<id>https://grasswiki.osgeo.org/w/index.php?title=GRASS_SoC_Ideas_2012&amp;diff=15419</id>
		<title>GRASS SoC Ideas 2012</title>
		<link rel="alternate" type="text/html" href="https://grasswiki.osgeo.org/w/index.php?title=GRASS_SoC_Ideas_2012&amp;diff=15419"/>
		<updated>2012-04-25T22:49:31Z</updated>

		<summary type="html">&lt;p&gt;⚠️PierreRoudier: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Image:grasslogo_vector_small.png|link=http://grass.osgeo.org]]&amp;lt;font size=&amp;quot;+3&amp;quot;&amp;gt; @ &amp;lt;/font&amp;gt; [[Image:Gsoc-2012-logo-color.png|250px|link=http://wiki.osgeo.org/wiki/Google_Summer_of_Code_2012]] &amp;lt;font size=&amp;quot;+3&amp;quot;&amp;gt; @ &amp;lt;/font&amp;gt; [[Image:OSGeo 220pix.png|link=http://www.osgeo.org]]&lt;br /&gt;
&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* See also previous Google Summer of Code [[GRASS SoC Ideas 2011|ideas from 2011]].&lt;br /&gt;
&lt;br /&gt;
* Visit the [http://wiki.osgeo.org/wiki/Google_Summer_of_Code_2012 main OSGeo Google Summer of Code 2012 @ OSGeo wiki page].&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
== About ==&lt;br /&gt;
&lt;br /&gt;
This is the GRASS page for [http://wiki.osgeo.org/index.php/Google_Summer_of_Code Google Summer of Code 2012]. Here we will list project ideas and and other information related to the GRASS GSoC projects.&lt;br /&gt;
&lt;br /&gt;
* [http://code.google.com/soc/ Official Google Summer of Code 2012 homepage]&lt;br /&gt;
* [http://wiki.osgeo.org/wiki/Google_Summer_of_Code_2012 OSGeo SoC 2012 homepage]&lt;br /&gt;
&lt;br /&gt;
Promotion:&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
 * OSGeo Flyer at &amp;lt;s&amp;gt;http://svn.osgeo.org/osgeo/marketing/flyer/google_summer_of_code/OSGeo_GSoC_2012.pdf &amp;lt;/s&amp;gt;(todo)&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
* Videos at      http://code.google.com/p/google-summer-of-code/wiki/Videos&lt;br /&gt;
* More Flyers at http://code.google.com/p/google-summer-of-code/wiki/GsocFlyers&lt;br /&gt;
&lt;br /&gt;
== Timeline ==&lt;br /&gt;
&lt;br /&gt;
* '''[http://www.google-melange.com/gsoc/document/show/gsoc_program/google/gsoc2012/faqs#timeline The official timeline]'''&lt;br /&gt;
&lt;br /&gt;
== Required Steps ==&lt;br /&gt;
&lt;br /&gt;
* '''List ideas'''&lt;br /&gt;
&lt;br /&gt;
* Assign Mentors to Ideas&lt;br /&gt;
&lt;br /&gt;
* Notify OSGeo&lt;br /&gt;
&lt;br /&gt;
* Mentors evaluate student applications&lt;br /&gt;
&lt;br /&gt;
* Accepted students announced&lt;br /&gt;
&lt;br /&gt;
* Students subscribe to the [http://lists.osgeo.org/mailman/listinfo/grass-dev grass-dev mailing list] and introduce themselves&lt;br /&gt;
&lt;br /&gt;
* Mentor will create directory structure in the [http://trac.osgeo.org/grass/browser/grass-addons GRASS add-ons SVN] for projects and setup access for students&lt;br /&gt;
** Students must read and post agreement to [http://grass.osgeo.org/programming7/rfc2_psc.html RFC2] to the [http://lists.osgeo.org/mailman/listinfo/grass-psc grass-psc mailing list] to gain SVN access&lt;br /&gt;
** Create a Wiki page for each accepted project, to be used as a progress reporting tool&lt;br /&gt;
&lt;br /&gt;
* Coding begins...&lt;br /&gt;
&lt;br /&gt;
* Students and mentors: Complete the Mid-term survey&lt;br /&gt;
&lt;br /&gt;
* Final commit and packaging for Google&lt;br /&gt;
&lt;br /&gt;
== Ideas ==&lt;br /&gt;
&lt;br /&gt;
* Also review ideas from [[GRASS SoC Ideas 2007#Ideas|2007]], [[GRASS SoC Ideas 2008#Ideas|2008]], [[GRASS SoC Ideas 2009#Ideas|2009]], [[GRASS SoC Ideas 2010#Ideas|2010]], and [[GRASS SoC Ideas 2011#Ideas|2011]]  which are still open.&lt;br /&gt;
&lt;br /&gt;
* Project ideas of '''your own''' are also most welcome and often the best.&lt;br /&gt;
&lt;br /&gt;
=== [[wxGUI]] ===&lt;br /&gt;
&lt;br /&gt;
# Develop GUI support in wxPython for visualy analyzing series of raster map layers. The module should provide users with capabilities to browse and animate raster (and potentially also vector) data series in a 2D display and save outputs to animated GIF, MOV, or MPEG files. A related module that displays the series as small images and support re-ordering, deleting and adding raster maps (frames) to the series would also be helpful. To compare visually two images a slider functionality could be added to the 2D display, for example, to compare before and after images, or two consequent images in series. The series of data layers can be handled as multiple standard raster or vector layers or using  the new time series support. See existing modules {{cmd|xganim}}, {{cmd|r.out.mpeg}}, [[NVIZ]]'s animation tools, and the [[Movies]] creation wiki page. There is also a related capability in the TclTk GUI. (co-mentor Helena Mitasova).&lt;br /&gt;
# Develop an interactive vector geometry selection and export tool for [[wxGUI]] as described in the trac ticket [http://trac.osgeo.org/grass/ticket/1471 #1471]&lt;br /&gt;
# Offer also (optional) &amp;quot;conventional&amp;quot; '''GUI layout''': For some users, the current approach of separate windows (SDI) leads to a '''windows flooding'''. This is a common complaint especially from newbies. Especially on large monitors or dual screen systems catching the [[wxGUI]] windows can be tedious when they appear on separate monitors (depends on windows manager, the much used KDE scatters typically the wxGUI windows all over the screen real estate). Almost each task generates a new wxGUI window which is freely floating around on the screen:  [http://grass.osgeo.org/grass63/screenshots/images/wxgrass_digit-03.png example 1] and [http://grass.osgeo.org/grass63/screenshots/images/wxgrass_digit-01.png example 2]. On a dual-screen this may sum up to 50cm of distance! The idea is to capture all those windows in one frame. For details, see [[wxGUI#Layout| wxGUI layout]].&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
&amp;lt;gallery widths=400 heights=250&amp;gt;&lt;br /&gt;
Image:Wxgui_current.png|Current wxGUI layout with detached window components&lt;br /&gt;
Image:Wxgui_proposal.png|Proposal for wxGUI layout modification (Recomposition of existing toolbars, mapview and menus)&lt;br /&gt;
&amp;lt;/gallery&amp;gt;&lt;br /&gt;
&amp;lt;/center&amp;gt;&lt;br /&gt;
# ''Your idea here''&lt;br /&gt;
&lt;br /&gt;
'''Willing to Mentor:''' [[User:Landa|Martin Landa]], [[User:MarisN|Maris Nartiss]], [[User:Mmetz|Markus Metz]], (''your name here'')&lt;br /&gt;
&lt;br /&gt;
=== Raster  ===&lt;br /&gt;
&lt;br /&gt;
#Add '''[[OpenMP]] parallelization''' where appropriate, for example {{cmd|r.cost}}, {{cmd|r.surf.contour}}, {{cmd|r.watershed}}. It is important to understand which modules are processor bound, and concentrate on them. i.e. do not needlessly complicate the code of non-long running processor bound modules. A good working knowledge of ANSI C and {{wikipedia|OpenMP}} is required. ({{wikipedia|OpenCL}} and {{wikipedia|pthreads}} are fine too!) &lt;br /&gt;
#Create a new GRASS module to find the {{wikipedia|topographic_prominence}} of peaks from a raster elevation map within the region. (probably this would only make up 1/4 to 1/2 of a multi-part GSoC project) &lt;br /&gt;
# ''Your suggestion here!''&lt;br /&gt;
&lt;br /&gt;
'''Willing to Mentor:''' Hamish (co-mentor parallelization and prominence projects), Wolf Bergenheim(''your name here'')&lt;br /&gt;
&lt;br /&gt;
=== Vector ===&lt;br /&gt;
&lt;br /&gt;
# Add '''[[OpenMP]] parallelization''' where appropriate, for example, {{cmd|v.surf.rst}} and {{cmd|v.vol.rst}} ''(co-mentor Helena Mitasova)''. (OpenCL and pthreads are fine too!) See above idea in the [[GRASS SoC Ideas 2012#Raster|Raster section]].&lt;br /&gt;
# Better '''support for wrap-around at 180 longitude''': Currently the raster engine is pretty good at wrapping data over 180 longitude. The vector data isn't, but it should be. This is a great task if by the end of the summer you'd like to be familiar with the implementation method of an entire vector stack of a fully featured modern GIS.&lt;br /&gt;
# Add '''break lines support to interpolation modules''' ({{cmd|v.surf.rst}}, {{cmd|v.surf.idw}}, {{cmd|v.surf.bspline}}). Current implementations provide no support to specify locations of cliffs or faults* thus leading to improper results within non-continous datasets. See [http://www.spatialanalysisonline.com/output/html/Breaklinesandnaturalboundaries.html Geospatial Analysis - a comprehensive guide. 3rd edition] for description. [*] well, some support exists, see {{AddonCmd|v.surf.icw}}.&lt;br /&gt;
# Speed up [[wxGUI]] handling and 2D display of large point clouds (several million points). This is likely to include additional &amp;quot;Level-1 Vector&amp;quot; support in the backend modules (for which a working knowledge of ANSI C is req'd).&lt;br /&gt;
# ''Your idea here'' ...&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Willing to Mentor:''' [[User:Landa|Martin Landa]], [[User:Mmetz|Markus Metz]], Hamish (co-mentor for parallelization), Wolf Bergenheim, (''your name here'')&lt;br /&gt;
&lt;br /&gt;
=== Imagery ===&lt;br /&gt;
&lt;br /&gt;
# GRASS's imagery modules (for satellite, scanned maps, and orthophotos) act as enhanced raster modules. In GRASS 5 and 6 they were mostly implemented using interactive X-monitors which are not available in MS Windows and so are removed in the new cross-platform code of GRASS 7.&lt;br /&gt;
#* We need someone willing to '''port the old modules to work with GRASS 7''', including writing new '''wxPython GUI frontends''' to a number of existing tools and updating the imagery libraries to current raster library standards.&lt;br /&gt;
#* In addition, there are a number of '''improved/automated georectification tools''' which have not been merged into GRASS 5/6 which it would be nice to have updated and merged into the main code.&lt;br /&gt;
# Implement '''[[OpenMP]] (multithreading)''' as much as possible (where appropriate; OpenCL and pthreads are fine too)&lt;br /&gt;
# In addition to the porting of the georectification tools mentioned above, it would be interesting to implement an orthorectification tool for satellite imagery. Currently, GRASS only has {{cmd|i.ortho.photo}} for aerial photographs.&lt;br /&gt;
# Implement image segmentation algorithms and tools&lt;br /&gt;
# Implement region-based classification&lt;br /&gt;
# Implement hierarchical classification tools (e.g. being able to create a large class &amp;quot;forest&amp;quot;, with subclasses of different types of forests)&lt;br /&gt;
# ''Your idea here''&lt;br /&gt;
&lt;br /&gt;
See the [[Image_processing#Ideas_collection_for_improving_GRASS.27_Image_processing_capabilities|ideas for imagery improvement]] and [http://trac.osgeo.org/grass/wiki/Grass7/ImageryLib GRASS 7 ideas] wiki pages for more details.&lt;br /&gt;
&lt;br /&gt;
'''Willing to Mentor:''' Hamish (co-mentor for parallelization), Markus Metz (orthorectification), (''your name here'')&lt;br /&gt;
&lt;br /&gt;
=== Cartography and display ===&lt;br /&gt;
&lt;br /&gt;
# Add SVG (and perhaps EPS) support to the display library, for use via {{cmd|d.graph}} and/or {{cmd|d.vect}}, and add SVG support to {{cmd|ps.map}} via a SVG to EPS converter tool (probably by adapting an existing GPL-compatible library). Code to be written in ANSI C. Step 1 is adding a Bézier curve rendering library function.&lt;br /&gt;
# Integrate Quantum/GRASS SVG output plugin with Inkscape. Python can serve as a common glue between these tools. The project would facilitate easy cartographic workflow while utilizing the advanced design functionality of Inkscape. This would be a two way bridge:&lt;br /&gt;
## QGIS/GRASS plugins to invoke an Inkscape process and send a data set.&lt;br /&gt;
## Inkscape plugin to query various OSGeo projects and display various data sets as layers.&lt;br /&gt;
# ''Your idea here ...''&lt;br /&gt;
&lt;br /&gt;
'''Willing to Mentor:''' Hamish (as a co-mentor)&lt;br /&gt;
&lt;br /&gt;
=== 3D visualization ===&lt;br /&gt;
&lt;br /&gt;
# Optimize OGSF (and NVIZ/wxNVIZ) to '''display large 3D point clouds with uninterupted tought speed'''. OGSF + (wx)NVIZ should be able to rotate point cloud (i.e. LiDAR dataset) with 4 millions of points on medium hardware (i.e. 2GHz CPU with 2Gb RAM and GPU with hardware transform and lighting support and dedicated video RAM) with response time not greater than 1.0 second.&lt;br /&gt;
# Design and implement '''text displaying and styling in OGSF library''' and it's front-ends (NVIZ, [[wxNVIZ]]). Solution should be user configurable (fonts, colors, effects etc.) and multilanguage friendly.&lt;br /&gt;
# Design and implement user-provided '''symbol support in OGSF library''' and it's front-ends (NVIZ, [[wxNVIZ]]). Solution should support GRASS symbols, SVG, and/or simple EPS symbols.&lt;br /&gt;
&amp;lt;!-- # Add/fix missing features to [[wxNVIZ]] (lighting, robust handling of z-exageration and viewing position including latlong data, cutting planes, multiattribute 3D points, decorations: scale, north, legend, text, isosurfaces and slicing) --&amp;gt;&lt;br /&gt;
# Drape multiple color maps over topography (equivalent to running r.patch or r.composite and draping the result; second raster is currently supported as transparency).&lt;br /&gt;
# Improve handling of z-exageration so that z-exag=1  is a realistic representation of landscape in terms of vertical scaling. Other default settings could also be improved to support wider range of data and improve robustness.&lt;br /&gt;
&lt;br /&gt;
'''Willing to Mentor:''' [[User:Landa|Martin Landa]] (for 2), co-mentor for 1 and 5: Helena Mitasova, (''your name here'')&lt;br /&gt;
&lt;br /&gt;
=== Volume modeling ===&lt;br /&gt;
&lt;br /&gt;
# Develop '''r3.flow''' for computing 3D flow lines and 3D flow accumulation from 3D rasters&lt;br /&gt;
# Enhance volume interpolation module '''{{cmd|v.vol.rst}}''' for handling of data in space-time cube, including computation of gradients and hypercurvatures&lt;br /&gt;
&lt;br /&gt;
'''Willing to Mentor:''' co-mentor Helena Mitasova, [[User:Huhabla|Sören Gebbert]]&lt;br /&gt;
&lt;br /&gt;
=== Improved Python interface ===&lt;br /&gt;
&lt;br /&gt;
Design '''sophisticated Python scripting interface''' for GRASS based on [http://grass.osgeo.org/programming7/pythonlib.html GRASS Python Scripting Library]. This API should become more intuitive and more integrative&lt;br /&gt;
&lt;br /&gt;
GRASS GIS would gain even more attractiveness!&lt;br /&gt;
&lt;br /&gt;
'''Willing to Mentor:''' [[User:Huhabla|Sören Gebbert]]&lt;br /&gt;
&lt;br /&gt;
=== Other ===&lt;br /&gt;
&lt;br /&gt;
* See also the [https://trac.osgeo.org/grass/query?status=assigned&amp;amp;status=new&amp;amp;status=reopened&amp;amp;order=priority&amp;amp;col=id&amp;amp;col=summary&amp;amp;col=status&amp;amp;col=type&amp;amp;col=priority&amp;amp;col=milestone&amp;amp;col=component&amp;amp;type=enhancement GRASS wish list]&lt;br /&gt;
&lt;br /&gt;
# Implement selected modules (in C/C++) for geospatial analysis (kriging, etc.) based on [http://hpgl.aoizora.org/ HPGL] library (see also [http://hub.qgis.org/projects/quantum-gis/wiki/Python_Plugin_Ideas#Add-and-R-Free-geostatistic-toolbox-using-HPGL QGIS plugin wish]).&lt;br /&gt;
# Design and implement modern '''metadata management system''' for GRASS to support [http://www.opengeospatial.org/standards/cat OGC CSW] and INSPIRE discovery a view services&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
# Design '''GRASS toolboxes environment''', see [[GRASS repository layout proposal]] for detailed information. This would also include general clean up and organization of existing GRASS modules in trunk and add-ons.&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
# ''Your idea here''&lt;br /&gt;
&lt;br /&gt;
'''Willing to Mentor:''' Wolf Bergenheim (Python API, metadata management), [[User:Landa|Martin Landa]] (for HPGL) (''your name here'')&lt;br /&gt;
&lt;br /&gt;
== Guidelines for Students ==&lt;br /&gt;
&lt;br /&gt;
How do you maximize your chances of getting picked? First read the [http://code.google.com/p/google-summer-of-code/wiki/AdviceforStudents Google SoC FAQ]. Then talk to us about your idea. Try emailing our [http://lists.osgeo.org/mailman/listinfo/grass-dev dev-mailing list], or come and talk to us in [[IRC]] (#grass). You can also reach the mentors directly by emailing:&lt;br /&gt;
* [http://lists.osgeo.org/mailman/listinfo/soc The OSGeo SoC mailing list]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
 * Anne (&amp;lt;tt&amp;gt; @ &amp;lt;/tt&amp;gt;)&lt;br /&gt;
 * Hamish (&amp;lt;tt&amp;gt;hamish_b at yahoo com&amp;lt;/tt&amp;gt;)&lt;br /&gt;
 * Wolf Bergenheim (&amp;lt;tt&amp;gt;wolf+grass at bergenheim.net&amp;lt;/tt&amp;gt;)&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* If you are thinking about applying, do make a point of reading the &amp;quot;[http://google-opensource.blogspot.co.nz/2011/02/flip-bits-not-burgers-student-guide.html Flip bits not Burgers: The Student's Guide to the Summer of Code]&amp;quot; eBook&lt;br /&gt;
&lt;br /&gt;
=== Getting started with GRASS coding ===&lt;br /&gt;
&lt;br /&gt;
* The source code is maintained in a [http://trac.osgeo.org/grass/browser/grass/trunk SVN server] which is easy to browse&lt;br /&gt;
&lt;br /&gt;
* Please review the submitting files for our coding standards&lt;br /&gt;
** {{src|SUBMITTING|branch=trunk}} for C coding rules&lt;br /&gt;
** {{src|SUBMITTING_PYTHON|branch=trunk}} for Python coding rules&lt;br /&gt;
** {{src|SUBMITTING_DOCS|branch=trunk}} for Documentantion coding rules&lt;br /&gt;
&lt;br /&gt;
* There is lots of good info at the [http://trac.osgeo.org/grass/wiki GRASS Developer's wiki]&lt;br /&gt;
: See also the [[Development|development section]] of the GRASS user's wiki&lt;br /&gt;
&lt;br /&gt;
== Guidelines for Mentors ==&lt;br /&gt;
&lt;br /&gt;
* Un(?)official book: http://www.booki.cc/gsoc-mentoring/&lt;br /&gt;
* Some more hints on the [http://wiki.osgeo.org/wiki/Google_Summer_of_Code_2012_Administrative#Links OSGeo wiki]&lt;br /&gt;
&lt;br /&gt;
== Accepted Ideas ==&lt;br /&gt;
&lt;br /&gt;
# ''Python high level map interaction for GRASS GIS'' ([http://www.google-melange.com/gsoc/project/google/gsoc2012/zarch/11001 abstract])&lt;br /&gt;
#: Student: Pietro Zambelli&lt;br /&gt;
#: Mentor: Sören Gebbert&lt;br /&gt;
#: Backup mentors: Luca Delucchi, Martin Landa&lt;br /&gt;
#: Wiki page: [[GRASS SoC Ideas 2012/High level map interaction]]&lt;br /&gt;
# ''GRASS GIS WxGui front end for vector analysis modules'' ([http://www.google-melange.com/gsoc/project/google/gsoc2012/turek/38001 abstract])&lt;br /&gt;
#: Student: Stepan Turek&lt;br /&gt;
#: Mentor: Martin Landa&lt;br /&gt;
#: Backup mentor: Markus Metz&lt;br /&gt;
#: Wiki page: wiki/blog page maintained by the student (typically in this GRASS wiki, or the trac development wiki, with weekly progress reports)&lt;br /&gt;
# ''Image Segmentation in GRASS GIS'' ([http://www.google-melange.com/gsoc/project/google/gsoc2012/emomsen/20001 abstract])&lt;br /&gt;
#: Student: Eric Momsen&lt;br /&gt;
#: Mentor: Markus Metz&lt;br /&gt;
#: Backup mentors: Moritz Lennert, Pierre Roudier&lt;br /&gt;
#: Wiki page: wiki/blog page maintained by the student (typically in this GRASS wiki, or the trac development wiki, with weekly progress reports)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
# ''Project name''&lt;br /&gt;
#: Student: Someone else's name here&lt;br /&gt;
#: Mentor: Their mentor's name here&lt;br /&gt;
#: Backup mentor: Their backup mentor's name here&lt;br /&gt;
#: Wiki page: wiki page maintained by them (typically in this GRASS wiki, or the trac development wiki)&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Development]]&lt;br /&gt;
[[Category:Community]]&lt;br /&gt;
[[Category:GSoC]]&lt;/div&gt;</summary>
		<author><name>⚠️PierreRoudier</name></author>
	</entry>
	<entry>
		<id>https://grasswiki.osgeo.org/w/index.php?title=GRASS_and_Python&amp;diff=13591</id>
		<title>GRASS and Python</title>
		<link rel="alternate" type="text/html" href="https://grasswiki.osgeo.org/w/index.php?title=GRASS_and_Python&amp;diff=13591"/>
		<updated>2011-06-01T04:29:07Z</updated>

		<summary type="html">&lt;p&gt;⚠️PierreRoudier: /* Python extensions for GRASS GIS */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;''(for discussions on the new GRASS GUI, see [[GRASS GUI|here]])''&lt;br /&gt;
&lt;br /&gt;
==Python SIGs==&lt;br /&gt;
Python Special Interest Groups are focused collaborative efforts to develop, improve, or maintain specific Python resources. Each SIG has a charter, a coordinator, a mailing list, and a directory on the Python website. SIG membership is informal, defined by subscription to the SIG's mailing list. Anyone can join a SIG, and participate in the development discussions via the SIG's mailing list. Below is the list of currently active Python SIGs, with links to their resources. &lt;br /&gt;
&lt;br /&gt;
See more at http://www.python.org/community/sigs/&lt;br /&gt;
&lt;br /&gt;
==Writing Python scripts in GRASS==&lt;br /&gt;
&lt;br /&gt;
Python is a programming language which is more powerful than shell scripting but easier and more forgiving than C.&lt;br /&gt;
The Python script can contain simple module description definitions which will be processed with {{cmd|g.parser}}, as shown in the example below. In this way with no extra coding a GUI can be built, inputs checked, and a skeleton help page can be generated automatically. In addition it adds links to the GRASS message translation system.&lt;br /&gt;
For code which needs access to the power of C, you can access the GRASS C library functions via the SWIG interface (note 7/2010: swig stuff to be superseded with 'ctypes' soon).&lt;br /&gt;
&lt;br /&gt;
* GRASS Python interface to library functions: http://grass.osgeo.org/programming6/swig/&lt;br /&gt;
* GRASS Python scripting library: http://grass.osgeo.org/programming6/pythonlib.html&lt;br /&gt;
&lt;br /&gt;
Code style: Have a look at [http://trac.osgeo.org/grass/browser/grass/trunk/SUBMITTING_PYTHON SUBMITTING_PYTHON].&lt;br /&gt;
&lt;br /&gt;
=== Creating Python scripts that call GRASS functionality from outside ===&lt;br /&gt;
&lt;br /&gt;
In order to use GRASS from outside, some environment variables have to be set.&lt;br /&gt;
&lt;br /&gt;
==== MS-Windows ====&lt;br /&gt;
&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;
Some hints:&lt;br /&gt;
&lt;br /&gt;
# The Python interpreter (python.exe) needs to be in the PATH&lt;br /&gt;
# Python needs to be associated with the .py extension&lt;br /&gt;
# PATHEXT needs to include .py if you want to be able to omit the extension&lt;br /&gt;
# PYTHONPATH needs to be set to %WINGISBASE%\etc\python&lt;br /&gt;
&lt;br /&gt;
1-3 should be taken care of by the Python installer. 4 needs to be done by the startup (currently, this doesn't appear to be the case on MS-Windows).&lt;br /&gt;
&lt;br /&gt;
Note:&lt;br /&gt;
&lt;br /&gt;
Currently (as of 22 Feb 2011) if you want to use Python for scripting GRASS on Windows, the best solution is to delete the bundled version of Python 2.5 from the GRASS installation, install Python and the required add-ons (wxPython, NumPy, PyWin32) from their official installers,&lt;br /&gt;
then edit the GRASS start-up script to remove any references to the bundled version.&lt;br /&gt;
&lt;br /&gt;
==== Linux ====&lt;br /&gt;
&lt;br /&gt;
The variables are set like this:&lt;br /&gt;
&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;
 # for parallel session management, we use process ID (PID) as lock file number:&lt;br /&gt;
 export GIS_LOCK=$$&lt;br /&gt;
 # path to GRASS settings file&lt;br /&gt;
 export GISRC=&amp;quot;$HOME/.grassrc6&amp;quot;&lt;br /&gt;
&lt;br /&gt;
=== Running external commands from Python ===&lt;br /&gt;
For information on running external commands from Python, see:&lt;br /&gt;
http://docs.python.org/lib/module-subprocess.html&lt;br /&gt;
&lt;br /&gt;
Avoid using the older os.* functions. Section 17.1.3 lists equivalents&lt;br /&gt;
using the Popen() interface, which is more robust (particularly on&lt;br /&gt;
Windows).&lt;br /&gt;
&lt;br /&gt;
=== Examples ===&lt;br /&gt;
&lt;br /&gt;
==== Display example ====&lt;br /&gt;
Example of Python script, which is processed by g.parser:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
#!/usr/bin/env python&lt;br /&gt;
#&lt;br /&gt;
############################################################################&lt;br /&gt;
#&lt;br /&gt;
# MODULE:      d.shadedmap&lt;br /&gt;
# AUTHOR(S):   Unknown; updated to GRASS 5.7 by Michael Barton&lt;br /&gt;
#              Converted to Python by Glynn Clements&lt;br /&gt;
# PURPOSE:     Uses d.his to drape a color raster over a shaded relief map&lt;br /&gt;
# COPYRIGHT:   (C) 2004,2008,2009 by the GRASS Development Team&lt;br /&gt;
#&lt;br /&gt;
#              This program is free software under the GNU General Public&lt;br /&gt;
#              License (&amp;gt;=v2). Read the file COPYING that comes with GRASS&lt;br /&gt;
#              for details.&lt;br /&gt;
#&lt;br /&gt;
#############################################################################&lt;br /&gt;
&lt;br /&gt;
#%Module&lt;br /&gt;
#% description: Drapes a color raster over a shaded relief map using d.his&lt;br /&gt;
#%End&lt;br /&gt;
#%option&lt;br /&gt;
#% key: reliefmap&lt;br /&gt;
#% type: string&lt;br /&gt;
#% gisprompt: old,cell,raster&lt;br /&gt;
#% description: Name of shaded relief or aspect map&lt;br /&gt;
#% required : yes&lt;br /&gt;
#%end&lt;br /&gt;
#%option&lt;br /&gt;
#% key: drapemap&lt;br /&gt;
#% type: string&lt;br /&gt;
#% gisprompt: old,cell,raster&lt;br /&gt;
#% description: Name of raster to drape over relief map&lt;br /&gt;
#% required : yes&lt;br /&gt;
#%end&lt;br /&gt;
#%option&lt;br /&gt;
#% key: brighten&lt;br /&gt;
#% type: integer&lt;br /&gt;
#% description: Percent to brighten&lt;br /&gt;
#% options: -99-99&lt;br /&gt;
#% answer: 0&lt;br /&gt;
#%end&lt;br /&gt;
&lt;br /&gt;
import sys&lt;br /&gt;
from grass.script import core as grass&lt;br /&gt;
&lt;br /&gt;
def main():&lt;br /&gt;
    drape_map = options['drapemap']&lt;br /&gt;
    relief_map = options['reliefmap']&lt;br /&gt;
    brighten = options['brighten']&lt;br /&gt;
    ret = grass.run_command(&amp;quot;d.his&amp;quot;, h_map = drape_map,  i_map = relief_map, brighten = brighten)&lt;br /&gt;
    sys.exit(ret)&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    options, flags = grass.parser()&lt;br /&gt;
    main()&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Parsing the options and flags  ====&lt;br /&gt;
&lt;br /&gt;
grass.parser() is an interface to g.parser, and allows to parse the options and flags passed to your script on the command line. It is to be called at the top-level:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    options, flags = grass.parser()&lt;br /&gt;
    main()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Global variables &amp;quot;options&amp;quot; and &amp;quot;flags&amp;quot; are Python dictionaries containing the options/flags values, keyed by lower-case option/flag names. The values in &amp;quot;options&amp;quot; are strings, those in &amp;quot;flags&amp;quot; are Python booleans. All those variables have to be previously declared in the header of your script.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
&amp;gt;&amp;gt;&amp;gt; options, flags = grass.parser()&lt;br /&gt;
&amp;gt;&amp;gt;&amp;gt; options&lt;br /&gt;
{'input': 'my_map', 'output': 'map_out', 'option1': '21.472', 'option2': ''}&lt;br /&gt;
&amp;gt;&amp;gt;&amp;gt; flags&lt;br /&gt;
{'c': True, 'm': False}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Example for embedding r.mapcalc (map algebra) ====&lt;br /&gt;
&lt;br /&gt;
grass.mapcalc() accepts a template string followed by keyword&lt;br /&gt;
arguments for the substitutions, e.g. (code snippets):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
grass.mapcalc(&amp;quot;${out} = ${rast1} + ${rast2}&amp;quot;,&lt;br /&gt;
              out = options['output'],&lt;br /&gt;
              rast1 = options['raster1'],&lt;br /&gt;
              rast2 = options['raster2'])&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
''Best practice'': first copy all of the options[] into separate variables at the beginning of main(), i.e.:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
def main():&lt;br /&gt;
    output = options['output']&lt;br /&gt;
    raster1 = options['raster1']&lt;br /&gt;
    raster2 = options['raster2']&lt;br /&gt;
 &lt;br /&gt;
    ...&lt;br /&gt;
 &lt;br /&gt;
    grass.mapcalc(&amp;quot;${out} = ${rast1} + ${rast2}&amp;quot;,&lt;br /&gt;
                  out = output,&lt;br /&gt;
                  rast1 = raster1,&lt;br /&gt;
                  rast2 = raster2)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Example for parsing category numbers ====&lt;br /&gt;
&lt;br /&gt;
Q: How to obtain the number of cells of a certain category?&lt;br /&gt;
&lt;br /&gt;
A: It is recommended to use pipe_command() and parse the output, e.g.:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
       p = grass.pipe_command('r.stats',flags='c',input='map')&lt;br /&gt;
       result = {}&lt;br /&gt;
       for line in p.stdout:&lt;br /&gt;
           val,count = line.strip().split()&lt;br /&gt;
           result[int(val)] = int(count)&lt;br /&gt;
       p.wait()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Example for getting the region's number of rows and columns ====&lt;br /&gt;
&lt;br /&gt;
Q: How to obtain the number of rows and columns of the current region?&lt;br /&gt;
&lt;br /&gt;
A: It is recommended to use the &amp;quot;grass.region()&amp;quot; function which will create a dictionary with values for extents and resolution, e.g.:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source 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;
############################################################################&lt;br /&gt;
#&lt;br /&gt;
# MODULE:       g.region.resolution&lt;br /&gt;
# AUTHOR(S):    based on a post at GRASS-USER mailing list [1]               &lt;br /&gt;
# PURPOSE:	Parses &amp;quot;g.region -g&amp;quot;, prints out number of rows, cols&lt;br /&gt;
# COPYLEFT:     ;-)&lt;br /&gt;
# COMMENT:      ...a lot of comments to be easy-to-read for/by beginners&lt;br /&gt;
#&lt;br /&gt;
#############################################################################&lt;br /&gt;
#&lt;br /&gt;
#%Module&lt;br /&gt;
#% description: Print number of rows, cols of current geographic region&lt;br /&gt;
#% keywords: region&lt;br /&gt;
#%end&lt;br /&gt;
&lt;br /&gt;
# importing required modules&lt;br /&gt;
import sys # the sys module [2]&lt;br /&gt;
from grass.script import core as grass # the core module [3]&lt;br /&gt;
&lt;br /&gt;
# information about imported modules can be obtained using the dir() function&lt;br /&gt;
# e.g.: dir(sys)&lt;br /&gt;
&lt;br /&gt;
# define the &amp;quot;main&amp;quot; function: get number of rows, cols of region&lt;br /&gt;
def main():&lt;br /&gt;
    &lt;br /&gt;
    # #######################################################################&lt;br /&gt;
    # the following commented code works but is kept only for learning purposes&lt;br /&gt;
     &lt;br /&gt;
    ## assigning the output of the command &amp;quot;g.region -g&amp;quot; in a string called &amp;quot;return_rows_x_cols&amp;quot;&lt;br /&gt;
    # return_rows_x_cols = grass.read_command('g.region', flags = 'g')&lt;br /&gt;
    &lt;br /&gt;
    ## parsing arguments of interest (rows, cols) in a dictionary named &amp;quot;rows_x_cols&amp;quot;&lt;br /&gt;
    # rows_x_cols = grass.parse_key_val(return_rows_x_cols)&lt;br /&gt;
    &lt;br /&gt;
    ## selectively print rows, cols from the dictionary &amp;quot;rows_x_cols&amp;quot;&lt;br /&gt;
    # print 'rows=%d \ncols=%d' % (int(rows_x_cols['rows']), int(rows_x_cols['cols']))&lt;br /&gt;
    &lt;br /&gt;
    # #######################################################################&lt;br /&gt;
    &lt;br /&gt;
    # faster/ easier way: use of the &amp;quot;grass.region()&amp;quot; function&lt;br /&gt;
    gregion = grass.region()&lt;br /&gt;
    rows = gregion['rows']&lt;br /&gt;
    cols = gregion['cols']&lt;br /&gt;
    &lt;br /&gt;
    # print rows, cols properly formated &lt;br /&gt;
    print 'rows=%d \ncols=%d' % (rows, cols)&lt;br /&gt;
&lt;br /&gt;
# this &amp;quot;if&amp;quot; condition instructs execution of code contained in this script, *only* if the script is being executed directly &lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;: # this allows the script to be used as a module in other scripts or as a standalone script&lt;br /&gt;
    options, flags = grass.parser() #&lt;br /&gt;
    sys.exit(main()) #&lt;br /&gt;
&lt;br /&gt;
# Links&lt;br /&gt;
# [1] http://n2.nabble.com/Getting-rows-cols-of-a-region-in-a-script-tp2787474p2787509.html&lt;br /&gt;
# [2] http://www.python.org/doc/2.5.2/lib/module-sys.html&lt;br /&gt;
# [3] http://download.osgeo.org/grass/grass6_progman/pythonlib.html#pythonCore&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Managing mapsets ====&lt;br /&gt;
&lt;br /&gt;
To check if a certain mapset exists in the active location, use:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
       grass.script.mapsets(False)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
... returns a list of mapsets in the current location.&lt;br /&gt;
&lt;br /&gt;
==== r.mapcalc example ====&lt;br /&gt;
&lt;br /&gt;
Example of Python script, which is processed by {{cmd|g.parser}}:&lt;br /&gt;
&lt;br /&gt;
The shell script line:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
  r.mapcalc &amp;quot;MASK = if(($cloudResampName &amp;lt; 0.01000),1,null())&amp;quot;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
would be written like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
       import grass.script as grass&lt;br /&gt;
&lt;br /&gt;
       ...&lt;br /&gt;
&lt;br /&gt;
       grass.mapcalc(&amp;quot;MASK=if(($cloudResampName &amp;lt; 0.01000),1,null())&amp;quot;,&lt;br /&gt;
                     cloudResampName = cloudResampName)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The first argument to the mapcalc function is a template (see the Python library documentation for [http://docs.python.org/library/string.html string.Template]). Any keyword arguments (other than quiet, verbose or overwrite) specify substitutions.&lt;br /&gt;
&lt;br /&gt;
==== Using output from GRASS modules in the script ====&lt;br /&gt;
&lt;br /&gt;
Sometimes you need to use the output of a module for the next step. There are dedicated functions to obtain the result of, for example, a statistical analysis.&lt;br /&gt;
&lt;br /&gt;
Example: get the range of a raster map and use it in {{cmd|r.mapcalc}}. Here you can use &amp;lt;code&amp;gt;grass.script.raster_info()&amp;lt;/code&amp;gt;, e.g.:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
       import grass.script as grass&lt;br /&gt;
&lt;br /&gt;
       max = grass.raster_info(inmap)['max']&lt;br /&gt;
       grass.mapcalc(&amp;quot;$outmap = $inmap / $max&amp;quot;,&lt;br /&gt;
                     inmap = inmap, outmap = outmap, max = max)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Calling a GRASS module in Python  ====&lt;br /&gt;
&lt;br /&gt;
Imagine, you wanted to execute this command in Python:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
  r.profile -g input=mymap output=newfile profile=12244.256,-295112.597,12128.012,-295293.77&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
All arguments except the first (which is a flag) are keyword arguments, i.e. &amp;lt;tt&amp;gt;arg = val&amp;lt;/tt&amp;gt;. For the flag, use &amp;lt;tt&amp;gt;flags = 'g'&amp;lt;/tt&amp;gt; (note that &amp;quot;-g&amp;quot; would be the negative of a Python variable named &amp;quot;g&amp;quot;!). So:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
       grass.run_command(&lt;br /&gt;
               'r.profile',&lt;br /&gt;
               input = input_map,&lt;br /&gt;
               output = output_file,&lt;br /&gt;
               profile = [12244.256,-295112.597,12128.012,-295293.77]&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
or:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
               profile = [(12244.256,-295112.597),(12128.012,-295293.77)]&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
i.e. you need to provide the keyword, and the argument must be a valid Python expression. Function &amp;lt;code&amp;gt;run_command()&amp;lt;/code&amp;gt; etc accept lists and tuples.&lt;br /&gt;
&lt;br /&gt;
'''Differences between ''run_command()'' and ''read_command()'':'''&lt;br /&gt;
&lt;br /&gt;
* run_command() executes the command and waits for it to terminate; it doesn't redirect any of the standard streams.&lt;br /&gt;
* read_command() executes the command with stdout redirected to a pipe, and reads everything written to it. Once the command terminates, it returns the data written to stdout as a string.&lt;br /&gt;
&lt;br /&gt;
'''How to retrieve error messages from ''read_command()'':'''&lt;br /&gt;
&lt;br /&gt;
None of the existing *_command functions redirect stderr. You can do so with e.g.:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
def read2_command(*args, **kwargs):&lt;br /&gt;
   kwargs['stdout'] = grass.PIPE&lt;br /&gt;
   kwargs['stderr'] = grass.PIPE&lt;br /&gt;
   ps = grass.start_command(*args, **kwargs)&lt;br /&gt;
   return ps.communicate()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This behaves like read_command() except that it returns a tuple of (stdout,stderr) rather than just stdout.&lt;br /&gt;
&lt;br /&gt;
==== Path to GISDBASE ====&lt;br /&gt;
&lt;br /&gt;
In order to a avoid hardcoded paths to GRASS mapset files like the SQLite DB file, you can get the GISDBASE variable from the environment:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
       import grass.script as grass&lt;br /&gt;
       import os.path&lt;br /&gt;
&lt;br /&gt;
       env = grass.gisenv()&lt;br /&gt;
&lt;br /&gt;
       gisdbase = env['GISDBASE']&lt;br /&gt;
       location = env['LOCATION_NAME']&lt;br /&gt;
       mapset = env['MAPSET']&lt;br /&gt;
&lt;br /&gt;
       path = os.path.join(gisdbase, location, mapset, 'sqlite.db')&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Python extensions for GRASS GIS==&lt;br /&gt;
=== wxPython GUI development for GRASS ===&lt;br /&gt;
&lt;br /&gt;
* See the [[wxGUI]] wiki page&lt;br /&gt;
&lt;br /&gt;
=== GRASS Python Scripting Library ===&lt;br /&gt;
&lt;br /&gt;
See [http://grass.osgeo.org/programming7/pythonlib.html GRASS Python Scripting Library] (Programmer's manual). See also [[Converting Bash scripts to Python]], and [http://trac.osgeo.org/grass/browser/grass/trunk/scripts sample Python scripts in GRASS 7]&lt;br /&gt;
&lt;br /&gt;
==== Uses for read, feed and pipe, start and exec commands ====&lt;br /&gt;
&lt;br /&gt;
All of the *_command functions use make_command to construct a command&lt;br /&gt;
line for a program which uses the GRASS parser. Most of them then pass&lt;br /&gt;
that command line to ''subprocess.Popen()'' via ''start_command()'', except&lt;br /&gt;
for ''exec_command()'' which uses ''os.execvpe()''.&lt;br /&gt;
&lt;br /&gt;
[To be precise, they use grass.Popen(), which just calls&lt;br /&gt;
subprocess.Popen() with shell=True on Windows and shell=False&lt;br /&gt;
otherwise. On Windows, you need to use shell=True to be able to&lt;br /&gt;
execute scripts (including batch files); shell=False only works with&lt;br /&gt;
binary executables.]&lt;br /&gt;
&lt;br /&gt;
start_command() separates the arguments into those which&lt;br /&gt;
subprocess.Popen() understands and the rest. The rest are passed to&lt;br /&gt;
make_command() to construct a command line which is passed as the&lt;br /&gt;
&amp;quot;args&amp;quot; parameter to subprocess.Popen().&lt;br /&gt;
&lt;br /&gt;
In other words, start_command() is a GRASS-oriented interface to&lt;br /&gt;
subprocess.Popen(). It should be suitable for any situation where you&lt;br /&gt;
would use subprocess.Popen() to execute a normal GRASS command (one&lt;br /&gt;
which uses the GRASS parser, which is almost all of them; the main&lt;br /&gt;
exception is r.mapcalc in 6.x).&lt;br /&gt;
&lt;br /&gt;
Most of the others are convenience wrappers around start_command(), for common use cases.&lt;br /&gt;
&lt;br /&gt;
* run_command() calls the wait() method on the process, so it doesn't return until the command has finished, and returns the command's exit code. Similar to system().&lt;br /&gt;
&lt;br /&gt;
* pipe_command() calls start_command() with stdout=PIPE and returns the process object. You can use the process' .stdout member to read the command's stdout. Similar to popen(..., &amp;quot;r&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
* feed_command() calls start_command() with stdin=PIPE and returns the process object. You can use the process' .stdin member to write to the command's stdout. Similar to popen(..., &amp;quot;w&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
* read_command() calls pipe_command(), reads the data from the command's stdout, and returns it as a string. Similar to `backticks` in the shell.&lt;br /&gt;
&lt;br /&gt;
* write_command() calls feed_command(), sends the string specified by the &amp;quot;stdin&amp;quot; argument to the command's stdin, waits for the command to finish and returns its exit code. Similar to &amp;quot;echo ... | command&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
* parse_command() calls read_command() and parses its output as key-value pairs. Useful for obtaining information from g.region, g.proj, r.info, etc.&lt;br /&gt;
&lt;br /&gt;
* exec_command() doesn't use start_command() but os.execvpe(). This causes the specified command to replace the current program (i.e. the Python script), so exec_command() never returns. Similar to bash's &amp;quot;exec&amp;quot; command. This can be useful if the script is a &amp;quot;wrapper&amp;quot; around a single command, where you construct the command line and execute the command as the final step.&lt;br /&gt;
&lt;br /&gt;
If you have any other questions, you might want to look at the code ($GISBASE/etc/python/grass/script/core.py). Most of these functions are only a few lines long.&lt;br /&gt;
&lt;br /&gt;
==== Interfacing with NumPy ====&lt;br /&gt;
&lt;br /&gt;
''Glynn writes:''&lt;br /&gt;
&lt;br /&gt;
The {{api|pythonlib.html#pythonArray|grass.script.array}} module defines a {{api|classpython_1_1array_1_1array.html|class array}} which is a subclass of [http://docs.scipy.org/doc/numpy/reference/generated/numpy.memmap.html numpy.memmap] with &amp;lt;code&amp;gt;.read()&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;.write()&amp;lt;/code&amp;gt; methods to read/write the underlying file via {{cmd|r.out.bin}}/{{cmd|r.in.bin}}.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
    import grass.script.array as garray&lt;br /&gt;
    a = garray.array()&lt;br /&gt;
    a.read(&amp;quot;elevation.dem&amp;quot;)&lt;br /&gt;
    b = garray.array()&lt;br /&gt;
    b[...] = (a / 50).astype(int) * 50  # or whatever&lt;br /&gt;
    b.write(&amp;quot;elev.50m&amp;quot;)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The size of the array is taken from the current region.&lt;br /&gt;
&lt;br /&gt;
The main drawback of using numpy is that you're limited by available&lt;br /&gt;
memory. Using a subclass of &amp;lt;code&amp;gt;numpy.memmap&amp;lt;/code&amp;gt; lets you use files which may&lt;br /&gt;
be much larger, but processing the entire array in one go is likely to&lt;br /&gt;
produce in-memory results of a similar size.&lt;br /&gt;
&lt;br /&gt;
One may also use the scipy matlab interface:&lt;br /&gt;
    &lt;br /&gt;
    ### SH: in GRASS ###&lt;br /&gt;
    r.out.mat input=elevation output=elev.mat&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
    ### PY ###&lt;br /&gt;
    import scipy.io as sio&lt;br /&gt;
    # load data&lt;br /&gt;
    elev = sio.loadmat('elev.mat')&lt;br /&gt;
    # retrive the actual array. the data set contains also the spatial reference&lt;br /&gt;
    elev.get('map_data')&lt;br /&gt;
    data = elev.get('map_data')&lt;br /&gt;
    # a first simple plot&lt;br /&gt;
    import pylab&lt;br /&gt;
    pylab.plot(data)&lt;br /&gt;
    pylab.show()&lt;br /&gt;
    # the contour plot&lt;br /&gt;
    pylab.contour(data)&lt;br /&gt;
    # obviously data needs to ne reversed&lt;br /&gt;
    import numpy as np&lt;br /&gt;
    data_rev = data[::-1]&lt;br /&gt;
    pylab.contour(data_rev)&lt;br /&gt;
    # =&amp;gt; this is a quick plot. basemap mapping may provide a nicer map!&lt;br /&gt;
    #######&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Testing and installing Python extensions ===&lt;br /&gt;
&lt;br /&gt;
==== Debugging ====&lt;br /&gt;
&lt;br /&gt;
Make sure the script is executable:&lt;br /&gt;
&lt;br /&gt;
    chmod +x /path/to/my.extension.py&lt;br /&gt;
&lt;br /&gt;
During development, a Python script can be debugged using the Python Debugger (pdb):&lt;br /&gt;
&lt;br /&gt;
    python -m pdb /path/to/my.extension.py input=my_input_layer output=my_output_layer option=value -f&lt;br /&gt;
&lt;br /&gt;
==== Installation ====&lt;br /&gt;
&lt;br /&gt;
Once you're happy with your script, you can put it in the scripts/ folder of your GRASS install. To do so, first create a directory named after your extension, then create a Makefile for it, and a HTML man page:&lt;br /&gt;
&lt;br /&gt;
    cd /path/to/grass_src/&lt;br /&gt;
    cd scripts&lt;br /&gt;
    ls # It is useful to check out the existing scripts and their structure&lt;br /&gt;
    mkdir my.extension&lt;br /&gt;
    cd my.extension&lt;br /&gt;
    cp path/to/my.extension.py .&lt;br /&gt;
    touch my.extension.html&lt;br /&gt;
    touch Makefile&lt;br /&gt;
&lt;br /&gt;
Next step is to edit the Makefile. It is a very simple text file, the only thing to check is to put the right extension name (WITHOUT the .py file extension) after PGM:&lt;br /&gt;
&lt;br /&gt;
    MODULE_TOPDIR = ../..&lt;br /&gt;
    &lt;br /&gt;
    PGM = my.extension&lt;br /&gt;
    &lt;br /&gt;
    include $(MODULE_TOPDIR)/include/Make/Script.make&lt;br /&gt;
    &lt;br /&gt;
    default: script&lt;br /&gt;
&lt;br /&gt;
The HTML file would be generated automatically. If you want to add more precisions in it, you can do it (just make sure you start at DESCRIPTION. See existing scripts.)&lt;br /&gt;
&lt;br /&gt;
You can then run &amp;quot;make&amp;quot; within the my.extension folder. Running &amp;quot;make&amp;quot; in the extension directory places the resulting files in the staging directory (path/to/grass_src/dist.&amp;lt;YOUR_ARCH&amp;gt;/). If you're running GRASS from the staging directory (/path/to/grass_src/bin.&amp;lt;YOUR_ARCH&amp;gt;/grass7), subsequent commands will used the updated files. &lt;br /&gt;
&lt;br /&gt;
    # in your extension directory (/path/to/grass_src/scripts/my.extension/)&lt;br /&gt;
    make&lt;br /&gt;
    # Starting GRASS from the staging directory&lt;br /&gt;
    /path/to/grass_src/bin.&amp;lt;YOUR_ARCH&amp;gt;/grass7&lt;br /&gt;
    my.extension help&lt;br /&gt;
&lt;br /&gt;
You can also run &amp;quot;make install&amp;quot; from the top level directory of your GRASS install (say /usr/local/src/grass_trunk/). Running &amp;quot;make install&amp;quot; from the top level just copies the whole of the dist.&amp;lt;YOUR_ARCH&amp;gt;/ directory to the installation directory (e.g. /usr/local/grass70) and the bin.&amp;lt;YOUR_ARCH&amp;gt;/grass70 bin file to the bin directory (e.g. /usr/local/bin), and fixes any embedded paths in scripts and configuration files.&lt;br /&gt;
&lt;br /&gt;
    cd /path/to/grass_src&lt;br /&gt;
    make install&lt;br /&gt;
    # Starting GRASS as usual would work and show your extension available&lt;br /&gt;
    grass7&lt;br /&gt;
    my.extension help&lt;br /&gt;
&lt;br /&gt;
=== Python Ctypes Interface ===&lt;br /&gt;
&lt;br /&gt;
This interface allows calling GRASS library functions from Python scripts. See [[Python Ctypes Examples]] for details.&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
&lt;br /&gt;
* GRASS 7: [http://trac.osgeo.org/grass/browser/grass/trunk/doc/python/raster_example_ctypes.py raster], [http://trac.osgeo.org/grass/browser/grass/trunk/doc/python/vector_example_ctypes.py vector] example&lt;br /&gt;
&lt;br /&gt;
=== Python SWIG interface ===&lt;br /&gt;
&lt;br /&gt;
  Warning: The GRASS-SWIG interface isn't particularly stable and well understood. Please consider to use the Python ctypes GRASS above.&lt;br /&gt;
&lt;br /&gt;
There is a prototype GRASS-SWIG interface available (thanks to Sajith VK), find it in GRASS 6-CVS: '''swig/python/'''. Draft documentation is [http://download.osgeo.org/grass/grass6_progman/swig/ here]. It now wraps both raster and vector data C functions plus the general GIS (G_*()) functions.&lt;br /&gt;
&lt;br /&gt;
Background: [http://www.swig.org SWIG] (Simplified Wrapper and Interface Generator) is: &lt;br /&gt;
&lt;br /&gt;
* A compiler that turns ANSI C/C++ declarations into scripting language interfaces.&lt;br /&gt;
* Completely automated (produces a fully working Python extension module). &lt;br /&gt;
* Language neutral. SWIG can also target Tcl, Perl, Guile, MATLAB (try PyLab+Matplotlib from python), etc... &lt;br /&gt;
* Attempts to eliminate the tedium of writing extension modules.&lt;br /&gt;
&lt;br /&gt;
==== Python-SWIG examples ====&lt;br /&gt;
&lt;br /&gt;
* Latest and greatest: [[http://trac.osgeo.org/grass/browser/grass/trunk/scripts GRASS 7 Python scripts]]&lt;br /&gt;
&lt;br /&gt;
* [[PythonSwigExamples|More complicated examples]]&lt;br /&gt;
&lt;br /&gt;
Sample script for GRASS 6 raster access (use within GRASS, Spearfish session):&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
#!/usr/bin/env python&lt;br /&gt;
&lt;br /&gt;
import os, sys&lt;br /&gt;
from grass.lib import grass&lt;br /&gt;
&lt;br /&gt;
if &amp;quot;GISBASE&amp;quot; not in os.environ:&lt;br /&gt;
    print &amp;quot;You must be in GRASS GIS to run this program.&amp;quot;&lt;br /&gt;
    sys.exit(1)&lt;br /&gt;
&lt;br /&gt;
if len(sys.argv)==2:&lt;br /&gt;
  input = sys.argv[1]&lt;br /&gt;
else:&lt;br /&gt;
  input = raw_input(&amp;quot;Raster Map Name? &amp;quot;)&lt;br /&gt;
&lt;br /&gt;
# initialize&lt;br /&gt;
grass.G_gisinit('')&lt;br /&gt;
&lt;br /&gt;
# find map in search path&lt;br /&gt;
mapset = grass.G_find_cell2(input, '')&lt;br /&gt;
&lt;br /&gt;
# determine the inputmap type (CELL/FCELL/DCELL) */&lt;br /&gt;
data_type = grass.G_raster_map_type(input, mapset)&lt;br /&gt;
&lt;br /&gt;
infd = grass.G_open_cell_old(input, mapset)&lt;br /&gt;
inrast = grass.G_allocate_raster_buf(data_type)&lt;br /&gt;
&lt;br /&gt;
rown = 0&lt;br /&gt;
while True:&lt;br /&gt;
    myrow = grass.G_get_raster_row(infd, inrast, rown, data_type)&lt;br /&gt;
    print rown, myrow[0:10]&lt;br /&gt;
    rown += 1&lt;br /&gt;
    if rown == 476:&lt;br /&gt;
        break&lt;br /&gt;
&lt;br /&gt;
grass.G_close_cell(inrast)&lt;br /&gt;
grass.G_free(cell)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Sample script for vector access (use within GRASS, Spearfish session):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
#!/usr/bin/python&lt;br /&gt;
&lt;br /&gt;
# run within GRASS Spearfish session&lt;br /&gt;
# run this before starting python to append module search path:&lt;br /&gt;
#   export PYTHONPATH=/usr/src/grass70/swig/python&lt;br /&gt;
#   check with &amp;quot;import sys; sys.path&amp;quot;&lt;br /&gt;
# or:&lt;br /&gt;
#   sys.path.append(&amp;quot;/usr/src/grass70/swig/python&amp;quot;)&lt;br /&gt;
# FIXME: install the grass bindings in $GISBASE/lib/ ?&lt;br /&gt;
&lt;br /&gt;
import os, sys&lt;br /&gt;
from grass.lib import grass&lt;br /&gt;
from grass.lib import vector as grassvect&lt;br /&gt;
&lt;br /&gt;
if &amp;quot;GISBASE&amp;quot; not in os.environ:&lt;br /&gt;
    print &amp;quot;You must be in GRASS GIS to run this program.&amp;quot;&lt;br /&gt;
    sys.exit(1)&lt;br /&gt;
&lt;br /&gt;
if len(sys.argv)==2:&lt;br /&gt;
  input = sys.argv[1]&lt;br /&gt;
else:&lt;br /&gt;
  input = raw_input(&amp;quot;Vector Map Name? &amp;quot;)&lt;br /&gt;
&lt;br /&gt;
# initialize&lt;br /&gt;
grass.G_gisinit('')&lt;br /&gt;
&lt;br /&gt;
# find map in search path&lt;br /&gt;
mapset = grass.G_find_vector2(input,'')&lt;br /&gt;
&lt;br /&gt;
# define map structure&lt;br /&gt;
map = grassvect.Map_info()&lt;br /&gt;
&lt;br /&gt;
# define open level (level 2: topology)&lt;br /&gt;
grassvect.Vect_set_open_level (2)&lt;br /&gt;
&lt;br /&gt;
# open existing map&lt;br /&gt;
grassvect.Vect_open_old(map, input, mapset)&lt;br /&gt;
&lt;br /&gt;
# query&lt;br /&gt;
print 'Vect map: ', input&lt;br /&gt;
print 'Vect is 3D: ', grassvect.Vect_is_3d (map)&lt;br /&gt;
print 'Vect DB links: ', grassvect.Vect_get_num_dblinks(map)&lt;br /&gt;
print 'Map Scale:  1:', grassvect.Vect_get_scale(map)&lt;br /&gt;
print 'Number of areas:', grassvect.Vect_get_num_areas(map)&lt;br /&gt;
&lt;br /&gt;
# close map&lt;br /&gt;
grassvect.Vect_close(map)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== TODO ====&lt;br /&gt;
&lt;br /&gt;
* Implement modules support in a Python class using --interface-description and a Python-XML parser. This should be a generic class with module's name as parameter, returning back an object which describes the module (description, flags, parameters, status of not/required). See [http://trac.osgeo.org/grass/browser/grass/trunk/gui/wxpython/ GRASS 6 wxPython interface] for inspiration. Important is to auto-generate the GRASS-Python class at compile time with a Python script.&lt;br /&gt;
&lt;br /&gt;
=== Python-GRASS add-ons ===&lt;br /&gt;
&lt;br /&gt;
Stand-alone addons:&lt;br /&gt;
&lt;br /&gt;
# Jáchym Čepický's G-ps.map, a GUI to typeset printable maps with ps.map (http://193.84.38.2/~jachym/index.py?cat=gpsmap)&lt;br /&gt;
# Jáchym Čepický's v.pydigit, a GUI to v.edit (http://les-ejk.cz/?cat=vpydigit)&lt;br /&gt;
# Jáchym Čepický's PyWPS, GRASS-Web Processing Service (http://pywps.wald.intevation.org)&lt;br /&gt;
&lt;br /&gt;
=== Using GRASS gui.tcl in Python ===&lt;br /&gt;
&lt;br /&gt;
Here is some example code to use the grass automatically generated guis in python code. This could (should) all be bundled up and abstracted away so that the implementation can be replaced later.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
import Tkinter&lt;br /&gt;
import os&lt;br /&gt;
&lt;br /&gt;
# Startup (once):&lt;br /&gt;
&lt;br /&gt;
tk = Tkinter.Tk()&lt;br /&gt;
tk.eval (&amp;quot;wm withdraw .&amp;quot;)&lt;br /&gt;
tk.eval (&amp;quot;source $env(GISBASE)/etc/gui.tcl&amp;quot;)&lt;br /&gt;
# Here you could do various things to change what the gui does&lt;br /&gt;
# See gui.tcl and README.GUI&lt;br /&gt;
&lt;br /&gt;
# Make a gui (per dialog)&lt;br /&gt;
# This sets up a window for the command.&lt;br /&gt;
# This can be different to integrate with tkinter:&lt;br /&gt;
tk.eval ('set path &amp;quot;.dialog$dlg&amp;quot;')&lt;br /&gt;
tk.eval ('toplevel .dialog$dlg')&lt;br /&gt;
# Load the code for this command:&lt;br /&gt;
fd = os.popen (&amp;quot;d.vect --tcltk&amp;quot;)&lt;br /&gt;
gui = fd.read()&lt;br /&gt;
# Run it&lt;br /&gt;
tk.eval(gui)&lt;br /&gt;
dlg = tk.eval('set dlg') # This is used later to get and set &lt;br /&gt;
&lt;br /&gt;
# Get the current command in the gui we just made:&lt;br /&gt;
currentcommand = tk.eval (&amp;quot;dialog_get_command &amp;quot; + dlg)&lt;br /&gt;
&lt;br /&gt;
# Set the command in the dialog we just made:&lt;br /&gt;
tk.eval (&amp;quot;dialog_set_command &amp;quot; + dlg + &amp;quot; {d.vect map=roads}&amp;quot;)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== FAQ ==&lt;br /&gt;
&lt;br /&gt;
* '''Q:''' Error message &amp;quot;execl() failed: Permission denied&amp;quot; - what to do?&lt;br /&gt;
: '''A:''' Be sure that the execute bit of the script is set.&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
&lt;br /&gt;
=== General guides ===&lt;br /&gt;
&lt;br /&gt;
* [http://en.wikibooks.org/wiki/Python_Programming/ Wikibook Python Programming]&lt;br /&gt;
* [http://www.poromenos.org/tutorials/python Quick Python tutorial] for programmers of other languages&lt;br /&gt;
*: [http://wiki.python.org/moin/BeginnersGuide/Programmers More Python tutorials] for programmers&lt;br /&gt;
* [http://www.python.org/dev/peps/pep-0008/ Python programming style guide]&lt;br /&gt;
* [http://wiki.python.org/moin/PythonEditors Python Editors]&lt;br /&gt;
&lt;br /&gt;
=== Programming ===&lt;br /&gt;
&lt;br /&gt;
* Python and GRASS:&lt;br /&gt;
** GRASS Python interface to library functions: http://download.osgeo.org/grass/grass6_progman/swig/ based on SWIG http://www.swig.org/&lt;br /&gt;
** GRASS Python scripting library: http://download.osgeo.org/grass/grass6_progman/pythonlib.html&lt;br /&gt;
** PyWPS, GRASS-Web Processing Service http://pywps.wald.intevation.org&lt;br /&gt;
&lt;br /&gt;
* Python and OSGeo:&lt;br /&gt;
** [http://wiki.osgeo.org/wiki/OSGeo_Python_Library OSGeo Python Library]&lt;br /&gt;
&lt;br /&gt;
* Python and GDAL/OGR:&lt;br /&gt;
** [http://mapserver.gis.umn.edu/community/conferences/MUM3/workshop/python Open Source Python GIS Hacks Mum'03]&lt;br /&gt;
** http://hobu.biz/software/OSGIS_Hacks - Python OSGIS Hacks '05&lt;br /&gt;
** http://zcologia.com/news/categorylist_html?cat_id=8&lt;br /&gt;
** http://www.perrygeo.net/wordpress/?p=4&lt;br /&gt;
&lt;br /&gt;
* Python bindings to PROJ:&lt;br /&gt;
** http://www.cdc.noaa.gov/people/jeffrey.s.whitaker/python/pyproj.html&lt;br /&gt;
&lt;br /&gt;
* Python and GIS:&lt;br /&gt;
** [http://gispython.org/ Open Source GIS-Python Laboratory]&lt;br /&gt;
&lt;br /&gt;
* Python and Statistics:&lt;br /&gt;
** [http://rpy.sourceforge.net/ RPy] - Python interface to the R-statistics programming language&lt;br /&gt;
&lt;br /&gt;
* Bindings:&lt;br /&gt;
** SIP (C/C++ bindings generator) http://directory.fsf.org/all/Python-SIP.html&lt;br /&gt;
** [http://www.cython.org/ Cython] - C-Extensions for Python (compile where speed is needed)&lt;br /&gt;
&lt;br /&gt;
* Other external projects&lt;br /&gt;
** [http://www.scipy.org Scientific Python]&lt;br /&gt;
** [http://wiki.python.org/moin/NumericAndScientific Numeric and Scientific]&lt;br /&gt;
** [http://w3.pppl.gov/~hammett/comp/python/python.html Info on Python for Scientific Applications]&lt;br /&gt;
&lt;br /&gt;
=== Presentations ===&lt;br /&gt;
&lt;br /&gt;
From FOSS4G2006:&lt;br /&gt;
* [http://www.foss4g2006.org/materialDisplay.py?contribId=136&amp;amp;amp;sessionId=48&amp;amp;amp;materialId=slides&amp;amp;amp;confId=1 A Python sweeps in the GRASS] - A. Frigeri 2006&lt;br /&gt;
* [http://www.foss4g2006.org/materialDisplay.py?contribId=67&amp;amp;amp;sessionId=48&amp;amp;amp;materialId=slides&amp;amp;amp;confId=1 GRASS goes web: PyWPS] - J. Cepicky 2006&lt;br /&gt;
&lt;br /&gt;
{{Python}}&lt;/div&gt;</summary>
		<author><name>⚠️PierreRoudier</name></author>
	</entry>
	<entry>
		<id>https://grasswiki.osgeo.org/w/index.php?title=GRASS_and_Python&amp;diff=13590</id>
		<title>GRASS and Python</title>
		<link rel="alternate" type="text/html" href="https://grasswiki.osgeo.org/w/index.php?title=GRASS_and_Python&amp;diff=13590"/>
		<updated>2011-06-01T03:59:12Z</updated>

		<summary type="html">&lt;p&gt;⚠️PierreRoudier: /* Parsing the options and flags */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;''(for discussions on the new GRASS GUI, see [[GRASS GUI|here]])''&lt;br /&gt;
&lt;br /&gt;
==Python SIGs==&lt;br /&gt;
Python Special Interest Groups are focused collaborative efforts to develop, improve, or maintain specific Python resources. Each SIG has a charter, a coordinator, a mailing list, and a directory on the Python website. SIG membership is informal, defined by subscription to the SIG's mailing list. Anyone can join a SIG, and participate in the development discussions via the SIG's mailing list. Below is the list of currently active Python SIGs, with links to their resources. &lt;br /&gt;
&lt;br /&gt;
See more at http://www.python.org/community/sigs/&lt;br /&gt;
&lt;br /&gt;
==Writing Python scripts in GRASS==&lt;br /&gt;
&lt;br /&gt;
Python is a programming language which is more powerful than shell scripting but easier and more forgiving than C.&lt;br /&gt;
The Python script can contain simple module description definitions which will be processed with {{cmd|g.parser}}, as shown in the example below. In this way with no extra coding a GUI can be built, inputs checked, and a skeleton help page can be generated automatically. In addition it adds links to the GRASS message translation system.&lt;br /&gt;
For code which needs access to the power of C, you can access the GRASS C library functions via the SWIG interface (note 7/2010: swig stuff to be superseded with 'ctypes' soon).&lt;br /&gt;
&lt;br /&gt;
* GRASS Python interface to library functions: http://grass.osgeo.org/programming6/swig/&lt;br /&gt;
* GRASS Python scripting library: http://grass.osgeo.org/programming6/pythonlib.html&lt;br /&gt;
&lt;br /&gt;
Code style: Have a look at [http://trac.osgeo.org/grass/browser/grass/trunk/SUBMITTING_PYTHON SUBMITTING_PYTHON].&lt;br /&gt;
&lt;br /&gt;
=== Creating Python scripts that call GRASS functionality from outside ===&lt;br /&gt;
&lt;br /&gt;
In order to use GRASS from outside, some environment variables have to be set.&lt;br /&gt;
&lt;br /&gt;
==== MS-Windows ====&lt;br /&gt;
&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;
Some hints:&lt;br /&gt;
&lt;br /&gt;
# The Python interpreter (python.exe) needs to be in the PATH&lt;br /&gt;
# Python needs to be associated with the .py extension&lt;br /&gt;
# PATHEXT needs to include .py if you want to be able to omit the extension&lt;br /&gt;
# PYTHONPATH needs to be set to %WINGISBASE%\etc\python&lt;br /&gt;
&lt;br /&gt;
1-3 should be taken care of by the Python installer. 4 needs to be done by the startup (currently, this doesn't appear to be the case on MS-Windows).&lt;br /&gt;
&lt;br /&gt;
Note:&lt;br /&gt;
&lt;br /&gt;
Currently (as of 22 Feb 2011) if you want to use Python for scripting GRASS on Windows, the best solution is to delete the bundled version of Python 2.5 from the GRASS installation, install Python and the required add-ons (wxPython, NumPy, PyWin32) from their official installers,&lt;br /&gt;
then edit the GRASS start-up script to remove any references to the bundled version.&lt;br /&gt;
&lt;br /&gt;
==== Linux ====&lt;br /&gt;
&lt;br /&gt;
The variables are set like this:&lt;br /&gt;
&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;
 # for parallel session management, we use process ID (PID) as lock file number:&lt;br /&gt;
 export GIS_LOCK=$$&lt;br /&gt;
 # path to GRASS settings file&lt;br /&gt;
 export GISRC=&amp;quot;$HOME/.grassrc6&amp;quot;&lt;br /&gt;
&lt;br /&gt;
=== Running external commands from Python ===&lt;br /&gt;
For information on running external commands from Python, see:&lt;br /&gt;
http://docs.python.org/lib/module-subprocess.html&lt;br /&gt;
&lt;br /&gt;
Avoid using the older os.* functions. Section 17.1.3 lists equivalents&lt;br /&gt;
using the Popen() interface, which is more robust (particularly on&lt;br /&gt;
Windows).&lt;br /&gt;
&lt;br /&gt;
=== Examples ===&lt;br /&gt;
&lt;br /&gt;
==== Display example ====&lt;br /&gt;
Example of Python script, which is processed by g.parser:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
#!/usr/bin/env python&lt;br /&gt;
#&lt;br /&gt;
############################################################################&lt;br /&gt;
#&lt;br /&gt;
# MODULE:      d.shadedmap&lt;br /&gt;
# AUTHOR(S):   Unknown; updated to GRASS 5.7 by Michael Barton&lt;br /&gt;
#              Converted to Python by Glynn Clements&lt;br /&gt;
# PURPOSE:     Uses d.his to drape a color raster over a shaded relief map&lt;br /&gt;
# COPYRIGHT:   (C) 2004,2008,2009 by the GRASS Development Team&lt;br /&gt;
#&lt;br /&gt;
#              This program is free software under the GNU General Public&lt;br /&gt;
#              License (&amp;gt;=v2). Read the file COPYING that comes with GRASS&lt;br /&gt;
#              for details.&lt;br /&gt;
#&lt;br /&gt;
#############################################################################&lt;br /&gt;
&lt;br /&gt;
#%Module&lt;br /&gt;
#% description: Drapes a color raster over a shaded relief map using d.his&lt;br /&gt;
#%End&lt;br /&gt;
#%option&lt;br /&gt;
#% key: reliefmap&lt;br /&gt;
#% type: string&lt;br /&gt;
#% gisprompt: old,cell,raster&lt;br /&gt;
#% description: Name of shaded relief or aspect map&lt;br /&gt;
#% required : yes&lt;br /&gt;
#%end&lt;br /&gt;
#%option&lt;br /&gt;
#% key: drapemap&lt;br /&gt;
#% type: string&lt;br /&gt;
#% gisprompt: old,cell,raster&lt;br /&gt;
#% description: Name of raster to drape over relief map&lt;br /&gt;
#% required : yes&lt;br /&gt;
#%end&lt;br /&gt;
#%option&lt;br /&gt;
#% key: brighten&lt;br /&gt;
#% type: integer&lt;br /&gt;
#% description: Percent to brighten&lt;br /&gt;
#% options: -99-99&lt;br /&gt;
#% answer: 0&lt;br /&gt;
#%end&lt;br /&gt;
&lt;br /&gt;
import sys&lt;br /&gt;
from grass.script import core as grass&lt;br /&gt;
&lt;br /&gt;
def main():&lt;br /&gt;
    drape_map = options['drapemap']&lt;br /&gt;
    relief_map = options['reliefmap']&lt;br /&gt;
    brighten = options['brighten']&lt;br /&gt;
    ret = grass.run_command(&amp;quot;d.his&amp;quot;, h_map = drape_map,  i_map = relief_map, brighten = brighten)&lt;br /&gt;
    sys.exit(ret)&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    options, flags = grass.parser()&lt;br /&gt;
    main()&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Parsing the options and flags  ====&lt;br /&gt;
&lt;br /&gt;
grass.parser() is an interface to g.parser, and allows to parse the options and flags passed to your script on the command line. It is to be called at the top-level:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    options, flags = grass.parser()&lt;br /&gt;
    main()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Global variables &amp;quot;options&amp;quot; and &amp;quot;flags&amp;quot; are Python dictionaries containing the options/flags values, keyed by lower-case option/flag names. The values in &amp;quot;options&amp;quot; are strings, those in &amp;quot;flags&amp;quot; are Python booleans. All those variables have to be previously declared in the header of your script.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
&amp;gt;&amp;gt;&amp;gt; options, flags = grass.parser()&lt;br /&gt;
&amp;gt;&amp;gt;&amp;gt; options&lt;br /&gt;
{'input': 'my_map', 'output': 'map_out', 'option1': '21.472', 'option2': ''}&lt;br /&gt;
&amp;gt;&amp;gt;&amp;gt; flags&lt;br /&gt;
{'c': True, 'm': False}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Example for embedding r.mapcalc (map algebra) ====&lt;br /&gt;
&lt;br /&gt;
grass.mapcalc() accepts a template string followed by keyword&lt;br /&gt;
arguments for the substitutions, e.g. (code snippets):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
grass.mapcalc(&amp;quot;${out} = ${rast1} + ${rast2}&amp;quot;,&lt;br /&gt;
              out = options['output'],&lt;br /&gt;
              rast1 = options['raster1'],&lt;br /&gt;
              rast2 = options['raster2'])&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
''Best practice'': first copy all of the options[] into separate variables at the beginning of main(), i.e.:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
def main():&lt;br /&gt;
    output = options['output']&lt;br /&gt;
    raster1 = options['raster1']&lt;br /&gt;
    raster2 = options['raster2']&lt;br /&gt;
 &lt;br /&gt;
    ...&lt;br /&gt;
 &lt;br /&gt;
    grass.mapcalc(&amp;quot;${out} = ${rast1} + ${rast2}&amp;quot;,&lt;br /&gt;
                  out = output,&lt;br /&gt;
                  rast1 = raster1,&lt;br /&gt;
                  rast2 = raster2)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Example for parsing category numbers ====&lt;br /&gt;
&lt;br /&gt;
Q: How to obtain the number of cells of a certain category?&lt;br /&gt;
&lt;br /&gt;
A: It is recommended to use pipe_command() and parse the output, e.g.:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
       p = grass.pipe_command('r.stats',flags='c',input='map')&lt;br /&gt;
       result = {}&lt;br /&gt;
       for line in p.stdout:&lt;br /&gt;
           val,count = line.strip().split()&lt;br /&gt;
           result[int(val)] = int(count)&lt;br /&gt;
       p.wait()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Example for getting the region's number of rows and columns ====&lt;br /&gt;
&lt;br /&gt;
Q: How to obtain the number of rows and columns of the current region?&lt;br /&gt;
&lt;br /&gt;
A: It is recommended to use the &amp;quot;grass.region()&amp;quot; function which will create a dictionary with values for extents and resolution, e.g.:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source 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;
############################################################################&lt;br /&gt;
#&lt;br /&gt;
# MODULE:       g.region.resolution&lt;br /&gt;
# AUTHOR(S):    based on a post at GRASS-USER mailing list [1]               &lt;br /&gt;
# PURPOSE:	Parses &amp;quot;g.region -g&amp;quot;, prints out number of rows, cols&lt;br /&gt;
# COPYLEFT:     ;-)&lt;br /&gt;
# COMMENT:      ...a lot of comments to be easy-to-read for/by beginners&lt;br /&gt;
#&lt;br /&gt;
#############################################################################&lt;br /&gt;
#&lt;br /&gt;
#%Module&lt;br /&gt;
#% description: Print number of rows, cols of current geographic region&lt;br /&gt;
#% keywords: region&lt;br /&gt;
#%end&lt;br /&gt;
&lt;br /&gt;
# importing required modules&lt;br /&gt;
import sys # the sys module [2]&lt;br /&gt;
from grass.script import core as grass # the core module [3]&lt;br /&gt;
&lt;br /&gt;
# information about imported modules can be obtained using the dir() function&lt;br /&gt;
# e.g.: dir(sys)&lt;br /&gt;
&lt;br /&gt;
# define the &amp;quot;main&amp;quot; function: get number of rows, cols of region&lt;br /&gt;
def main():&lt;br /&gt;
    &lt;br /&gt;
    # #######################################################################&lt;br /&gt;
    # the following commented code works but is kept only for learning purposes&lt;br /&gt;
     &lt;br /&gt;
    ## assigning the output of the command &amp;quot;g.region -g&amp;quot; in a string called &amp;quot;return_rows_x_cols&amp;quot;&lt;br /&gt;
    # return_rows_x_cols = grass.read_command('g.region', flags = 'g')&lt;br /&gt;
    &lt;br /&gt;
    ## parsing arguments of interest (rows, cols) in a dictionary named &amp;quot;rows_x_cols&amp;quot;&lt;br /&gt;
    # rows_x_cols = grass.parse_key_val(return_rows_x_cols)&lt;br /&gt;
    &lt;br /&gt;
    ## selectively print rows, cols from the dictionary &amp;quot;rows_x_cols&amp;quot;&lt;br /&gt;
    # print 'rows=%d \ncols=%d' % (int(rows_x_cols['rows']), int(rows_x_cols['cols']))&lt;br /&gt;
    &lt;br /&gt;
    # #######################################################################&lt;br /&gt;
    &lt;br /&gt;
    # faster/ easier way: use of the &amp;quot;grass.region()&amp;quot; function&lt;br /&gt;
    gregion = grass.region()&lt;br /&gt;
    rows = gregion['rows']&lt;br /&gt;
    cols = gregion['cols']&lt;br /&gt;
    &lt;br /&gt;
    # print rows, cols properly formated &lt;br /&gt;
    print 'rows=%d \ncols=%d' % (rows, cols)&lt;br /&gt;
&lt;br /&gt;
# this &amp;quot;if&amp;quot; condition instructs execution of code contained in this script, *only* if the script is being executed directly &lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;: # this allows the script to be used as a module in other scripts or as a standalone script&lt;br /&gt;
    options, flags = grass.parser() #&lt;br /&gt;
    sys.exit(main()) #&lt;br /&gt;
&lt;br /&gt;
# Links&lt;br /&gt;
# [1] http://n2.nabble.com/Getting-rows-cols-of-a-region-in-a-script-tp2787474p2787509.html&lt;br /&gt;
# [2] http://www.python.org/doc/2.5.2/lib/module-sys.html&lt;br /&gt;
# [3] http://download.osgeo.org/grass/grass6_progman/pythonlib.html#pythonCore&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Managing mapsets ====&lt;br /&gt;
&lt;br /&gt;
To check if a certain mapset exists in the active location, use:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
       grass.script.mapsets(False)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
... returns a list of mapsets in the current location.&lt;br /&gt;
&lt;br /&gt;
==== r.mapcalc example ====&lt;br /&gt;
&lt;br /&gt;
Example of Python script, which is processed by {{cmd|g.parser}}:&lt;br /&gt;
&lt;br /&gt;
The shell script line:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
  r.mapcalc &amp;quot;MASK = if(($cloudResampName &amp;lt; 0.01000),1,null())&amp;quot;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
would be written like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
       import grass.script as grass&lt;br /&gt;
&lt;br /&gt;
       ...&lt;br /&gt;
&lt;br /&gt;
       grass.mapcalc(&amp;quot;MASK=if(($cloudResampName &amp;lt; 0.01000),1,null())&amp;quot;,&lt;br /&gt;
                     cloudResampName = cloudResampName)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The first argument to the mapcalc function is a template (see the Python library documentation for [http://docs.python.org/library/string.html string.Template]). Any keyword arguments (other than quiet, verbose or overwrite) specify substitutions.&lt;br /&gt;
&lt;br /&gt;
==== Using output from GRASS modules in the script ====&lt;br /&gt;
&lt;br /&gt;
Sometimes you need to use the output of a module for the next step. There are dedicated functions to obtain the result of, for example, a statistical analysis.&lt;br /&gt;
&lt;br /&gt;
Example: get the range of a raster map and use it in {{cmd|r.mapcalc}}. Here you can use &amp;lt;code&amp;gt;grass.script.raster_info()&amp;lt;/code&amp;gt;, e.g.:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
       import grass.script as grass&lt;br /&gt;
&lt;br /&gt;
       max = grass.raster_info(inmap)['max']&lt;br /&gt;
       grass.mapcalc(&amp;quot;$outmap = $inmap / $max&amp;quot;,&lt;br /&gt;
                     inmap = inmap, outmap = outmap, max = max)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Calling a GRASS module in Python  ====&lt;br /&gt;
&lt;br /&gt;
Imagine, you wanted to execute this command in Python:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
  r.profile -g input=mymap output=newfile profile=12244.256,-295112.597,12128.012,-295293.77&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
All arguments except the first (which is a flag) are keyword arguments, i.e. &amp;lt;tt&amp;gt;arg = val&amp;lt;/tt&amp;gt;. For the flag, use &amp;lt;tt&amp;gt;flags = 'g'&amp;lt;/tt&amp;gt; (note that &amp;quot;-g&amp;quot; would be the negative of a Python variable named &amp;quot;g&amp;quot;!). So:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
       grass.run_command(&lt;br /&gt;
               'r.profile',&lt;br /&gt;
               input = input_map,&lt;br /&gt;
               output = output_file,&lt;br /&gt;
               profile = [12244.256,-295112.597,12128.012,-295293.77]&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
or:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
               profile = [(12244.256,-295112.597),(12128.012,-295293.77)]&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
i.e. you need to provide the keyword, and the argument must be a valid Python expression. Function &amp;lt;code&amp;gt;run_command()&amp;lt;/code&amp;gt; etc accept lists and tuples.&lt;br /&gt;
&lt;br /&gt;
'''Differences between ''run_command()'' and ''read_command()'':'''&lt;br /&gt;
&lt;br /&gt;
* run_command() executes the command and waits for it to terminate; it doesn't redirect any of the standard streams.&lt;br /&gt;
* read_command() executes the command with stdout redirected to a pipe, and reads everything written to it. Once the command terminates, it returns the data written to stdout as a string.&lt;br /&gt;
&lt;br /&gt;
'''How to retrieve error messages from ''read_command()'':'''&lt;br /&gt;
&lt;br /&gt;
None of the existing *_command functions redirect stderr. You can do so with e.g.:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
def read2_command(*args, **kwargs):&lt;br /&gt;
   kwargs['stdout'] = grass.PIPE&lt;br /&gt;
   kwargs['stderr'] = grass.PIPE&lt;br /&gt;
   ps = grass.start_command(*args, **kwargs)&lt;br /&gt;
   return ps.communicate()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This behaves like read_command() except that it returns a tuple of (stdout,stderr) rather than just stdout.&lt;br /&gt;
&lt;br /&gt;
==== Path to GISDBASE ====&lt;br /&gt;
&lt;br /&gt;
In order to a avoid hardcoded paths to GRASS mapset files like the SQLite DB file, you can get the GISDBASE variable from the environment:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
       import grass.script as grass&lt;br /&gt;
       import os.path&lt;br /&gt;
&lt;br /&gt;
       env = grass.gisenv()&lt;br /&gt;
&lt;br /&gt;
       gisdbase = env['GISDBASE']&lt;br /&gt;
       location = env['LOCATION_NAME']&lt;br /&gt;
       mapset = env['MAPSET']&lt;br /&gt;
&lt;br /&gt;
       path = os.path.join(gisdbase, location, mapset, 'sqlite.db')&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Python extensions for GRASS GIS==&lt;br /&gt;
=== wxPython GUI development for GRASS ===&lt;br /&gt;
&lt;br /&gt;
* See the [[wxGUI]] wiki page&lt;br /&gt;
&lt;br /&gt;
=== GRASS Python Scripting Library ===&lt;br /&gt;
&lt;br /&gt;
See [http://grass.osgeo.org/programming7/pythonlib.html GRASS Python Scripting Library] (Programmer's manual). See also [[Converting Bash scripts to Python]], and [http://trac.osgeo.org/grass/browser/grass/trunk/scripts sample Python scripts in GRASS 7]&lt;br /&gt;
&lt;br /&gt;
==== Uses for read, feed and pipe, start and exec commands ====&lt;br /&gt;
&lt;br /&gt;
All of the *_command functions use make_command to construct a command&lt;br /&gt;
line for a program which uses the GRASS parser. Most of them then pass&lt;br /&gt;
that command line to ''subprocess.Popen()'' via ''start_command()'', except&lt;br /&gt;
for ''exec_command()'' which uses ''os.execvpe()''.&lt;br /&gt;
&lt;br /&gt;
[To be precise, they use grass.Popen(), which just calls&lt;br /&gt;
subprocess.Popen() with shell=True on Windows and shell=False&lt;br /&gt;
otherwise. On Windows, you need to use shell=True to be able to&lt;br /&gt;
execute scripts (including batch files); shell=False only works with&lt;br /&gt;
binary executables.]&lt;br /&gt;
&lt;br /&gt;
start_command() separates the arguments into those which&lt;br /&gt;
subprocess.Popen() understands and the rest. The rest are passed to&lt;br /&gt;
make_command() to construct a command line which is passed as the&lt;br /&gt;
&amp;quot;args&amp;quot; parameter to subprocess.Popen().&lt;br /&gt;
&lt;br /&gt;
In other words, start_command() is a GRASS-oriented interface to&lt;br /&gt;
subprocess.Popen(). It should be suitable for any situation where you&lt;br /&gt;
would use subprocess.Popen() to execute a normal GRASS command (one&lt;br /&gt;
which uses the GRASS parser, which is almost all of them; the main&lt;br /&gt;
exception is r.mapcalc in 6.x).&lt;br /&gt;
&lt;br /&gt;
Most of the others are convenience wrappers around start_command(), for common use cases.&lt;br /&gt;
&lt;br /&gt;
* run_command() calls the wait() method on the process, so it doesn't return until the command has finished, and returns the command's exit code. Similar to system().&lt;br /&gt;
&lt;br /&gt;
* pipe_command() calls start_command() with stdout=PIPE and returns the process object. You can use the process' .stdout member to read the command's stdout. Similar to popen(..., &amp;quot;r&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
* feed_command() calls start_command() with stdin=PIPE and returns the process object. You can use the process' .stdin member to write to the command's stdout. Similar to popen(..., &amp;quot;w&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
* read_command() calls pipe_command(), reads the data from the command's stdout, and returns it as a string. Similar to `backticks` in the shell.&lt;br /&gt;
&lt;br /&gt;
* write_command() calls feed_command(), sends the string specified by the &amp;quot;stdin&amp;quot; argument to the command's stdin, waits for the command to finish and returns its exit code. Similar to &amp;quot;echo ... | command&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
* parse_command() calls read_command() and parses its output as key-value pairs. Useful for obtaining information from g.region, g.proj, r.info, etc.&lt;br /&gt;
&lt;br /&gt;
* exec_command() doesn't use start_command() but os.execvpe(). This causes the specified command to replace the current program (i.e. the Python script), so exec_command() never returns. Similar to bash's &amp;quot;exec&amp;quot; command. This can be useful if the script is a &amp;quot;wrapper&amp;quot; around a single command, where you construct the command line and execute the command as the final step.&lt;br /&gt;
&lt;br /&gt;
If you have any other questions, you might want to look at the code ($GISBASE/etc/python/grass/script/core.py). Most of these functions are only a few lines long.&lt;br /&gt;
&lt;br /&gt;
==== Interfacing with NumPy ====&lt;br /&gt;
&lt;br /&gt;
''Glynn writes:''&lt;br /&gt;
&lt;br /&gt;
The {{api|pythonlib.html#pythonArray|grass.script.array}} module defines a {{api|classpython_1_1array_1_1array.html|class array}} which is a subclass of [http://docs.scipy.org/doc/numpy/reference/generated/numpy.memmap.html numpy.memmap] with &amp;lt;code&amp;gt;.read()&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;.write()&amp;lt;/code&amp;gt; methods to read/write the underlying file via {{cmd|r.out.bin}}/{{cmd|r.in.bin}}.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
    import grass.script.array as garray&lt;br /&gt;
    a = garray.array()&lt;br /&gt;
    a.read(&amp;quot;elevation.dem&amp;quot;)&lt;br /&gt;
    b = garray.array()&lt;br /&gt;
    b[...] = (a / 50).astype(int) * 50  # or whatever&lt;br /&gt;
    b.write(&amp;quot;elev.50m&amp;quot;)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The size of the array is taken from the current region.&lt;br /&gt;
&lt;br /&gt;
The main drawback of using numpy is that you're limited by available&lt;br /&gt;
memory. Using a subclass of &amp;lt;code&amp;gt;numpy.memmap&amp;lt;/code&amp;gt; lets you use files which may&lt;br /&gt;
be much larger, but processing the entire array in one go is likely to&lt;br /&gt;
produce in-memory results of a similar size.&lt;br /&gt;
&lt;br /&gt;
One may also use the scipy matlab interface:&lt;br /&gt;
    &lt;br /&gt;
    ### SH: in GRASS ###&lt;br /&gt;
    r.out.mat input=elevation output=elev.mat&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
    ### PY ###&lt;br /&gt;
    import scipy.io as sio&lt;br /&gt;
    # load data&lt;br /&gt;
    elev = sio.loadmat('elev.mat')&lt;br /&gt;
    # retrive the actual array. the data set contains also the spatial reference&lt;br /&gt;
    elev.get('map_data')&lt;br /&gt;
    data = elev.get('map_data')&lt;br /&gt;
    # a first simple plot&lt;br /&gt;
    import pylab&lt;br /&gt;
    pylab.plot(data)&lt;br /&gt;
    pylab.show()&lt;br /&gt;
    # the contour plot&lt;br /&gt;
    pylab.contour(data)&lt;br /&gt;
    # obviously data needs to ne reversed&lt;br /&gt;
    import numpy as np&lt;br /&gt;
    data_rev = data[::-1]&lt;br /&gt;
    pylab.contour(data_rev)&lt;br /&gt;
    # =&amp;gt; this is a quick plot. basemap mapping may provide a nicer map!&lt;br /&gt;
    #######&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Python Ctypes Interface ===&lt;br /&gt;
&lt;br /&gt;
This interface allows calling GRASS library functions from Python scripts. See [[Python Ctypes Examples]] for details.&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
&lt;br /&gt;
* GRASS 7: [http://trac.osgeo.org/grass/browser/grass/trunk/doc/python/raster_example_ctypes.py raster], [http://trac.osgeo.org/grass/browser/grass/trunk/doc/python/vector_example_ctypes.py vector] example&lt;br /&gt;
&lt;br /&gt;
=== Python SWIG interface ===&lt;br /&gt;
&lt;br /&gt;
  Warning: The GRASS-SWIG interface isn't particularly stable and well understood. Please consider to use the Python ctypes GRASS above.&lt;br /&gt;
&lt;br /&gt;
There is a prototype GRASS-SWIG interface available (thanks to Sajith VK), find it in GRASS 6-CVS: '''swig/python/'''. Draft documentation is [http://download.osgeo.org/grass/grass6_progman/swig/ here]. It now wraps both raster and vector data C functions plus the general GIS (G_*()) functions.&lt;br /&gt;
&lt;br /&gt;
Background: [http://www.swig.org SWIG] (Simplified Wrapper and Interface Generator) is: &lt;br /&gt;
&lt;br /&gt;
* A compiler that turns ANSI C/C++ declarations into scripting language interfaces.&lt;br /&gt;
* Completely automated (produces a fully working Python extension module). &lt;br /&gt;
* Language neutral. SWIG can also target Tcl, Perl, Guile, MATLAB (try PyLab+Matplotlib from python), etc... &lt;br /&gt;
* Attempts to eliminate the tedium of writing extension modules.&lt;br /&gt;
&lt;br /&gt;
==== Python-SWIG examples ====&lt;br /&gt;
&lt;br /&gt;
* Latest and greatest: [[http://trac.osgeo.org/grass/browser/grass/trunk/scripts GRASS 7 Python scripts]]&lt;br /&gt;
&lt;br /&gt;
* [[PythonSwigExamples|More complicated examples]]&lt;br /&gt;
&lt;br /&gt;
Sample script for GRASS 6 raster access (use within GRASS, Spearfish session):&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
#!/usr/bin/env python&lt;br /&gt;
&lt;br /&gt;
import os, sys&lt;br /&gt;
from grass.lib import grass&lt;br /&gt;
&lt;br /&gt;
if &amp;quot;GISBASE&amp;quot; not in os.environ:&lt;br /&gt;
    print &amp;quot;You must be in GRASS GIS to run this program.&amp;quot;&lt;br /&gt;
    sys.exit(1)&lt;br /&gt;
&lt;br /&gt;
if len(sys.argv)==2:&lt;br /&gt;
  input = sys.argv[1]&lt;br /&gt;
else:&lt;br /&gt;
  input = raw_input(&amp;quot;Raster Map Name? &amp;quot;)&lt;br /&gt;
&lt;br /&gt;
# initialize&lt;br /&gt;
grass.G_gisinit('')&lt;br /&gt;
&lt;br /&gt;
# find map in search path&lt;br /&gt;
mapset = grass.G_find_cell2(input, '')&lt;br /&gt;
&lt;br /&gt;
# determine the inputmap type (CELL/FCELL/DCELL) */&lt;br /&gt;
data_type = grass.G_raster_map_type(input, mapset)&lt;br /&gt;
&lt;br /&gt;
infd = grass.G_open_cell_old(input, mapset)&lt;br /&gt;
inrast = grass.G_allocate_raster_buf(data_type)&lt;br /&gt;
&lt;br /&gt;
rown = 0&lt;br /&gt;
while True:&lt;br /&gt;
    myrow = grass.G_get_raster_row(infd, inrast, rown, data_type)&lt;br /&gt;
    print rown, myrow[0:10]&lt;br /&gt;
    rown += 1&lt;br /&gt;
    if rown == 476:&lt;br /&gt;
        break&lt;br /&gt;
&lt;br /&gt;
grass.G_close_cell(inrast)&lt;br /&gt;
grass.G_free(cell)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Sample script for vector access (use within GRASS, Spearfish session):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
#!/usr/bin/python&lt;br /&gt;
&lt;br /&gt;
# run within GRASS Spearfish session&lt;br /&gt;
# run this before starting python to append module search path:&lt;br /&gt;
#   export PYTHONPATH=/usr/src/grass70/swig/python&lt;br /&gt;
#   check with &amp;quot;import sys; sys.path&amp;quot;&lt;br /&gt;
# or:&lt;br /&gt;
#   sys.path.append(&amp;quot;/usr/src/grass70/swig/python&amp;quot;)&lt;br /&gt;
# FIXME: install the grass bindings in $GISBASE/lib/ ?&lt;br /&gt;
&lt;br /&gt;
import os, sys&lt;br /&gt;
from grass.lib import grass&lt;br /&gt;
from grass.lib import vector as grassvect&lt;br /&gt;
&lt;br /&gt;
if &amp;quot;GISBASE&amp;quot; not in os.environ:&lt;br /&gt;
    print &amp;quot;You must be in GRASS GIS to run this program.&amp;quot;&lt;br /&gt;
    sys.exit(1)&lt;br /&gt;
&lt;br /&gt;
if len(sys.argv)==2:&lt;br /&gt;
  input = sys.argv[1]&lt;br /&gt;
else:&lt;br /&gt;
  input = raw_input(&amp;quot;Vector Map Name? &amp;quot;)&lt;br /&gt;
&lt;br /&gt;
# initialize&lt;br /&gt;
grass.G_gisinit('')&lt;br /&gt;
&lt;br /&gt;
# find map in search path&lt;br /&gt;
mapset = grass.G_find_vector2(input,'')&lt;br /&gt;
&lt;br /&gt;
# define map structure&lt;br /&gt;
map = grassvect.Map_info()&lt;br /&gt;
&lt;br /&gt;
# define open level (level 2: topology)&lt;br /&gt;
grassvect.Vect_set_open_level (2)&lt;br /&gt;
&lt;br /&gt;
# open existing map&lt;br /&gt;
grassvect.Vect_open_old(map, input, mapset)&lt;br /&gt;
&lt;br /&gt;
# query&lt;br /&gt;
print 'Vect map: ', input&lt;br /&gt;
print 'Vect is 3D: ', grassvect.Vect_is_3d (map)&lt;br /&gt;
print 'Vect DB links: ', grassvect.Vect_get_num_dblinks(map)&lt;br /&gt;
print 'Map Scale:  1:', grassvect.Vect_get_scale(map)&lt;br /&gt;
print 'Number of areas:', grassvect.Vect_get_num_areas(map)&lt;br /&gt;
&lt;br /&gt;
# close map&lt;br /&gt;
grassvect.Vect_close(map)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== TODO ====&lt;br /&gt;
&lt;br /&gt;
* Implement modules support in a Python class using --interface-description and a Python-XML parser. This should be a generic class with module's name as parameter, returning back an object which describes the module (description, flags, parameters, status of not/required). See [http://trac.osgeo.org/grass/browser/grass/trunk/gui/wxpython/ GRASS 6 wxPython interface] for inspiration. Important is to auto-generate the GRASS-Python class at compile time with a Python script.&lt;br /&gt;
&lt;br /&gt;
=== Python-GRASS add-ons ===&lt;br /&gt;
&lt;br /&gt;
Stand-alone addons:&lt;br /&gt;
&lt;br /&gt;
# Jáchym Čepický's G-ps.map, a GUI to typeset printable maps with ps.map (http://193.84.38.2/~jachym/index.py?cat=gpsmap)&lt;br /&gt;
# Jáchym Čepický's v.pydigit, a GUI to v.edit (http://les-ejk.cz/?cat=vpydigit)&lt;br /&gt;
# Jáchym Čepický's PyWPS, GRASS-Web Processing Service (http://pywps.wald.intevation.org)&lt;br /&gt;
&lt;br /&gt;
=== Using GRASS gui.tcl in Python ===&lt;br /&gt;
&lt;br /&gt;
Here is some example code to use the grass automatically generated guis in python code. This could (should) all be bundled up and abstracted away so that the implementation can be replaced later.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
import Tkinter&lt;br /&gt;
import os&lt;br /&gt;
&lt;br /&gt;
# Startup (once):&lt;br /&gt;
&lt;br /&gt;
tk = Tkinter.Tk()&lt;br /&gt;
tk.eval (&amp;quot;wm withdraw .&amp;quot;)&lt;br /&gt;
tk.eval (&amp;quot;source $env(GISBASE)/etc/gui.tcl&amp;quot;)&lt;br /&gt;
# Here you could do various things to change what the gui does&lt;br /&gt;
# See gui.tcl and README.GUI&lt;br /&gt;
&lt;br /&gt;
# Make a gui (per dialog)&lt;br /&gt;
# This sets up a window for the command.&lt;br /&gt;
# This can be different to integrate with tkinter:&lt;br /&gt;
tk.eval ('set path &amp;quot;.dialog$dlg&amp;quot;')&lt;br /&gt;
tk.eval ('toplevel .dialog$dlg')&lt;br /&gt;
# Load the code for this command:&lt;br /&gt;
fd = os.popen (&amp;quot;d.vect --tcltk&amp;quot;)&lt;br /&gt;
gui = fd.read()&lt;br /&gt;
# Run it&lt;br /&gt;
tk.eval(gui)&lt;br /&gt;
dlg = tk.eval('set dlg') # This is used later to get and set &lt;br /&gt;
&lt;br /&gt;
# Get the current command in the gui we just made:&lt;br /&gt;
currentcommand = tk.eval (&amp;quot;dialog_get_command &amp;quot; + dlg)&lt;br /&gt;
&lt;br /&gt;
# Set the command in the dialog we just made:&lt;br /&gt;
tk.eval (&amp;quot;dialog_set_command &amp;quot; + dlg + &amp;quot; {d.vect map=roads}&amp;quot;)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== FAQ ==&lt;br /&gt;
&lt;br /&gt;
* '''Q:''' Error message &amp;quot;execl() failed: Permission denied&amp;quot; - what to do?&lt;br /&gt;
: '''A:''' Be sure that the execute bit of the script is set.&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
&lt;br /&gt;
=== General guides ===&lt;br /&gt;
&lt;br /&gt;
* [http://en.wikibooks.org/wiki/Python_Programming/ Wikibook Python Programming]&lt;br /&gt;
* [http://www.poromenos.org/tutorials/python Quick Python tutorial] for programmers of other languages&lt;br /&gt;
*: [http://wiki.python.org/moin/BeginnersGuide/Programmers More Python tutorials] for programmers&lt;br /&gt;
* [http://www.python.org/dev/peps/pep-0008/ Python programming style guide]&lt;br /&gt;
* [http://wiki.python.org/moin/PythonEditors Python Editors]&lt;br /&gt;
&lt;br /&gt;
=== Programming ===&lt;br /&gt;
&lt;br /&gt;
* Python and GRASS:&lt;br /&gt;
** GRASS Python interface to library functions: http://download.osgeo.org/grass/grass6_progman/swig/ based on SWIG http://www.swig.org/&lt;br /&gt;
** GRASS Python scripting library: http://download.osgeo.org/grass/grass6_progman/pythonlib.html&lt;br /&gt;
** PyWPS, GRASS-Web Processing Service http://pywps.wald.intevation.org&lt;br /&gt;
&lt;br /&gt;
* Python and OSGeo:&lt;br /&gt;
** [http://wiki.osgeo.org/wiki/OSGeo_Python_Library OSGeo Python Library]&lt;br /&gt;
&lt;br /&gt;
* Python and GDAL/OGR:&lt;br /&gt;
** [http://mapserver.gis.umn.edu/community/conferences/MUM3/workshop/python Open Source Python GIS Hacks Mum'03]&lt;br /&gt;
** http://hobu.biz/software/OSGIS_Hacks - Python OSGIS Hacks '05&lt;br /&gt;
** http://zcologia.com/news/categorylist_html?cat_id=8&lt;br /&gt;
** http://www.perrygeo.net/wordpress/?p=4&lt;br /&gt;
&lt;br /&gt;
* Python bindings to PROJ:&lt;br /&gt;
** http://www.cdc.noaa.gov/people/jeffrey.s.whitaker/python/pyproj.html&lt;br /&gt;
&lt;br /&gt;
* Python and GIS:&lt;br /&gt;
** [http://gispython.org/ Open Source GIS-Python Laboratory]&lt;br /&gt;
&lt;br /&gt;
* Python and Statistics:&lt;br /&gt;
** [http://rpy.sourceforge.net/ RPy] - Python interface to the R-statistics programming language&lt;br /&gt;
&lt;br /&gt;
* Bindings:&lt;br /&gt;
** SIP (C/C++ bindings generator) http://directory.fsf.org/all/Python-SIP.html&lt;br /&gt;
** [http://www.cython.org/ Cython] - C-Extensions for Python (compile where speed is needed)&lt;br /&gt;
&lt;br /&gt;
* Other external projects&lt;br /&gt;
** [http://www.scipy.org Scientific Python]&lt;br /&gt;
** [http://wiki.python.org/moin/NumericAndScientific Numeric and Scientific]&lt;br /&gt;
** [http://w3.pppl.gov/~hammett/comp/python/python.html Info on Python for Scientific Applications]&lt;br /&gt;
&lt;br /&gt;
=== Presentations ===&lt;br /&gt;
&lt;br /&gt;
From FOSS4G2006:&lt;br /&gt;
* [http://www.foss4g2006.org/materialDisplay.py?contribId=136&amp;amp;amp;sessionId=48&amp;amp;amp;materialId=slides&amp;amp;amp;confId=1 A Python sweeps in the GRASS] - A. Frigeri 2006&lt;br /&gt;
* [http://www.foss4g2006.org/materialDisplay.py?contribId=67&amp;amp;amp;sessionId=48&amp;amp;amp;materialId=slides&amp;amp;amp;confId=1 GRASS goes web: PyWPS] - J. Cepicky 2006&lt;br /&gt;
&lt;br /&gt;
{{Python}}&lt;/div&gt;</summary>
		<author><name>⚠️PierreRoudier</name></author>
	</entry>
	<entry>
		<id>https://grasswiki.osgeo.org/w/index.php?title=GRASS_and_Python&amp;diff=13589</id>
		<title>GRASS and Python</title>
		<link rel="alternate" type="text/html" href="https://grasswiki.osgeo.org/w/index.php?title=GRASS_and_Python&amp;diff=13589"/>
		<updated>2011-06-01T02:12:12Z</updated>

		<summary type="html">&lt;p&gt;⚠️PierreRoudier: Added more explainations about grass.parser() and its output&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;''(for discussions on the new GRASS GUI, see [[GRASS GUI|here]])''&lt;br /&gt;
&lt;br /&gt;
==Python SIGs==&lt;br /&gt;
Python Special Interest Groups are focused collaborative efforts to develop, improve, or maintain specific Python resources. Each SIG has a charter, a coordinator, a mailing list, and a directory on the Python website. SIG membership is informal, defined by subscription to the SIG's mailing list. Anyone can join a SIG, and participate in the development discussions via the SIG's mailing list. Below is the list of currently active Python SIGs, with links to their resources. &lt;br /&gt;
&lt;br /&gt;
See more at http://www.python.org/community/sigs/&lt;br /&gt;
&lt;br /&gt;
==Writing Python scripts in GRASS==&lt;br /&gt;
&lt;br /&gt;
Python is a programming language which is more powerful than shell scripting but easier and more forgiving than C.&lt;br /&gt;
The Python script can contain simple module description definitions which will be processed with {{cmd|g.parser}}, as shown in the example below. In this way with no extra coding a GUI can be built, inputs checked, and a skeleton help page can be generated automatically. In addition it adds links to the GRASS message translation system.&lt;br /&gt;
For code which needs access to the power of C, you can access the GRASS C library functions via the SWIG interface (note 7/2010: swig stuff to be superseded with 'ctypes' soon).&lt;br /&gt;
&lt;br /&gt;
* GRASS Python interface to library functions: http://grass.osgeo.org/programming6/swig/&lt;br /&gt;
* GRASS Python scripting library: http://grass.osgeo.org/programming6/pythonlib.html&lt;br /&gt;
&lt;br /&gt;
Code style: Have a look at [http://trac.osgeo.org/grass/browser/grass/trunk/SUBMITTING_PYTHON SUBMITTING_PYTHON].&lt;br /&gt;
&lt;br /&gt;
=== Creating Python scripts that call GRASS functionality from outside ===&lt;br /&gt;
&lt;br /&gt;
In order to use GRASS from outside, some environment variables have to be set.&lt;br /&gt;
&lt;br /&gt;
==== MS-Windows ====&lt;br /&gt;
&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;
Some hints:&lt;br /&gt;
&lt;br /&gt;
# The Python interpreter (python.exe) needs to be in the PATH&lt;br /&gt;
# Python needs to be associated with the .py extension&lt;br /&gt;
# PATHEXT needs to include .py if you want to be able to omit the extension&lt;br /&gt;
# PYTHONPATH needs to be set to %WINGISBASE%\etc\python&lt;br /&gt;
&lt;br /&gt;
1-3 should be taken care of by the Python installer. 4 needs to be done by the startup (currently, this doesn't appear to be the case on MS-Windows).&lt;br /&gt;
&lt;br /&gt;
Note:&lt;br /&gt;
&lt;br /&gt;
Currently (as of 22 Feb 2011) if you want to use Python for scripting GRASS on Windows, the best solution is to delete the bundled version of Python 2.5 from the GRASS installation, install Python and the required add-ons (wxPython, NumPy, PyWin32) from their official installers,&lt;br /&gt;
then edit the GRASS start-up script to remove any references to the bundled version.&lt;br /&gt;
&lt;br /&gt;
==== Linux ====&lt;br /&gt;
&lt;br /&gt;
The variables are set like this:&lt;br /&gt;
&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;
 # for parallel session management, we use process ID (PID) as lock file number:&lt;br /&gt;
 export GIS_LOCK=$$&lt;br /&gt;
 # path to GRASS settings file&lt;br /&gt;
 export GISRC=&amp;quot;$HOME/.grassrc6&amp;quot;&lt;br /&gt;
&lt;br /&gt;
=== Running external commands from Python ===&lt;br /&gt;
For information on running external commands from Python, see:&lt;br /&gt;
http://docs.python.org/lib/module-subprocess.html&lt;br /&gt;
&lt;br /&gt;
Avoid using the older os.* functions. Section 17.1.3 lists equivalents&lt;br /&gt;
using the Popen() interface, which is more robust (particularly on&lt;br /&gt;
Windows).&lt;br /&gt;
&lt;br /&gt;
=== Examples ===&lt;br /&gt;
&lt;br /&gt;
==== Display example ====&lt;br /&gt;
Example of Python script, which is processed by g.parser:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
#!/usr/bin/env python&lt;br /&gt;
#&lt;br /&gt;
############################################################################&lt;br /&gt;
#&lt;br /&gt;
# MODULE:      d.shadedmap&lt;br /&gt;
# AUTHOR(S):   Unknown; updated to GRASS 5.7 by Michael Barton&lt;br /&gt;
#              Converted to Python by Glynn Clements&lt;br /&gt;
# PURPOSE:     Uses d.his to drape a color raster over a shaded relief map&lt;br /&gt;
# COPYRIGHT:   (C) 2004,2008,2009 by the GRASS Development Team&lt;br /&gt;
#&lt;br /&gt;
#              This program is free software under the GNU General Public&lt;br /&gt;
#              License (&amp;gt;=v2). Read the file COPYING that comes with GRASS&lt;br /&gt;
#              for details.&lt;br /&gt;
#&lt;br /&gt;
#############################################################################&lt;br /&gt;
&lt;br /&gt;
#%Module&lt;br /&gt;
#% description: Drapes a color raster over a shaded relief map using d.his&lt;br /&gt;
#%End&lt;br /&gt;
#%option&lt;br /&gt;
#% key: reliefmap&lt;br /&gt;
#% type: string&lt;br /&gt;
#% gisprompt: old,cell,raster&lt;br /&gt;
#% description: Name of shaded relief or aspect map&lt;br /&gt;
#% required : yes&lt;br /&gt;
#%end&lt;br /&gt;
#%option&lt;br /&gt;
#% key: drapemap&lt;br /&gt;
#% type: string&lt;br /&gt;
#% gisprompt: old,cell,raster&lt;br /&gt;
#% description: Name of raster to drape over relief map&lt;br /&gt;
#% required : yes&lt;br /&gt;
#%end&lt;br /&gt;
#%option&lt;br /&gt;
#% key: brighten&lt;br /&gt;
#% type: integer&lt;br /&gt;
#% description: Percent to brighten&lt;br /&gt;
#% options: -99-99&lt;br /&gt;
#% answer: 0&lt;br /&gt;
#%end&lt;br /&gt;
&lt;br /&gt;
import sys&lt;br /&gt;
from grass.script import core as grass&lt;br /&gt;
&lt;br /&gt;
def main():&lt;br /&gt;
    drape_map = options['drapemap']&lt;br /&gt;
    relief_map = options['reliefmap']&lt;br /&gt;
    brighten = options['brighten']&lt;br /&gt;
    ret = grass.run_command(&amp;quot;d.his&amp;quot;, h_map = drape_map,  i_map = relief_map, brighten = brighten)&lt;br /&gt;
    sys.exit(ret)&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    options, flags = grass.parser()&lt;br /&gt;
    main()&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Parsing the options and flags  ====&lt;br /&gt;
&lt;br /&gt;
grass.parser() is an interface to g.parser, and allows to parse the options and flags passed to your script on the command line. It is to be called at the top-level:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    options, flags = grass.parser()&lt;br /&gt;
    main()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Global variables &amp;quot;options&amp;quot; and &amp;quot;flags&amp;quot; are Python dictionaries containing the options/flags values, keyed by lower-case option/flag names. The values in &amp;quot;options&amp;quot; are strings, those in &amp;quot;flags&amp;quot; are Python booleans. All those variables have to be previously declared in the header of your script.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
&amp;gt;&amp;gt;&amp;gt; options, flags = grass.parser()&lt;br /&gt;
&amp;gt;&amp;gt;&amp;gt; options&lt;br /&gt;
{'input': 'my_map', 'size': '21.472', 'output': 'map_out'}&lt;br /&gt;
&amp;gt;&amp;gt;&amp;gt; flags&lt;br /&gt;
{'c': True, 'm': False}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Example for embedding r.mapcalc (map algebra) ====&lt;br /&gt;
&lt;br /&gt;
grass.mapcalc() accepts a template string followed by keyword&lt;br /&gt;
arguments for the substitutions, e.g. (code snippets):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
grass.mapcalc(&amp;quot;${out} = ${rast1} + ${rast2}&amp;quot;,&lt;br /&gt;
              out = options['output'],&lt;br /&gt;
              rast1 = options['raster1'],&lt;br /&gt;
              rast2 = options['raster2'])&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
''Best practice'': first copy all of the options[] into separate variables at the beginning of main(), i.e.:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
def main():&lt;br /&gt;
    output = options['output']&lt;br /&gt;
    raster1 = options['raster1']&lt;br /&gt;
    raster2 = options['raster2']&lt;br /&gt;
 &lt;br /&gt;
    ...&lt;br /&gt;
 &lt;br /&gt;
    grass.mapcalc(&amp;quot;${out} = ${rast1} + ${rast2}&amp;quot;,&lt;br /&gt;
                  out = output,&lt;br /&gt;
                  rast1 = raster1,&lt;br /&gt;
                  rast2 = raster2)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Example for parsing category numbers ====&lt;br /&gt;
&lt;br /&gt;
Q: How to obtain the number of cells of a certain category?&lt;br /&gt;
&lt;br /&gt;
A: It is recommended to use pipe_command() and parse the output, e.g.:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
       p = grass.pipe_command('r.stats',flags='c',input='map')&lt;br /&gt;
       result = {}&lt;br /&gt;
       for line in p.stdout:&lt;br /&gt;
           val,count = line.strip().split()&lt;br /&gt;
           result[int(val)] = int(count)&lt;br /&gt;
       p.wait()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Example for getting the region's number of rows and columns ====&lt;br /&gt;
&lt;br /&gt;
Q: How to obtain the number of rows and columns of the current region?&lt;br /&gt;
&lt;br /&gt;
A: It is recommended to use the &amp;quot;grass.region()&amp;quot; function which will create a dictionary with values for extents and resolution, e.g.:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source 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;
############################################################################&lt;br /&gt;
#&lt;br /&gt;
# MODULE:       g.region.resolution&lt;br /&gt;
# AUTHOR(S):    based on a post at GRASS-USER mailing list [1]               &lt;br /&gt;
# PURPOSE:	Parses &amp;quot;g.region -g&amp;quot;, prints out number of rows, cols&lt;br /&gt;
# COPYLEFT:     ;-)&lt;br /&gt;
# COMMENT:      ...a lot of comments to be easy-to-read for/by beginners&lt;br /&gt;
#&lt;br /&gt;
#############################################################################&lt;br /&gt;
#&lt;br /&gt;
#%Module&lt;br /&gt;
#% description: Print number of rows, cols of current geographic region&lt;br /&gt;
#% keywords: region&lt;br /&gt;
#%end&lt;br /&gt;
&lt;br /&gt;
# importing required modules&lt;br /&gt;
import sys # the sys module [2]&lt;br /&gt;
from grass.script import core as grass # the core module [3]&lt;br /&gt;
&lt;br /&gt;
# information about imported modules can be obtained using the dir() function&lt;br /&gt;
# e.g.: dir(sys)&lt;br /&gt;
&lt;br /&gt;
# define the &amp;quot;main&amp;quot; function: get number of rows, cols of region&lt;br /&gt;
def main():&lt;br /&gt;
    &lt;br /&gt;
    # #######################################################################&lt;br /&gt;
    # the following commented code works but is kept only for learning purposes&lt;br /&gt;
     &lt;br /&gt;
    ## assigning the output of the command &amp;quot;g.region -g&amp;quot; in a string called &amp;quot;return_rows_x_cols&amp;quot;&lt;br /&gt;
    # return_rows_x_cols = grass.read_command('g.region', flags = 'g')&lt;br /&gt;
    &lt;br /&gt;
    ## parsing arguments of interest (rows, cols) in a dictionary named &amp;quot;rows_x_cols&amp;quot;&lt;br /&gt;
    # rows_x_cols = grass.parse_key_val(return_rows_x_cols)&lt;br /&gt;
    &lt;br /&gt;
    ## selectively print rows, cols from the dictionary &amp;quot;rows_x_cols&amp;quot;&lt;br /&gt;
    # print 'rows=%d \ncols=%d' % (int(rows_x_cols['rows']), int(rows_x_cols['cols']))&lt;br /&gt;
    &lt;br /&gt;
    # #######################################################################&lt;br /&gt;
    &lt;br /&gt;
    # faster/ easier way: use of the &amp;quot;grass.region()&amp;quot; function&lt;br /&gt;
    gregion = grass.region()&lt;br /&gt;
    rows = gregion['rows']&lt;br /&gt;
    cols = gregion['cols']&lt;br /&gt;
    &lt;br /&gt;
    # print rows, cols properly formated &lt;br /&gt;
    print 'rows=%d \ncols=%d' % (rows, cols)&lt;br /&gt;
&lt;br /&gt;
# this &amp;quot;if&amp;quot; condition instructs execution of code contained in this script, *only* if the script is being executed directly &lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;: # this allows the script to be used as a module in other scripts or as a standalone script&lt;br /&gt;
    options, flags = grass.parser() #&lt;br /&gt;
    sys.exit(main()) #&lt;br /&gt;
&lt;br /&gt;
# Links&lt;br /&gt;
# [1] http://n2.nabble.com/Getting-rows-cols-of-a-region-in-a-script-tp2787474p2787509.html&lt;br /&gt;
# [2] http://www.python.org/doc/2.5.2/lib/module-sys.html&lt;br /&gt;
# [3] http://download.osgeo.org/grass/grass6_progman/pythonlib.html#pythonCore&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Managing mapsets ====&lt;br /&gt;
&lt;br /&gt;
To check if a certain mapset exists in the active location, use:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
       grass.script.mapsets(False)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
... returns a list of mapsets in the current location.&lt;br /&gt;
&lt;br /&gt;
==== r.mapcalc example ====&lt;br /&gt;
&lt;br /&gt;
Example of Python script, which is processed by {{cmd|g.parser}}:&lt;br /&gt;
&lt;br /&gt;
The shell script line:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
  r.mapcalc &amp;quot;MASK = if(($cloudResampName &amp;lt; 0.01000),1,null())&amp;quot;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
would be written like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
       import grass.script as grass&lt;br /&gt;
&lt;br /&gt;
       ...&lt;br /&gt;
&lt;br /&gt;
       grass.mapcalc(&amp;quot;MASK=if(($cloudResampName &amp;lt; 0.01000),1,null())&amp;quot;,&lt;br /&gt;
                     cloudResampName = cloudResampName)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The first argument to the mapcalc function is a template (see the Python library documentation for [http://docs.python.org/library/string.html string.Template]). Any keyword arguments (other than quiet, verbose or overwrite) specify substitutions.&lt;br /&gt;
&lt;br /&gt;
==== Using output from GRASS modules in the script ====&lt;br /&gt;
&lt;br /&gt;
Sometimes you need to use the output of a module for the next step. There are dedicated functions to obtain the result of, for example, a statistical analysis.&lt;br /&gt;
&lt;br /&gt;
Example: get the range of a raster map and use it in {{cmd|r.mapcalc}}. Here you can use &amp;lt;code&amp;gt;grass.script.raster_info()&amp;lt;/code&amp;gt;, e.g.:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
       import grass.script as grass&lt;br /&gt;
&lt;br /&gt;
       max = grass.raster_info(inmap)['max']&lt;br /&gt;
       grass.mapcalc(&amp;quot;$outmap = $inmap / $max&amp;quot;,&lt;br /&gt;
                     inmap = inmap, outmap = outmap, max = max)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Calling a GRASS module in Python  ====&lt;br /&gt;
&lt;br /&gt;
Imagine, you wanted to execute this command in Python:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
  r.profile -g input=mymap output=newfile profile=12244.256,-295112.597,12128.012,-295293.77&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
All arguments except the first (which is a flag) are keyword arguments, i.e. &amp;lt;tt&amp;gt;arg = val&amp;lt;/tt&amp;gt;. For the flag, use &amp;lt;tt&amp;gt;flags = 'g'&amp;lt;/tt&amp;gt; (note that &amp;quot;-g&amp;quot; would be the negative of a Python variable named &amp;quot;g&amp;quot;!). So:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
       grass.run_command(&lt;br /&gt;
               'r.profile',&lt;br /&gt;
               input = input_map,&lt;br /&gt;
               output = output_file,&lt;br /&gt;
               profile = [12244.256,-295112.597,12128.012,-295293.77]&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
or:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
               profile = [(12244.256,-295112.597),(12128.012,-295293.77)]&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
i.e. you need to provide the keyword, and the argument must be a valid Python expression. Function &amp;lt;code&amp;gt;run_command()&amp;lt;/code&amp;gt; etc accept lists and tuples.&lt;br /&gt;
&lt;br /&gt;
'''Differences between ''run_command()'' and ''read_command()'':'''&lt;br /&gt;
&lt;br /&gt;
* run_command() executes the command and waits for it to terminate; it doesn't redirect any of the standard streams.&lt;br /&gt;
* read_command() executes the command with stdout redirected to a pipe, and reads everything written to it. Once the command terminates, it returns the data written to stdout as a string.&lt;br /&gt;
&lt;br /&gt;
'''How to retrieve error messages from ''read_command()'':'''&lt;br /&gt;
&lt;br /&gt;
None of the existing *_command functions redirect stderr. You can do so with e.g.:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
def read2_command(*args, **kwargs):&lt;br /&gt;
   kwargs['stdout'] = grass.PIPE&lt;br /&gt;
   kwargs['stderr'] = grass.PIPE&lt;br /&gt;
   ps = grass.start_command(*args, **kwargs)&lt;br /&gt;
   return ps.communicate()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This behaves like read_command() except that it returns a tuple of (stdout,stderr) rather than just stdout.&lt;br /&gt;
&lt;br /&gt;
==== Path to GISDBASE ====&lt;br /&gt;
&lt;br /&gt;
In order to a avoid hardcoded paths to GRASS mapset files like the SQLite DB file, you can get the GISDBASE variable from the environment:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
       import grass.script as grass&lt;br /&gt;
       import os.path&lt;br /&gt;
&lt;br /&gt;
       env = grass.gisenv()&lt;br /&gt;
&lt;br /&gt;
       gisdbase = env['GISDBASE']&lt;br /&gt;
       location = env['LOCATION_NAME']&lt;br /&gt;
       mapset = env['MAPSET']&lt;br /&gt;
&lt;br /&gt;
       path = os.path.join(gisdbase, location, mapset, 'sqlite.db')&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Python extensions for GRASS GIS==&lt;br /&gt;
=== wxPython GUI development for GRASS ===&lt;br /&gt;
&lt;br /&gt;
* See the [[wxGUI]] wiki page&lt;br /&gt;
&lt;br /&gt;
=== GRASS Python Scripting Library ===&lt;br /&gt;
&lt;br /&gt;
See [http://grass.osgeo.org/programming7/pythonlib.html GRASS Python Scripting Library] (Programmer's manual). See also [[Converting Bash scripts to Python]], and [http://trac.osgeo.org/grass/browser/grass/trunk/scripts sample Python scripts in GRASS 7]&lt;br /&gt;
&lt;br /&gt;
==== Uses for read, feed and pipe, start and exec commands ====&lt;br /&gt;
&lt;br /&gt;
All of the *_command functions use make_command to construct a command&lt;br /&gt;
line for a program which uses the GRASS parser. Most of them then pass&lt;br /&gt;
that command line to ''subprocess.Popen()'' via ''start_command()'', except&lt;br /&gt;
for ''exec_command()'' which uses ''os.execvpe()''.&lt;br /&gt;
&lt;br /&gt;
[To be precise, they use grass.Popen(), which just calls&lt;br /&gt;
subprocess.Popen() with shell=True on Windows and shell=False&lt;br /&gt;
otherwise. On Windows, you need to use shell=True to be able to&lt;br /&gt;
execute scripts (including batch files); shell=False only works with&lt;br /&gt;
binary executables.]&lt;br /&gt;
&lt;br /&gt;
start_command() separates the arguments into those which&lt;br /&gt;
subprocess.Popen() understands and the rest. The rest are passed to&lt;br /&gt;
make_command() to construct a command line which is passed as the&lt;br /&gt;
&amp;quot;args&amp;quot; parameter to subprocess.Popen().&lt;br /&gt;
&lt;br /&gt;
In other words, start_command() is a GRASS-oriented interface to&lt;br /&gt;
subprocess.Popen(). It should be suitable for any situation where you&lt;br /&gt;
would use subprocess.Popen() to execute a normal GRASS command (one&lt;br /&gt;
which uses the GRASS parser, which is almost all of them; the main&lt;br /&gt;
exception is r.mapcalc in 6.x).&lt;br /&gt;
&lt;br /&gt;
Most of the others are convenience wrappers around start_command(), for common use cases.&lt;br /&gt;
&lt;br /&gt;
* run_command() calls the wait() method on the process, so it doesn't return until the command has finished, and returns the command's exit code. Similar to system().&lt;br /&gt;
&lt;br /&gt;
* pipe_command() calls start_command() with stdout=PIPE and returns the process object. You can use the process' .stdout member to read the command's stdout. Similar to popen(..., &amp;quot;r&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
* feed_command() calls start_command() with stdin=PIPE and returns the process object. You can use the process' .stdin member to write to the command's stdout. Similar to popen(..., &amp;quot;w&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
* read_command() calls pipe_command(), reads the data from the command's stdout, and returns it as a string. Similar to `backticks` in the shell.&lt;br /&gt;
&lt;br /&gt;
* write_command() calls feed_command(), sends the string specified by the &amp;quot;stdin&amp;quot; argument to the command's stdin, waits for the command to finish and returns its exit code. Similar to &amp;quot;echo ... | command&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
* parse_command() calls read_command() and parses its output as key-value pairs. Useful for obtaining information from g.region, g.proj, r.info, etc.&lt;br /&gt;
&lt;br /&gt;
* exec_command() doesn't use start_command() but os.execvpe(). This causes the specified command to replace the current program (i.e. the Python script), so exec_command() never returns. Similar to bash's &amp;quot;exec&amp;quot; command. This can be useful if the script is a &amp;quot;wrapper&amp;quot; around a single command, where you construct the command line and execute the command as the final step.&lt;br /&gt;
&lt;br /&gt;
If you have any other questions, you might want to look at the code ($GISBASE/etc/python/grass/script/core.py). Most of these functions are only a few lines long.&lt;br /&gt;
&lt;br /&gt;
==== Interfacing with NumPy ====&lt;br /&gt;
&lt;br /&gt;
''Glynn writes:''&lt;br /&gt;
&lt;br /&gt;
The {{api|pythonlib.html#pythonArray|grass.script.array}} module defines a {{api|classpython_1_1array_1_1array.html|class array}} which is a subclass of [http://docs.scipy.org/doc/numpy/reference/generated/numpy.memmap.html numpy.memmap] with &amp;lt;code&amp;gt;.read()&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;.write()&amp;lt;/code&amp;gt; methods to read/write the underlying file via {{cmd|r.out.bin}}/{{cmd|r.in.bin}}.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
    import grass.script.array as garray&lt;br /&gt;
    a = garray.array()&lt;br /&gt;
    a.read(&amp;quot;elevation.dem&amp;quot;)&lt;br /&gt;
    b = garray.array()&lt;br /&gt;
    b[...] = (a / 50).astype(int) * 50  # or whatever&lt;br /&gt;
    b.write(&amp;quot;elev.50m&amp;quot;)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The size of the array is taken from the current region.&lt;br /&gt;
&lt;br /&gt;
The main drawback of using numpy is that you're limited by available&lt;br /&gt;
memory. Using a subclass of &amp;lt;code&amp;gt;numpy.memmap&amp;lt;/code&amp;gt; lets you use files which may&lt;br /&gt;
be much larger, but processing the entire array in one go is likely to&lt;br /&gt;
produce in-memory results of a similar size.&lt;br /&gt;
&lt;br /&gt;
One may also use the scipy matlab interface:&lt;br /&gt;
    &lt;br /&gt;
    ### SH: in GRASS ###&lt;br /&gt;
    r.out.mat input=elevation output=elev.mat&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
    ### PY ###&lt;br /&gt;
    import scipy.io as sio&lt;br /&gt;
    # load data&lt;br /&gt;
    elev = sio.loadmat('elev.mat')&lt;br /&gt;
    # retrive the actual array. the data set contains also the spatial reference&lt;br /&gt;
    elev.get('map_data')&lt;br /&gt;
    data = elev.get('map_data')&lt;br /&gt;
    # a first simple plot&lt;br /&gt;
    import pylab&lt;br /&gt;
    pylab.plot(data)&lt;br /&gt;
    pylab.show()&lt;br /&gt;
    # the contour plot&lt;br /&gt;
    pylab.contour(data)&lt;br /&gt;
    # obviously data needs to ne reversed&lt;br /&gt;
    import numpy as np&lt;br /&gt;
    data_rev = data[::-1]&lt;br /&gt;
    pylab.contour(data_rev)&lt;br /&gt;
    # =&amp;gt; this is a quick plot. basemap mapping may provide a nicer map!&lt;br /&gt;
    #######&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Python Ctypes Interface ===&lt;br /&gt;
&lt;br /&gt;
This interface allows calling GRASS library functions from Python scripts. See [[Python Ctypes Examples]] for details.&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
&lt;br /&gt;
* GRASS 7: [http://trac.osgeo.org/grass/browser/grass/trunk/doc/python/raster_example_ctypes.py raster], [http://trac.osgeo.org/grass/browser/grass/trunk/doc/python/vector_example_ctypes.py vector] example&lt;br /&gt;
&lt;br /&gt;
=== Python SWIG interface ===&lt;br /&gt;
&lt;br /&gt;
  Warning: The GRASS-SWIG interface isn't particularly stable and well understood. Please consider to use the Python ctypes GRASS above.&lt;br /&gt;
&lt;br /&gt;
There is a prototype GRASS-SWIG interface available (thanks to Sajith VK), find it in GRASS 6-CVS: '''swig/python/'''. Draft documentation is [http://download.osgeo.org/grass/grass6_progman/swig/ here]. It now wraps both raster and vector data C functions plus the general GIS (G_*()) functions.&lt;br /&gt;
&lt;br /&gt;
Background: [http://www.swig.org SWIG] (Simplified Wrapper and Interface Generator) is: &lt;br /&gt;
&lt;br /&gt;
* A compiler that turns ANSI C/C++ declarations into scripting language interfaces.&lt;br /&gt;
* Completely automated (produces a fully working Python extension module). &lt;br /&gt;
* Language neutral. SWIG can also target Tcl, Perl, Guile, MATLAB (try PyLab+Matplotlib from python), etc... &lt;br /&gt;
* Attempts to eliminate the tedium of writing extension modules.&lt;br /&gt;
&lt;br /&gt;
==== Python-SWIG examples ====&lt;br /&gt;
&lt;br /&gt;
* Latest and greatest: [[http://trac.osgeo.org/grass/browser/grass/trunk/scripts GRASS 7 Python scripts]]&lt;br /&gt;
&lt;br /&gt;
* [[PythonSwigExamples|More complicated examples]]&lt;br /&gt;
&lt;br /&gt;
Sample script for GRASS 6 raster access (use within GRASS, Spearfish session):&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
#!/usr/bin/env python&lt;br /&gt;
&lt;br /&gt;
import os, sys&lt;br /&gt;
from grass.lib import grass&lt;br /&gt;
&lt;br /&gt;
if &amp;quot;GISBASE&amp;quot; not in os.environ:&lt;br /&gt;
    print &amp;quot;You must be in GRASS GIS to run this program.&amp;quot;&lt;br /&gt;
    sys.exit(1)&lt;br /&gt;
&lt;br /&gt;
if len(sys.argv)==2:&lt;br /&gt;
  input = sys.argv[1]&lt;br /&gt;
else:&lt;br /&gt;
  input = raw_input(&amp;quot;Raster Map Name? &amp;quot;)&lt;br /&gt;
&lt;br /&gt;
# initialize&lt;br /&gt;
grass.G_gisinit('')&lt;br /&gt;
&lt;br /&gt;
# find map in search path&lt;br /&gt;
mapset = grass.G_find_cell2(input, '')&lt;br /&gt;
&lt;br /&gt;
# determine the inputmap type (CELL/FCELL/DCELL) */&lt;br /&gt;
data_type = grass.G_raster_map_type(input, mapset)&lt;br /&gt;
&lt;br /&gt;
infd = grass.G_open_cell_old(input, mapset)&lt;br /&gt;
inrast = grass.G_allocate_raster_buf(data_type)&lt;br /&gt;
&lt;br /&gt;
rown = 0&lt;br /&gt;
while True:&lt;br /&gt;
    myrow = grass.G_get_raster_row(infd, inrast, rown, data_type)&lt;br /&gt;
    print rown, myrow[0:10]&lt;br /&gt;
    rown += 1&lt;br /&gt;
    if rown == 476:&lt;br /&gt;
        break&lt;br /&gt;
&lt;br /&gt;
grass.G_close_cell(inrast)&lt;br /&gt;
grass.G_free(cell)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Sample script for vector access (use within GRASS, Spearfish session):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
#!/usr/bin/python&lt;br /&gt;
&lt;br /&gt;
# run within GRASS Spearfish session&lt;br /&gt;
# run this before starting python to append module search path:&lt;br /&gt;
#   export PYTHONPATH=/usr/src/grass70/swig/python&lt;br /&gt;
#   check with &amp;quot;import sys; sys.path&amp;quot;&lt;br /&gt;
# or:&lt;br /&gt;
#   sys.path.append(&amp;quot;/usr/src/grass70/swig/python&amp;quot;)&lt;br /&gt;
# FIXME: install the grass bindings in $GISBASE/lib/ ?&lt;br /&gt;
&lt;br /&gt;
import os, sys&lt;br /&gt;
from grass.lib import grass&lt;br /&gt;
from grass.lib import vector as grassvect&lt;br /&gt;
&lt;br /&gt;
if &amp;quot;GISBASE&amp;quot; not in os.environ:&lt;br /&gt;
    print &amp;quot;You must be in GRASS GIS to run this program.&amp;quot;&lt;br /&gt;
    sys.exit(1)&lt;br /&gt;
&lt;br /&gt;
if len(sys.argv)==2:&lt;br /&gt;
  input = sys.argv[1]&lt;br /&gt;
else:&lt;br /&gt;
  input = raw_input(&amp;quot;Vector Map Name? &amp;quot;)&lt;br /&gt;
&lt;br /&gt;
# initialize&lt;br /&gt;
grass.G_gisinit('')&lt;br /&gt;
&lt;br /&gt;
# find map in search path&lt;br /&gt;
mapset = grass.G_find_vector2(input,'')&lt;br /&gt;
&lt;br /&gt;
# define map structure&lt;br /&gt;
map = grassvect.Map_info()&lt;br /&gt;
&lt;br /&gt;
# define open level (level 2: topology)&lt;br /&gt;
grassvect.Vect_set_open_level (2)&lt;br /&gt;
&lt;br /&gt;
# open existing map&lt;br /&gt;
grassvect.Vect_open_old(map, input, mapset)&lt;br /&gt;
&lt;br /&gt;
# query&lt;br /&gt;
print 'Vect map: ', input&lt;br /&gt;
print 'Vect is 3D: ', grassvect.Vect_is_3d (map)&lt;br /&gt;
print 'Vect DB links: ', grassvect.Vect_get_num_dblinks(map)&lt;br /&gt;
print 'Map Scale:  1:', grassvect.Vect_get_scale(map)&lt;br /&gt;
print 'Number of areas:', grassvect.Vect_get_num_areas(map)&lt;br /&gt;
&lt;br /&gt;
# close map&lt;br /&gt;
grassvect.Vect_close(map)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== TODO ====&lt;br /&gt;
&lt;br /&gt;
* Implement modules support in a Python class using --interface-description and a Python-XML parser. This should be a generic class with module's name as parameter, returning back an object which describes the module (description, flags, parameters, status of not/required). See [http://trac.osgeo.org/grass/browser/grass/trunk/gui/wxpython/ GRASS 6 wxPython interface] for inspiration. Important is to auto-generate the GRASS-Python class at compile time with a Python script.&lt;br /&gt;
&lt;br /&gt;
=== Python-GRASS add-ons ===&lt;br /&gt;
&lt;br /&gt;
Stand-alone addons:&lt;br /&gt;
&lt;br /&gt;
# Jáchym Čepický's G-ps.map, a GUI to typeset printable maps with ps.map (http://193.84.38.2/~jachym/index.py?cat=gpsmap)&lt;br /&gt;
# Jáchym Čepický's v.pydigit, a GUI to v.edit (http://les-ejk.cz/?cat=vpydigit)&lt;br /&gt;
# Jáchym Čepický's PyWPS, GRASS-Web Processing Service (http://pywps.wald.intevation.org)&lt;br /&gt;
&lt;br /&gt;
=== Using GRASS gui.tcl in Python ===&lt;br /&gt;
&lt;br /&gt;
Here is some example code to use the grass automatically generated guis in python code. This could (should) all be bundled up and abstracted away so that the implementation can be replaced later.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
import Tkinter&lt;br /&gt;
import os&lt;br /&gt;
&lt;br /&gt;
# Startup (once):&lt;br /&gt;
&lt;br /&gt;
tk = Tkinter.Tk()&lt;br /&gt;
tk.eval (&amp;quot;wm withdraw .&amp;quot;)&lt;br /&gt;
tk.eval (&amp;quot;source $env(GISBASE)/etc/gui.tcl&amp;quot;)&lt;br /&gt;
# Here you could do various things to change what the gui does&lt;br /&gt;
# See gui.tcl and README.GUI&lt;br /&gt;
&lt;br /&gt;
# Make a gui (per dialog)&lt;br /&gt;
# This sets up a window for the command.&lt;br /&gt;
# This can be different to integrate with tkinter:&lt;br /&gt;
tk.eval ('set path &amp;quot;.dialog$dlg&amp;quot;')&lt;br /&gt;
tk.eval ('toplevel .dialog$dlg')&lt;br /&gt;
# Load the code for this command:&lt;br /&gt;
fd = os.popen (&amp;quot;d.vect --tcltk&amp;quot;)&lt;br /&gt;
gui = fd.read()&lt;br /&gt;
# Run it&lt;br /&gt;
tk.eval(gui)&lt;br /&gt;
dlg = tk.eval('set dlg') # This is used later to get and set &lt;br /&gt;
&lt;br /&gt;
# Get the current command in the gui we just made:&lt;br /&gt;
currentcommand = tk.eval (&amp;quot;dialog_get_command &amp;quot; + dlg)&lt;br /&gt;
&lt;br /&gt;
# Set the command in the dialog we just made:&lt;br /&gt;
tk.eval (&amp;quot;dialog_set_command &amp;quot; + dlg + &amp;quot; {d.vect map=roads}&amp;quot;)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== FAQ ==&lt;br /&gt;
&lt;br /&gt;
* '''Q:''' Error message &amp;quot;execl() failed: Permission denied&amp;quot; - what to do?&lt;br /&gt;
: '''A:''' Be sure that the execute bit of the script is set.&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
&lt;br /&gt;
=== General guides ===&lt;br /&gt;
&lt;br /&gt;
* [http://en.wikibooks.org/wiki/Python_Programming/ Wikibook Python Programming]&lt;br /&gt;
* [http://www.poromenos.org/tutorials/python Quick Python tutorial] for programmers of other languages&lt;br /&gt;
*: [http://wiki.python.org/moin/BeginnersGuide/Programmers More Python tutorials] for programmers&lt;br /&gt;
* [http://www.python.org/dev/peps/pep-0008/ Python programming style guide]&lt;br /&gt;
* [http://wiki.python.org/moin/PythonEditors Python Editors]&lt;br /&gt;
&lt;br /&gt;
=== Programming ===&lt;br /&gt;
&lt;br /&gt;
* Python and GRASS:&lt;br /&gt;
** GRASS Python interface to library functions: http://download.osgeo.org/grass/grass6_progman/swig/ based on SWIG http://www.swig.org/&lt;br /&gt;
** GRASS Python scripting library: http://download.osgeo.org/grass/grass6_progman/pythonlib.html&lt;br /&gt;
** PyWPS, GRASS-Web Processing Service http://pywps.wald.intevation.org&lt;br /&gt;
&lt;br /&gt;
* Python and OSGeo:&lt;br /&gt;
** [http://wiki.osgeo.org/wiki/OSGeo_Python_Library OSGeo Python Library]&lt;br /&gt;
&lt;br /&gt;
* Python and GDAL/OGR:&lt;br /&gt;
** [http://mapserver.gis.umn.edu/community/conferences/MUM3/workshop/python Open Source Python GIS Hacks Mum'03]&lt;br /&gt;
** http://hobu.biz/software/OSGIS_Hacks - Python OSGIS Hacks '05&lt;br /&gt;
** http://zcologia.com/news/categorylist_html?cat_id=8&lt;br /&gt;
** http://www.perrygeo.net/wordpress/?p=4&lt;br /&gt;
&lt;br /&gt;
* Python bindings to PROJ:&lt;br /&gt;
** http://www.cdc.noaa.gov/people/jeffrey.s.whitaker/python/pyproj.html&lt;br /&gt;
&lt;br /&gt;
* Python and GIS:&lt;br /&gt;
** [http://gispython.org/ Open Source GIS-Python Laboratory]&lt;br /&gt;
&lt;br /&gt;
* Python and Statistics:&lt;br /&gt;
** [http://rpy.sourceforge.net/ RPy] - Python interface to the R-statistics programming language&lt;br /&gt;
&lt;br /&gt;
* Bindings:&lt;br /&gt;
** SIP (C/C++ bindings generator) http://directory.fsf.org/all/Python-SIP.html&lt;br /&gt;
** [http://www.cython.org/ Cython] - C-Extensions for Python (compile where speed is needed)&lt;br /&gt;
&lt;br /&gt;
* Other external projects&lt;br /&gt;
** [http://www.scipy.org Scientific Python]&lt;br /&gt;
** [http://wiki.python.org/moin/NumericAndScientific Numeric and Scientific]&lt;br /&gt;
** [http://w3.pppl.gov/~hammett/comp/python/python.html Info on Python for Scientific Applications]&lt;br /&gt;
&lt;br /&gt;
=== Presentations ===&lt;br /&gt;
&lt;br /&gt;
From FOSS4G2006:&lt;br /&gt;
* [http://www.foss4g2006.org/materialDisplay.py?contribId=136&amp;amp;amp;sessionId=48&amp;amp;amp;materialId=slides&amp;amp;amp;confId=1 A Python sweeps in the GRASS] - A. Frigeri 2006&lt;br /&gt;
* [http://www.foss4g2006.org/materialDisplay.py?contribId=67&amp;amp;amp;sessionId=48&amp;amp;amp;materialId=slides&amp;amp;amp;confId=1 GRASS goes web: PyWPS] - J. Cepicky 2006&lt;br /&gt;
&lt;br /&gt;
{{Python}}&lt;/div&gt;</summary>
		<author><name>⚠️PierreRoudier</name></author>
	</entry>
</feed>