[GRASS-SVN] r57185 - in grass-addons/grass6/general: . g.infer

svn_grass at osgeo.org svn_grass at osgeo.org
Wed Jul 17 02:20:50 PDT 2013


Author: gisix
Date: 2013-07-17 02:20:50 -0700 (Wed, 17 Jul 2013)
New Revision: 57185

Added:
   grass-addons/grass6/general/g.infer/
   grass-addons/grass6/general/g.infer/Makefile
   grass-addons/grass6/general/g.infer/description.html
   grass-addons/grass6/general/g.infer/g.infer
   grass-addons/grass6/general/g.infer/reference.py
   grass-addons/grass6/general/g.infer/spearfish.py
Log:
g.infer: module added

Added: grass-addons/grass6/general/g.infer/Makefile
===================================================================
--- grass-addons/grass6/general/g.infer/Makefile	                        (rev 0)
+++ grass-addons/grass6/general/g.infer/Makefile	2013-07-17 09:20:50 UTC (rev 57185)
@@ -0,0 +1,7 @@
+MODULE_TOPDIR = ../..
+
+PGM = g.infer
+
+include $(MODULE_TOPDIR)/include/Make/Script.make
+
+default: script

Added: grass-addons/grass6/general/g.infer/description.html
===================================================================
--- grass-addons/grass6/general/g.infer/description.html	                        (rev 0)
+++ grass-addons/grass6/general/g.infer/description.html	2013-07-17 09:20:50 UTC (rev 57185)
@@ -0,0 +1,670 @@
+
+
+<h2>NAME</h2>
+<em><b>g.infer</b></em>
+<h2>KEYWORDS</h2>
+general, inference engine, expert system, rule engine, solver, workflow, classification, data-driven programming, rule based programming, CLIPS
+<h2>SYNOPSIS</h2>
+<b>g.infer</b><br>
+<b>g.infer help</b><br>
+
+<b>g.infer</b> [-<b>efix</b>]  [<b>rast</b>=<em>name[,name,...]</em>] [<b>rast3d</b>=<em>name[,name,...]</em>] [<b>vector</b>=<em>name[,name,...]</em>][<b>rulebase</b>=<em>name</em>][<b>library</b>=<em>name</em>] [<b>facts</b>=<em>name</em>] [<b>output</b>=<em>name[,name,...]</em>] [<b>columns</b>=<em>string</em>] [<b>export</b>=<em>name</em>] [<b>load_instances</b>=<em>name</em>] [<b>bload_instances</b>=<em>name</em>] [<b>save_instances</b>=<em>name</em>] [<b>bsave_instances</b>=<em>name</em>]  [<b>save</b>=<em>string[,string,...]</em>][<b>bsave</b>=<em>string[,string,...]</em>] [<b>strategy</b>=<em>string</em>] [<b>limit</b>=<em>integer</em>] [<b>salience</b>=<em>string</em>] [<b>module</b>=<em>string</em>] [<b>watch</b>=<em>string[,string,...]</em>] [<b>print</b>=<em>string</em>] [<b>config</b>=<em>string</em>] [<b>classdefault</b>=<em>string</em>][--<b>overwrite</b>]  [--<b>verbose</b>]  [--<b>quiet</b>]
+
+<h3>Flags</h3>
+<DL>
+<DT><b>-d</b></DT>
+<DD>Use log-files (dribble option of CLIPS engine).</DD>
+
+<!--
+<DT><b>-f(P)</b></DT>
+<DD>Print fact-base before the inference run.</DD>
+-->
+<DT><b>-i</b></DT>
+<DD>Launch interactive command prompt before the inference run. (use <b>Ctrl-D</b> to exit from prompt)  </DD>
+
+
+<DT><b>-e</b></DT>
+<DD>Forward internal rule engine error messages to the GRASS environment for printing</DD>
+
+<DT><b>-x</b></DT>
+<DD>Terminate module execution prior to inference run</DD>
+
+<DT><b>--overwrite</b></DT>
+<DD>Allow output files to overwrite existing files</DD>
+<DT><b>--verbose</b></DT>
+<DD>Verbose module output</DD>
+<DT><b>--quiet</b></DT>
+<DD>Quiet module output</DD>
+</DL>
+
+<h3>Parameters</h3>
+<DL>
+
+<DT><b>vector</b>=<em>name,[name,...]</em></DT>
+<DD>Vector layer(s) to be imported into the CLIPS fact base. Currently only point geometries are supported. </DD>
+
+
+<DT><b>rast</b>=<em>name,[name,...]</em></DT>
+<DD>Raster layer(s) to be imported into the CLIPS fact-base, including raster labels (default). </DD>
+
+<DT><b>rast3d</b>=<em>name,[name,...]</em></DT>
+<DD>Rast3d volume layer(s) to be imported into the CLIPS fact-base.</DD>
+
+<DT><b>facts</b>=<em>name</em></DT>
+<DD>ASCII file containing rule base data (facts)</DD>
+
+<DT><b>rulebase</b>=<em>name</em></DT>
+<DD>ASCII file containing rulebase elements  and related content (rules, templates, facts and objects).</DD>
+
+<DT><b>library</b>=<em>name</em></DT>
+<DD>A library of built-inrulebases. Currently available: reference, spearfish (to be used within the Spearfish demo location).</DD>
+
+<DT><b>export</b>=<em>name,[name,...]</em></DT>
+<DD>Export (previously imported) map layers (a subset of imported vector, raster or rast3d layers) and update the respective GRASS layers </DD>
+
+<DT><b>output</b>=<em>name</em></DT>
+<DD>New GRASS vector (points) layer to be created from the facts linked to a rule base template.</DD>
+
+<DT><b>columns</b>=<em>column name</em></DT>
+<DD>Attribute columns definition for the output vector layer (<b>output</b> option).</DD>
+
+
+<DT><b>strategy</b>=<em>string</em></DT>
+<DD>Sets conflict resolution (collission) strategy for the rulebase.</DD>
+<DD>Options: <em>breadth,complexity,depth,lex,mea,simplicity,random</em></DD>
+<DD>Default: <em>depth</em></DD>
+
+<DT><b>limit</b>=<em>integer</em></DT>
+<DD>Maximum number of rules to fire during the inference run. Does not apply to the refiring of the same rule.</DD>
+
+<DT><b>salience</b>=<em>string</em></DT>
+<DD>Strategy for rule precedence assessment by salience.
+<DD>Options: <em>when-defined,when-activated,every-cycle</em></DD>
+<DD>Default: <em>when-defined</em></DD>
+
+<DT><b>module</b>=<em>string</em></DT>
+<DD>For rule bases partitioned into modules: rule base module(s) on the focus stack.</DD>
+<DD>Default: <em>MAIN</em></DD>
+
+<DT><b>watch </b>=<em>string[,string,...]</em></DT>
+<DD>Selection of rule engine operations to be watched (logged):
+</DD>
+<DD>Options: <em>activations,compilations,facts,functions,genericfunctions,globals,methods,messagehandlers,messages,rules,slots,statistics,all</em></DD>
+<DD>Default: <em>none</em></DD>
+
+<DT><b>print </b>=<em>string[,string,...]</em></DT>
+<DD>Environment information to be printed out before the inference run.
+
+<DD>Options: <em>agenda,breakpoints,classes,deffacts,definstances,facts,focusstack,functions,generics,globals,instances,messagehandlers,modules,rules,templates</em></DD>
+<DD>Default: <em>none</em></DD>
+
+<DT><b>config </b>=<em>string</em></DT>
+<DD>Rule engine configuration</DD>
+<DD>Options: <em>auto-float-dividend,dynamic-constraint-checking,fact-duplication,incremental-reset,reset-globals,sequence-operator-recognition,static-constraint-checking</em></DD>
+<DD>Default: <em>none</em></DD>
+
+<DT><b>classdefault </b>=<em>string</em></DT>
+<DD>Class defaults</DD>
+
+<DD>Options: <em>convenience,conservation</em></DD>
+<DD>Default: <em>convenience</em></DD>
+
+
+
+<DT><b>save_instances</b>=<em>name</em></DT>
+<DD>Object instances to be saved (ASCII)</DD>
+
+<DT><b>bsave_instances</b>=<em>name</em></DT>
+<DD>Object instances to be saved (binary).</DD>
+
+<DT><b>load_instances</b>=<em>name</em></DT>
+<DD>ASCII file containing objects</DD>
+
+<DT><b>bload_instances</b>=<em>name</em></DT>
+<DD>Binary file containing objects</DD>
+
+
+<DT><b>save</b>=<em>string</em></DT>
+<DD>Rule base entities to be saved (ASCII)</DD>
+<DD>Options: <em>constructs,facts,instances</em></DD>
+
+<DT><b>bsave</b>=<em>string</em></DT>
+<DD>Rule base entities to be saved (binary) </DD>
+<DD>Options: <em>constructs,facts,instances</em></DD>
+
+
+
+
+
+<h2>Description</h2>
+
+<b>g.infer</b> is a tool to create rule-based data-driven workflows from GRASS data layers and additional data sources.
+<b>g.infer</b> can modify existing GRASS data layers, can create new vector layers or can start additional additional GRASS modules. This is controlled by an inference process,
+which applies a knowledge base on a set of known facts (data). g.infer provides a <b>Production System</b> to set up <b>Expert Systems</b> from domain knowledge and GIS data layers. <p>
+
+<p>
+The g.infer inference environment is based on a strict separation of knowledge (rules) and data (facts and  object instances).
+ Data consists of GRASS-derived spatial information and other input. The g.infer inference engine applies the knowledge, consisting of rules (stored in the rulebase), to the available data.
+ For development and testing, interactive access and logging options are available.
+<p>
+g.infer provides a flexible environment to start rule-based work. For complex tasks there are also advanced capabilities to extend the knowledge modelling whenever necessary.
+This approach can be used for geodata classification, GIS workflow control and other tasks.
+
+<p>
+The <b>C-Language Integrated Production System (CLIPS) Expert System Shell</b> environment is embedded within g.infer using the <b>pyCLIPS</b> Python module. In depth information is found in the References, which contain also links to literature describing the projects <b>Jess</b> and <b>Drools</b> which are based on CLIPS. Their documentation contains additional clues for CLIPS-related development.
+<p>
+The exchange of data between the GRASS and CLIPS environments is handled by extensions of the pyCLIPS functionality, connecting both GRASS and CLIPS. See the "Notes on g.infer pyCLIPS extensions" section for details. <p>
+
+
+
+<h3>Input</h3>
+
+g.infer can ingest multiple input sources as data: Spatial information can be imported from GRASS data layers (raster, rast3d, point-vector) and additional sources. Rule base-related constructs (templates, facts, classes and instances) are read from external files or built-in rule bases via the library option.
+<p>
+Additional data can also be imported during the inference process if requested by the rule base. The user can further enter facts and rulebase elements via an interactive CLIPS prompt.
+
+<h3>Output</h3>
+
+g.infer can manipulate the content of imported GRASS data layers and other sources of data.
+These changes can be written back to the respective GRASS layers using the <b>export</b> option for persistent storage.
+A new vector layer can be created through the <b>output</b> option. The creation of additional GRASS layers can be invoked by the rulebase beyond the limited range of options provided by g.infer module parameters.
+
+
+
+<h3>Rulebase</h3>
+
+The g.infer rulebases contains the working knowledge for the inference process, which is seperate from the data (facts). They are read from file by the <b>rulebase</b> option or selected using the <b>library</b> option. Rulebases can be edited via the interactive CLIPS prompt (-i flag) before the actual inference run. <p>
+
+There are three ways  to represent knowledge in g.infer. They are based on concepts from the CLIPS programming language (see CLIPS documentation for details). All of them can be part of the rulebase:
+<ul>
+<li><b>Rules</b>, for heuristic knowledge based on experience. Rules can be applied to facts and objects.
+<p>
+<li><b>Functional Programming</b>, where functions defined as code returning values based on the provided input.
+<p>
+<li><b>Object-oriented programming</b>, supporting  features such as classes, message-handlers, abstraction, encapsulation, inheritance and polymorphism.
+</ul>
+<p>
+ Rules adhere to a IF THEN layout defined by the CLIPS programming language (see below). The condition antecedent ("IF") -part is referred to as left hand side (<b>LHS</b>), while the invoked consequent ("THEN") is  called the right hand side (<b>RHS</b>). LHS and RHS sides of a rule statement are connected by the "<b>=></b>" characters. 
+<p>
+
+
+<h3>Inference Engine</h3>
+
+The inference engine is the part of the g.infer module which evaluates what rules are to be applied, based on the currently available data (facts).
+
+The CLIPS inference engine used in g.infer is based on the Rete algorithm (Forgy 1982), using a forward-chaining data-driven approach.
+The order in which rules are to be executed can be controlled in three ways: By explicitly defining <b>salience</b> values for each rule,
+knowledge base partitioning by <b>modules</b> or implicitly by setting the
+<b>conflict resolution</b> strategy (<b>strategy</b> option).  The section "Rulbase Development, Operation and Debugging" holds a more detailed description.
+
+<p>
+
+<h3>Performance</h3>
+The Rete-algorithm performs well for a change  below 10 percent of the available data (facts) during an inference run.
+Scenarios, in which the complete content of a GRASS layer must be changed, resulting in 100 percent change, will result in decreased performance.
+<p>
+g.infer uses the current settings of the GRASS region to create facts from the GIS layers which are provided as input. The resolution of the region must be set appropriately for the task, as a very high resolution will result in a large number of facts.
+
+<h3>Knowledge Engineering in g.infer</h3>
+
+Knowledge engineering (modelling) in g.infer involves in most cases the definition of  rules for the rulebase. It can also include more complex programming tasks, such as conditions, loops, functions and object oriented programming.
+
+ For knowledge modelling and programming in g.infer, the programming language of the CLIPS Expert System Toolkit is used, which is closely related to the programming language <b>LISP</b>.
+For an in depth description of the CLIPS language, refer to the CLIPS Users's Guide and Reference Manuals (Giarratano 2007, 2008). A useful introduction to LISP is provided by Graham, 1995.<p>
+
+In the following, the given <i>examples</i> refer to a rulebase and are imported via a rulebase file, from a built in demo rulebase, or are entered using the interactive CLIPS prompt. This CLIPS-based <b>programming</b> can not be mixed with GRASS GIS scripting, but can invoke GRASS modules as part of the RHS of rules.
+
+<h4>Rulebase Notation</h4>
+
+<b>g.infer</b> rulebase constructs use a fully parenthesized polish prefix notation: Any term, or formula, must be put in braces, with the operator preceding the operands:
+<pre>(operator operand1 operand2 ... operandN)</pre>
+<p>
+This differs from the infix notation commonly used in GRASS GIS, like in r.mapcalc:
+<p>
+
+<ul>
+<li><pre><b>Infix (GRASS GIS)</b>: ((1 + 2) + 3 )  Result: 6</pre>
+<li><pre><b>Prefix (CLIPS)</b>:    (+ (+ 1 2) 3 )  Result: 6</pre>
+</ul>
+<p>
+
+<h4>Data Types</h4>
+g.infer's rule engine provides eight primitive data types for representing information.
+As the programming language of the CLIPS Production System is weakly typed, variables can be declared without explicitly setting a type. The available types are <b>float, integer, symbol, string, external-address, fact-address, instance-name</b> and <b>instance-address</b>. <b>Numeric information</b> can be represented using floats and integers. <b>Symbolic information</b> can be represented using symbols and strings.A number consists only of digits (0-9), a decimal point (.), a sign (+ or -), and, optionally, an (e) for exponential notation with its corresponding sign. A number is either stored as a float or an integer. Any number consisting of an optional sign followed by only digits is stored as an integer. All other numbers are stored as floats.
+
+<p>
+
+<h4>Facts</h4>
+
+Facts are the common high level form for representing information in g.infer.
+Within the CLIPS Production System, facts are the fundamental unit of data to be processed by the rulebase to infer information by the firing of applicable rules.
+Each fact represents a piece of data which has been placed in the overall <b>fact list</b> of the currently known facts.
+
+
+<p>
+Facts may be added to the fact list (using the <b>assert</b> command), removed from the fact list (using the <b>retract</b> command),
+modified (using the <b>modify</b> command), or duplicated (using the <b>duplicate</b> command) by either direct user interaction or while the rule base is executed.
+The number of facts in the <b>fact list</b>  and the amount of information that can be stored within a fact is limited only by the amount of available memory.
+If a fact is to be asserted into the fact list which exactly matches an already existing fact, the new assertion will be ignored. This default behaviour can be changed.
+
+<p>
+Some CLIPS language commands, including <b>retract, modify,</b> and <b>duplicate</b>, require a fact to be specified by a reference.
+A fact can be specified either by fact index or fact address:
+Whenever a fact is asserted (or modified) it is assigned a unique index number called its <b>fact index</b>.
+Fact indices start at zero and are incremented by one for each new or changed fact. Whenever a <b>reset</b> or <b>clear</b> command is given, the fact indices restart at zero.
+A fact may also be specified through the use of a <b>fact address</b>.
+A fact address can be obtained by capturing the return value of commands which return fact addresses (such as assert, modify, and duplicate)
+or by binding a variable to the fact address of a  fact which matches a pattern on the LHS of a rule.
+A <b>fact identifier</b> is a shorthand notation for printing a fact. It consists of the character <b>f</b>, followed by a dash, followed by the fact index of the fact.
+<p>
+
+
+There are two categories of facts, <b>ordered facts</b> and <b>non-ordered facts</b>. Both types are applied in g.infer to represent information imported from the GRASS GIS environment.
+
+
+
+<p>
+
+<h5> Ordered facts </h5>
+<p>
+Ordered facts consist of a symbol followed by a sequence of zero or more fields separated by spaces and delimited by an opening parenthesis on the left and a closing parenthesis on the right.
+Ordered facts encode information positionally and can contain multiple data fields. The first field of an ordered fact specifies a <b>relation</b> that applied to the remaining fields in the ordered fact.
+
+For example, <pre>(is-a GRASS GIS)</pre> states that GRASS is a GIS.
+
+<p>
+
+See the CLIPS Introduction and User Guides in the Reference Section for an in-depth discussion.
+
+
+
+<p>
+
+A simple fact can contain multiple fields for content:
+
+<pre>(assert (trail "OtterTrail" scenic flat))</pre>
+
+<h5> GRASS environment variables as ordered facts </h5>
+<p>
+Ordered facts are used to represent GRASS enironment variables into g.infer, including g.region parameters. These ordered facts can be manipulated within the CLIPS environment and be used when calling GRASS modules from within CLIPS. They must be exported back into GRASS to become permanent within the current session, which is not done by default. The following representations of GRASS environment variables as facts are generated by default:
+<p>
+
+REGION_ROWS, REGION_COLS, REGION_CELLS, REGION_NSRES, REGION_EWRES, REGION_N, REGION_S, REGION_E, REGION_W, REGION_ROWS3, REGION_COLS3, REGION_CELLS3, REGION_NSRES3, REGION_EWRES3, REGION_TBRES, REGION_T, REGION_B, REGION_DEPTHS, GISDBASE, LOCATION_NAME, MAPSET, GRASS_GUI
+
+
+
+
+<h5> Non-ordered facts </h5>
+
+<p>
+Facts to contain structured information require a <b>template</b> to define the structure:
+<p>
+Template based, non ordered facts allow to structure the content of a fact by assessing data fields by name (and type).
+The <b>deftemplate</b> construct  is used to create a named template (which can then be used to access fields by name). This approach is used to import GRASS layers in g.infer to create the respective facts.
+<p>
+
+
+The deftemplate construct allows the name of a template to be defined along with zero or more definitions of named fields, also called slots. Unlike ordered facts, the slots of a deftemplate fact may be constrained by type, value, and numeric range. In addition, default values can be specified for a slot. A slot consists of an opening parenthesis followed by the name of the slot, zero or more fields, and a closing parenthesis.
+<p>
+
+
+Deftemplate facts are easily distinguished from ordered facts by their first field. If the symbol serving as the first field corresponds to the name of a deftemplate, then the fact is a deftemplate fact. Like ordered facts, deftemplate facts are enclosed by an opening parenthesis on the left and a closing parenthesis on the right.
+<p>
+In addition to being asserted and retracted, deftemplate facts can also be modified and duplicated (using the <b>modify</b> and <b>duplicate</b> commands). Modifying a fact changes a set of specified slots within that fact. Duplicating a fact creates a new fact identical to the original fact and then changes a set of specified slots within the new fact. The benefit of using the modify and duplicate commands is that slots which do not change, can be left out in the statement.
+<p>
+Examples are provided in the built-in rule bases via the library-option and in the CLIPS User's Guide and Basic Programming Guide.
+
+
+<p>
+
+<b>Template based Facts for GRASS Layers</b>
+<p>
+Whenever a GRASS layer is imported by g.infer, a template is created according to its data structure and facts are asserted for the layers content.
+While the template for vector layers will differ depending on the attribute layers,  raster data templates adhere to the following structure:
+<p>
+Raster: <pre>(geo_test "a comment" (x 599000.0) (y 4921800.0) (value 5) (attribute "something"))</pre>
+
+Vector: <pre>SOIL EXAMPLE (field as point layer)</pre>
+
+Rast3d: <pre>(random_slice_00009 (x 599000.0) (y 4921800.0) (z 9.0) (value 1.0))</pre>
+<p>
+<pre>"_slice_000009" has been added by g.infer for internal reference.</pre>
+
+
+
+<h4>Rules</h4>
+
+<p>
+The primary method of representing and modifing knowledge in g.infer are rules. Any g.infer rulebase comprises of a set of rules which collectively
+ solve a classification task, establish a workflow or do similar. Rules are used to represent heuristics, or "rules of thumb",
+which specify a set of actions to be performed for a given situation.
+Rules can cause actions such as the creation, modification or deletion of facts or the call-up of GRASS modules and scripts.
+A rule is composed of an <b>antecedent</b> and a <b>consequent</b>.
+The antecedent of a rule is also referred to as the <b>if portion</b> or the <b>left hand side (LHS)</b> of the rule.
+The consequent of a rule is also referred to as the <b>then portion</b> or the <b>right hand side (RHS)</b> of the rule.
+<p>
+
+The <b>antecedent of a rule</b> (LHS) is a set of conditions (or conditional elements) which must be satisfied for the rule to be applicable.
+The conditions of a rule are satisfied based on the existence or non existence of specified facts in the fact list or specified instances of user defined classes in the instance list.
+One type of condition which can be specified is a<b> pattern</b>.
+Patterns consist of a set of restrictions which are used to determine which facts or objects satisfy the condition specified by the pattern.
+<p>
+The process of matching facts and objects to patterns is called <b>pattern matching</b>. A mechanism, called the <b>inference engine</b>,
+matches patterns against the current state of the fact list and instance list and determines which rules are applicable during the inference run.
+<p>
+
+The <b>consequent of a rule</b> (RHS) is the set of actions to be executed when the rule is applicable. This is colloquially refefred to as "the rule fires".
+The actions of applicable rules are executed when the inference engine is instructed to begin execution of applicable rules. If more than one rule is applicable,
+the inference engine uses a <b>conflict resolution strategy</b> to determine which rule should fire first.
+The actions of the selected rule are executed (which can change the overall list of applicable rules). Afterwards the inference engine selects another rule and executes its actions. This process continues until no applicable rules remain.
+<p>
+
+In many ways, rules can be thought of as IF - THEN statements found in procedural programming languages. However, the conditions of an IF - THEN statement
+in a procedural language are only evaluated when the program flow of control is directly at the IF - THEN statement. In contrast, rules act like WHENEVER - THEN statements.
+The inference engine always keeps track of rules which have their conditions satisfied and thus rules can immediately be executed when they are applicable.
+In this sense, rules are similar to exception handlers found in other programming languages.
+<p>
+
+
+
+<h4>Comments</h4>
+Rulebase content and other CLIPS code can be commented by starting lines with a semicolon.
+<p>
+
+
+
+<h4>Variables</h4>
+Variables in CLIPS are weakly typed. They are not restricted to a predefined data type. So when creating a variable, it is not required to provide typing information.
+
+The <b>defglobal</b> construct allows variables to be defined which are global in scope throughout the CLIPS environment.
+Such a global variable can be accessed anywhere in the CLIPS environment and retains its value independent of other constructs. In contrast, some constructs (such as defrule and deffunction) allow local variables to be defined within the definition of the construct. These local variables can be referred to within the construct, but have no meaning outside the construct.
+
+
+
+<h4>Functions</h4>
+
+A function in CLIPS is a piece of executable code identified by a specific name which returns a useful value or performs a side effect (such as printing a message).
+<p>
+
+The <b>defun</b> command  is used to define new functions. The body of a deffunction is a series of expressions similar to the RHS of a rule that are executed in order by the CLIPS inference engine when the deffunction is called. The return value of a deffunction is the value of the last expression evaluated within the deffunction. Calling a deffunction is identical to calling any other function in CLIPS.
+<p>
+Function Definition Example: <pre>(defun fahrenheit_celsius (celsius_value) (+ (* celsius_value 1.8) 32))</pre>
+<p>Examples are provided in the built-in rule bases (library option) and in the CLIPS User's Guide and Basic Programming Guide.
+
+<h4>Conditionals</h4>
+Examples for conditions, comparing facts and variables with each other, are provided in the built-in rule bases (library option) and in the CLIPS User's Guide and Basic Programming Guide.
+
+
+<h3>Rulebase Development, Operation and Debugging:</h3>
+
+g.infer is a tool to set up and operate rule-based workflows for information classification and data processing.
+The workflow will be loaded via a 'rulebase'-file or a built in rulebase, consisting of a set of rules, called a knowledge base. <p>
+Rule activiation is controlled by the g.infer rule engine, based on spatial data from the GIS layers.
+
+When a rule is activated for the first time, it is placed on the <b>agenda</b>, based (in order) on the following factors:
+<p>
+a)   Newly activated rules are placed above all rules of lower salience and below all rules of higher salience.
+<p>
+b)   Among rules of equal salience, the current conflict resolution strategy is used to determine the placement among the other rules of equal salience.
+<p>
+c)   If a rule is activated (along with several other rules) by the same assertion or retraction of a fact, and steps a and b are unable to specify an ordering, then the rule is arbitrarily (not randomly) ordered in relation to the other rules with which it was activated. In this respect,  the order in which rules are defined has an arbitrary effect on conflict resolution (which is also dependent upon the current underlying implementation of rules). This arbitrary ordering for the proper execution of rules should not be depended on for knowledge modelling.
+<p>
+
+Once a knowledge base (in the form of rules) has been loaded into g.infer and the fact and instance lists are available, the inference engine is ready to execute rules:
+<p>
+<ul>
+
+<li><b>a)</b>The right hand side (RHS) actions of the selected rule are executed. The use of the return function on the RHS of a rule may remove the current focus from the focus stack. The number of rules fired is incremented for use with the rule firing limit.
+
+<li><b>b)</b>  As a result of step b, rules may be activated or deactivated. Activated rules, whose conditions are currently satisfied, are placed on the agenda of the module in which they are defined. The placement on the agenda is determined by the salience of the rule and the current conflict resolution strategy. Deactivated rules are removed from the agenda.
+
+<li><b>c)</b> If dynamic salience is being used, the salience values for all rules on the agenda are reevaluated. Repeat the cycle beginning with step a.
+
+<li><b>d)</b>If a previously defined rule firing limit has been reached or there is no current focus, then execution is halted. The top rule on the agenda of the module which is the current focus is selected for execution. If there are no rules on that agenda, then the current focus is removed from the focus stack and the current focus becomes the next module on the focus stack. If the focus stack is empty, then execution is halted, otherwise step a is executed again.
+
+</ul>
+
+<p>
+Whenever a rule modifies a specific fact, the particular fact is retracted, that is, removed from the fact stack and a new (altered) fact is instantiated and added on the fact stack. <p>
+
+A rule base can be designed to act similar to the r.mapcalc module. This requires a close coupled multistage design of the rule base.
+<p>
+It is easily possible to construct a rule set which acts like an infinity-loop, which never terminates. This is in the most part undesired, but may be an asset for monitoring activities.
+
+<p>
+<pre>Examples are provided in the built-in rule bases (library option) and in the CLIPS User's Guide and Basic Programming Guide.</pre>
+
+
+<p>
+
+
+<h4>Conflict Resolution</h4>
+
+When more than one rule are eglible to fire, a priorization among the candidate rules is needed. Rules can be explicitly assigned a rank/priority called <b>salience</b>.
+<p>
+The <b>conflict resolution strategy</b> is an implicit mechanism for specifying the order in which rules of equal salience should be executed.
+<p>
+g.infer provides seven conflict resolution strategies. The default strategy is depth. The current strategy can be set by using the set strategy command (which will reorder the agenda based upon the new strategy):
+
+<p>
+
+<ul>
+<li><b>Breadth Strategy (breadth)</b>: Newly activated rules are placed below all rules of the same salience. 
+<li><b>Complexity Strategy (complexity)</b>: Among rules of the same salience, newly activated rules are placed above all activations of rules with equal or lower specificity.
+<li><b>Depth (depth: default)</b>:Newly activated rules are placed above all rules of the same salience. 
+<li><b>LEX Strategy (lex)</b>: Among rules of the same salience, newly activated rules are placed using the OPS5 strategy of the same name. First the recency of the pattern entities that activated the rule is used to determine where to place the activation. Every fact and instance is marked internally with a "time tag" to indicate its relative recency with respect to every other fact and instance in the system. The pattern entities associated with each rule activation are sorted in descending order for determining placement. An activation with a more recent pattern entities is placed before activations with less recent pattern entities. 
+
+<li><b>MEA Strategy (mea)</b>: Among rules of the same salience, newly activated rules are placed using the OPS5 strategy of the same name. First the time tag of the pattern entity associated with the first pattern is used to determine where to place the activation. An activation thats first pattern's time tag is greater than another activations first pattern's time tag is placed before the other activation on the agenda. If both activations have the same time tag associated with the first pattern, then the LEX strategy is used to determine placement of the activation. As with the CLIPS LEX strategy, negated patterns have pseudo time tags.
+<li><b>Simplicity Strategy (simplicity)</b>: Among rules of the same salience, newly activated rules are placed above all activations of rules with equal or higher specificity.
+<li><b>Random Strategy (random)</b>: Each activation is assigned a random number which is used to determine its placement among activations of equal salience. 
+</ul>
+<p>
+
+<h5>Salience</h5>
+
+The preferred mechanisms in g.infer for ordering the execution of rules are explicitly assigned salience values and knowledge base grouping using modules. Salience allows one to explicitly specify that one rule should be executed before another rule.
+<p>
+Options to apply salience values:
+<ul>
+<li><b>when-defined (default)</b>: salience evaluation at the time of rule definition
+<li><b>when-activated</b>: salience evaluation at the time of rule definition and upon being activated
+<li><b>every-cycle</b>: salience values will be calculated dynamically at run-time between rule firings
+</ul>
+
+
+<h5>Defmodules</h5>
+ Modules allow one to explicitly specify that all of the rules in a particular group (module) should be executed before all of the rules in a different group.
+<p>
+Defmodules allow a knowledge base to be partitioned. Every construct defined must be placed in a module. The programmer can explicitly control which constructs in a module are visible to other modules and which constructs from other modules are visible to a module. The visibility of facts and instances between modules can be controlled in a similar manner. Modules can also be used to control the flow of execution of rules.
+
+<pre>Examples are provided in the CLIPS User's Guide and Basic Programming Guide.</pre>
+
+
+
+<h4>Agenda</h4>
+
+The <b>agenda</b> is the list of all rules which have their conditions satisfied (and have not yet been executed). If the knowledge base is partitioned into multiple modules, each module has its own agenda. The agenda acts similar to a stack (the top rule on the agenda is the first one to be executed).
+
+
+
+
+
+<b>Focus</b>
+<p>
+The current focus determines which agenda the run command uses during execution. The reset and clear commands automatically set the current focus to the MAIN module.
+
+
+<p>
+
+<h4>Logging and Debugging</h4>
+
+<p>
+Several features of g.infer support the development and debugging of rule-bases:
+<p>
+<h4>Debugging: g.infer Flags for Logging, Interaction and Abort:</h4>
+<ul>
+<li><b>x-Flag</b>: Stop-option: The stop-option terminates g.infer following an optional invocation of a interactive CLIPS shell and before the automated inference run.
+<li><b>i-Flag</b>: Interactive CLIPS shell: The launching of an CLIPS shell before the automated inference run allows to query interactively all aspects of the current CLIPS session. <b>Ctrl-D</b> exits from the interactive Shell.
+<li><b>e-Flag</b>: Traceback-Mode: CLIPS error messages are forwarded to g.infer.
+<li><b>d-Flag</b>: Dribble-Mode: All CLIPS entities which are listed via the FOO-option are written down to file for follow-up analysis.
+<li><b>save-instances</b>: Allows to save COOL constructs, facts, instances to an ASCII file
+<li><b>bsave-instances</b>: Allows to save COOL constructs, facts, instances to a binary file.
+
+<li><b>watch-Option</b>: Prints watch messages for CLIPS constructs. These are stored to file if the dribble-flag has been set.
+
+</ul>
+
+<h4>Watch-Option: Logging of Knowledge Base Performance</h4>
+
+See the section "Notes on CLIPS" for complete definition of terminology.
+
+<ul>
+<li><b>activations</b>: All rule activations and deactivations will be displayed.
+<li><b>compilations</b>: If compilations are watched, the progress of construct definitions will be displayed.
+<li><b>deffunctions</b>: The start and finish of deffunctions will be displayed.
+
+<li><b>facts</b>: All fact assertions and retractions will be displayed.
+<li><b>focus</b>: Changes to the current focus will be displayed.
+<li><b>genericfunctions</b>: The start and finish of generic functions will be displayed.
+<li><b>globals</b>: Variable assignments to globals variables will be displayed.
+<li><b>instances</b>: Creation and deletion of instances will be displayed.
+<li><b>methods</b>: The start and finish of individual methods within a generic function will be displayed.
+<li><b>messagehandlers</b>: FOO
+<li><b>messages</b>: The start and finish of messages will be displayed.
+<li><b>rules</b>: All rule firings will be dis­played.
+<li><b>slots</b>: Changes to any instance slot values will be displayed.
+<li><b>statistics</b>: Timing information along with other information (average number of facts, average number of activations, etc.) will be displayed after a run. Note that the number of rules fired and timing information is not printed unless this item is being watch.
+<li><b>all</b>: If all is watched, then all other watch items will be watched. By default, only compilations are watched.
+</ul>
+
+<h4>Config-Option</h4>
+<DT><b>config</b></DT>
+<DD>Configuration options for CLIPS engine: auto-float-dividend,dynamic-constraint-checking,fact-duplication,incremental-reset,reset-globals,sequence-operator-recognition,static-constraint-checking.
+
+<ul>
+<li><b>auto-float-dividend</b>: the dividend of the division function is automatically converted to a floating point number
+<li><b>dynamic-constraint-checking</b>: Slot values are checked for constraint violations (FALSE by default).
+<li><b>fact-duplication</b>: A duplicate fact is asserted with a new fact?index (FALSE  by default).
+<li><b>incremental-reset</b>: Newly defined rules are updated based upon the current state of the fact-list (TRUE by default).
+<li><b>reset-globals</b>: Global variables are reset to their original values when the reset command is performed(TRUE by default).
+<li><b>sequence-operator-recognition</b>: Multifield variables are expanded and passed as separate arguments in the function call (FALSE by default).
+<li><b>static-constraint-checking</b>: Constraint violations are checked when function calls and constructs are parsed (TRUE by default).
+</ul>
+ </DD>
+
+<h4>Classdefault-Option</h4>
+<DT>classdefault<b> </b></DT>
+<DD>Class default of CLIPS engine: convenience(default),conservation
+
+<ul>
+<li><b>convenience</b>: (default) In convenience mode, for the purposes of role inheritance, system defined class behave as concrete classes; for the purpose of pattern-match inheritance, system defined classes behave as reactive classes unless the inheriting class is abstract; and the default setting for the create-accessor facet of the class slots is read-write.
+<li><b>conservation</b>: The role and reactivity of system-defined classes is unchanged for the purposes of role and pattern-match inheritance and the default setting for the create-accessor facet of the class slots is ?NONE.
+
+</ul></DD>
+</DL>
+
+<h4>Rulebase Libraries</h4>
+g.infer provides several pre-configured rulebases. The rulebases from the library can be used alone or in combination by user-defined rulebases. They provide a basic interactive user interface to launch specific demo applications and can also be started from the CLIPS prompt (using the <b>(run)</b> command). All demo rulebases contain extensive comments to document their functionaility for the interested user. 
+
+<ul>
+<li><b>reference</b>: Multiple examples CLIPS-language related programming including facts, rules, templates, etc..
+<li><b>spearfish</b>: Examples on the use of GRASS modules in rule based programming. This library requries the Spearfish ("spearfish60") location.
+
+</ul>
+
+
+<h2>Notes on g.infer pyCLIPS extensions</h2>
+
+
+
+g.infer extends the pyCLIPS- amd CLIPS environments with several commands to communicate and interact the GRASS GIS:
+
+<ul>
+<li><b>ginfer_printout</b>: Extends the CLIPS printout command for use in g.infer:  (defrule duck_print1 (animal-is duck) => (ginfer_printout t "Demo: ginfer_printout T CRLF" crlf) (ginfer_printout stdout "Demo: ginfer_printout STDOUT CRLF" crlf))
+<li><b>ginfer_readline</b>: Extends the CLIPS readline command for g.infer: (defrule duck_ask1 (animal-is duck) => (ginfer_printout t "Demo: ginfer_read: Feedback, please:" crlf) (assert (ducky1 (ginfer_read t)))(ginfer_printout t " " crlf))
+<li><b>grass_message</b>:  Uses the g.message module to print messages:  (defrule verbose_python_call0 (verbose on) => (assert (examine sections))(python-call grass_message "GRASS_MESSAGEd: works!"))
+<li><b>grass_run_command</b>:  Invokes a GRASS module from within the CLIPS shell: (defrule grassrun_glist (verbose on) => (python-call grass_run_command "g.list" "f" "type=rast,vect"))
+</ul>
+<p>
+Examples of the invocation of GRAS modules as part of the RHS ofrules are provided in the built in demo rule bases.
+<p>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+<h3>CLIPS Object Oriented Language</h3>
+
+The CLIPS Object Oriented Language (<b>COOL</b>) includes elements of data abstraction and knowledge representation. It supports abstraction, encapsulation, inheritance, polymorphism and dynamic binding. An overview of COOL as a whole, incorporating the elements of both concepts is given in [BPG].
+
+The primary difference between objects and templates (or non ordered) facts is the notion of inheritance. Inheritance allows the properties and behavior of a class to be described in terms of other classes. COOL supports multiple inheritance: a class may directly inherit slots and message?handlers from more than one class. Since inheritance is only useful for slots and message?handlers, it is often not meaningful to inherit from one of the primitive type classes, such as MULTIFIELD or NUMBER. This is because these classes cannot have slots and usually do not have message - handlers.
+
+
+<h2>SEE ALSO</h2>
+
+<em>
+<a href="r.fuzzy.html">r.fuzzy</a>,
+<a href="r.mapcalc.html">r.mapcalc: Raster algebra</a>,
+<a href="http://skagit.meas.ncsu.edu/~helena/gmslab/grassman5/html/r.infer.html">r.infer</a>,
+<a href="v.in.ascii.html">v.in.ascii: Definition of vector columns for output vectors</a>
+
+</em>
+
+<h2> Examples </h2>
+
+Examples are provided in the built in rule bases (library option).
+
+
+
+<h2>REFERENCES</h2>
+
+Browne P. (2009) JBOSS Drools Business Rules. Packt Publishing. ISBN 1-847-19606-3
+<p>
+
+Forgy C., (1982) Rete: A Fast Algorithm for the Many Pattern/Many Object Pattern Match Problem", Artificial Intelligence, 19, pp 17–37
+<p>
+
+Friedman-Hill E. (2003). Jess in Action. Manning Publications. ISBN 1-930-11089-8<p>
+
+Garosi F. (2008). PyCLIPS Manual Release 1.0. URL http://sourceforge.net/projects/pyclips/files/pyclips/pyclips-1.0/pyclips-1.0.7.348.pdf/download
+<p>
+
+Giarratano J., Gary R. (2004). Expert Systems: Principles and Programming. Course Technology. ISBN 0-534-38447-1<p>
+
+Giarratano, J.C. (2007). CLIPS User's Guide. URL http://clipsrules.sourceforge.net/documentation/v630/ug.pdf<p>
+
+Giarratano, J.C. (2007). CLIPS Reference Manual: Basic Programming Guide. URL http://clipsrules.sourceforge.net/documentation/v630/bpg.pdf<p>
+
+Giarratano, J.C. (2008). CLIPS Reference Manual: Advanced Programming Guide. URL http://clipsrules.sourceforge.net/documentation/v630/apg.pdf<p>
+
+Graham P. (1995). ANSI Common Lisp. Prentice Hall, ISBN 0-133-79875-6 <p>
+
+Löwe P. (2004). Technical Note - A Spatial Decision Support System for Radar-Metereology in South Africa. Transactions in GIS. 8(2):235-244. Blackwell Publishing Ltd. Oxford.<p>
+
+Löwe P. (2004). Methoden der Künstlichen Intelligenz in Radarmeteorologie und Bodenerosionsforschung (Dissertation). URL http://opus.bibliothek.uni-wuerzburg.de/volltexte/2004/759/ <p>
+
+Jackson P. (1998). Introduction to Expert Systems. Addison Wesley. ISBN 0-201-87686-8 <p>
+
+Puppe F. (1993) Systematic Introduction to Expert Systems. Springer. ISBN 3-540-56255-9<p>
+
+Riley G., (2008). The History of CLIPS. URL http://clipsrules.sourceforge.net/WhatIsCLIPS.html#History<p>
+
+Rudolph G. (2008). Some Guidelines For Deciding Whether To Use a Rule Engine. URL http://www.jessrules.com/jess/guidelines.shtml<p>
+
+
+
+
+<h2>AUTHOR</h2>
+Peter Löwe
+
+<p><i>Last changed: $Date: 2013-02-19 22:56:45 +0100 (Tues, 19 Feb 2013) $</i>
+<HR>


Property changes on: grass-addons/grass6/general/g.infer/description.html
___________________________________________________________________
Added: svn:executable
   + *

Added: grass-addons/grass6/general/g.infer/g.infer
===================================================================
--- grass-addons/grass6/general/g.infer/g.infer	                        (rev 0)
+++ grass-addons/grass6/general/g.infer/g.infer	2013-07-17 09:20:50 UTC (rev 57185)
@@ -0,0 +1,2889 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+############################################################################
+#
+# MODULE:      g.infer.clips  
+# AUTHOR(S):   Peter Loewe loewe at gisix.com
+#              
+# PURPOSE:     GRASS interface to the CLIPS inference engine
+# COPYRIGHT:   (C) 2011,2012,2013 by Peter Loewe
+#
+#              This program is free software under the GNU General Public
+#              License (>=v2). Read the file COPYING that comes with GRASS
+#              for details.
+#############################################################################
+#############################################################################
+#BUGS
+# grass_run / grass_read has problems when executing off-the-shelf shell commands like "sleep 2s"
+#############################################################################
+#TESTED:
+#
+# in/out: RASTER without Labels: WORKS 2012-01-18
+# in/out: RASTER with Labels: WORKS 2012-01-18
+# in/out: VOLUMES without labels: WORKS 2012-01-23
+# in/out: Vector points 2D: WORK 2012-01-23
+# out:    Create new vector point layer 2012-05-08 - broken - reconifmred: 2013-01-15
+# in/out: Vector points 3D: 2012-06-07
+# in/out: facts:
+# in/out: COOL-objects:
+#
+# GRASS modules on RHS:
+# GENERAL
+# g.list: (python-call grass_run_command "g.list" "f" "type=rast,vect")
+# g.version: (python-call grass_run_command "g.version" "c")
+
+
+
+#####################################################
+#####################################################
+#####################################################
+#####################################################
+## GRASS g.infer module description
+#####################################################
+
+#%module
+#% description: GRASS GIS interface to the CLIPS inference engine
+#% keywords: inference, reseasoning, knowledge-based
+#%end
+
+#####################################################
+#####################################################
+#####################################################
+#####################################################
+## GRASS GUI: Flags
+#####################################################
+
+#%flag
+#% key: d
+#% description: Activate CLIPS dribble option.
+#% guisection: CLIPS
+#%end
+
+#%flag
+#% key: e
+#% description: Traceback of CLIPS error messages.
+#% guisection: CLIPS
+#%end
+
+#%flag
+#% key: i
+#% description: Interactive CLIPS shell
+#% guisection: CLIPS
+#%end
+
+#%flag
+#% key: l
+#% description: Raster input: Ignore raster labels (default: labels are imported).
+#% guisection: Input
+#%end
+
+#DEPRECATED: In most cases this will halt the module as lots and lots of GIS layer derived facts would have to be printed.
+## #%flag
+## #% key: p
+## #% description: Print applicable facts (pre-loaded) for the inference run (default: off).
+## #% guisection: CLIPS
+## #%end
+
+# #%flag
+# #% key: k
+# #% description: Provide a built-in knowledge base of application examples.
+# #% guisection: CLIPS
+# #%end
+
+#%flag
+#% key: x
+#% description: Stop execution just prior to inference run.
+#% guisection: CLIPS
+#%end
+
+
+#####################################################
+#####################################################
+#####################################################
+#####################################################
+## GRASS GUI: Options
+#####################################################
+
+#%option
+#% key: rulebase
+#% type: string
+#% key_desc: name
+#% description: Rule base file (ASCII).
+#% gisprompt: old_file,file,input
+#% required : no
+#% guisection: Input
+#%end
+
+#%option
+#% key: load_instances
+#% type: string
+#% key_desc: load_instances
+#% description: Load instances from ASCII file
+#% gisprompt: old_file,file,input
+#% required : no
+#% guisection: Input
+#%end
+
+#%option
+#% key: bload_instances
+#% type: string
+#% key_desc: bload_instances
+#% description: Load instances from binary file
+#% gisprompt: old_file,file,input
+#% required : no
+#% guisection: Input
+#%end
+
+#%option
+#% key: rast
+#% type: string
+#% gisprompt: old,cell,raster
+#% description: Raster input map(s)
+#% multiple : yes
+#% key_desc : name
+#% required : no
+#% guisection: Input
+#%end
+
+#%option
+#% key: rast3d
+#% type: string
+#% gisprompt: old,raster3,raster3
+#% description: Raster3d input map(s)
+#% multiple : yes
+#% key_desc : name
+#% required : no
+#% guisection: Input
+#%end
+
+#%option
+#% key: vector
+#% type: string
+#% gisprompt: old,vector,vector
+#% description: Vector input map(s)
+#% multiple : yes
+#% key_desc : name
+#% required : no
+#% guisection: Input
+#%end
+
+#%option
+#% key: facts
+#% type: string
+#% gisprompt: old_file,file,file
+#% description: CLIPS facts input
+#% multiple : no
+#% key_desc : facts
+#% required : no
+#% guisection: Input
+#%end
+
+#%option
+#% key: library
+#% type: string
+#% description: Built-in CLIPS rulebases which are included in g.infer. The spearfish rulebase requires the Spearfish location.  
+#% options: reference,spearfish
+#% multiple : yes
+#% key_desc : name
+#% required : no
+#% guisection: Input
+#%end
+
+#############################################
+##General g.infer output-related options
+
+#%option
+#% key: export
+#% type: string
+#% description: Export of maps (a subset of the maps selected as input layers)
+#% key_desc : name
+#% required : no
+#% multiple : yes
+#% guisection: Output
+#%end
+
+#%option
+#% key: output 
+#% type: string
+#% description: new vector output map
+#% key_desc : name
+#% required : no
+#% multiple : yes
+#% guisection: Output
+#%end
+
+#%option
+#% key: save_instances
+#% type: string
+#% description: ASCII output of COOL instances 
+#% key_desc : instances_ascii_output_name
+#% required : no
+#% guisection: Output
+#%end
+
+#%option
+#% key: bsave_instances
+#% type: string
+#% description: Binary output of COOL instances 
+#% key_desc : instances_binary_output_name
+#% required : no
+#% guisection: Output
+#%end
+
+#%option
+#% key: columns
+#% type: string
+#% description: Attribute column structure for output vector  
+#% key_desc : name
+#% required : no
+#% guisection: Output
+#%end
+
+#%option
+#% key: save_rulebase
+#% type: string
+#% description: CLIPS entities to be saved to ASCII file  
+#% options: constructs,facts,instances
+#% multiple : yes
+#% key_desc : name
+#% required : no
+#% guisection: Output
+#%end
+
+#%option
+#% key: bsave_rulebase
+#% type: string
+#% description: CLIPS entities to be saved to binary file 
+#% options: constructs,facts,instances
+#% multiple : yes
+#% key_desc : name
+#% required : no
+#% guisection: Output
+#%end
+
+
+################################
+## CLIPS-related OPTIONS
+
+#%option
+#% key: strategy
+#% type: string
+#% description: Inference Strategy 
+#% key_desc : Select the inference strategy (default: depth)
+#% options: breadth,complexity,depth,lex,mea,simplicity,random
+#% required : no
+#% guisection: CLIPS
+#%end
+
+#%option
+#% key: limit
+#% type: string
+#% description: Maximum number of inferences 
+#% key_desc : Upper limit for inference runs
+#% required : no
+#% guisection: CLIPS
+#%end
+
+#%option
+#% key: salience
+#% type: string
+#% description: Salience behaviour 
+#% key_desc : Select the salience behaviour strategy (default: when-defined)
+#% options: when-defined,when-activated,every-cycle
+#% required : no
+#% guisection: CLIPS
+#%end
+
+#%option
+#% key: module
+#% type: string
+#% description: Rule base module(s) to be on te focus stack for inference launch (default: MAIN)
+#% key_desc : Module(s) (group(s= of rules) to be specificaly put the focus stack for the inference run.
+#% required : no
+#% multiple : yes
+#% guisection: CLIPS
+#%end
+
+#%option
+#% key: watch
+#% type: string
+#% options: activations,compilations,facts,functions,genericfunctions,globals,methods,messagehandlers,messages,rules,slots,statistics,all
+#% multiple : yes
+#% description: Watch options for CLIPS engine
+#% key_desc : Watch options for CLIPS engine.
+#% required : no
+#% guisection: CLIPS
+#%end
+
+#%option
+#% key: print
+#% type: string
+#% options: agenda,breakpoints,classes,deffacts,definstances,facts,focusstack,functions,generics,globals,instances,messagehandlers,modules,rules,templates
+#% multiple : yes
+#% description: Prints CLIPS items prior to inference run.
+#% key_desc : Prints CLIPS items prior to inference run.
+#% required : no
+#% guisection: CLIPS
+#%end
+
+#%option
+#% key: config
+#% type: string
+#% options: auto-float-dividend,dynamic-constraint-checking,fact-duplication,incremental-reset,reset-globals,sequence-operator-recognition,static-constraint-checking
+#% multiple : yes
+#% description: Configuration options for CLIPS engine
+#% key_desc : Configuration options for CLIPS engine.
+#% required : no
+#% guisection: CLIPS
+#%end
+
+#%option
+#% key: classdefault
+#% type: string
+#% options: convenience,conservation
+#% multiple : no
+#% description: Class default of CLIPS engine
+#% key_desc : Class default of CLIPS engine.
+#% required : no
+#% guisection: CLIPS
+#%end
+
+#######################################################################
+#######################################################################
+#######################################################################
+## Import Python Modules
+#######################################################################
+
+def module_exists(the_module,as_name = False):
+    """! TBD"""
+    the_module_name = str(the_module)	 
+    try:
+        if as_name:
+	    import the_module_name as as_name	
+	else:
+	    __import__(the_module_name)
+		       
+    except ImportError:
+        error_message=str("[module_exists] Import Error:" + str(the_module))
+	grass.fatal(_(error_message))
+    return True
+
+
+import grass.script as grass
+from grass.lib import vector as grassvect
+
+from grass.lib.gis import * 
+from ctypes import *
+import grass.script.array as garray
+#module_exists("grass.script.array","garray")
+import clips
+#module_exists('clips')
+#ISSUE: see below. same case.
+import sys
+import os
+import atexit
+import random
+import time
+import string as _string
+import types
+#module_exists(str("types"))
+#^^^^ There is some issue: Global name types is not defined.
+module_exists('numpy')
+module_exists(str("os.path"))
+
+#######################################################################
+#######################################################################
+#######################################################################
+## Global Variables
+#######################################################################
+
+##################################################
+#A placeholder for the NULL substitute for vector export
+# must be improved to support FLOATS for NULLS during export.
+FACT_NULL = -2147483648
+FACT_NULL_FLOAT = "nan"
+
+# Reality check: 
+#    Integer maps, NULLs -> (value -2147483648)
+#    Float maps: NULL -> (value nan)
+
+##################################################
+# Set up dictionaries to manage all relevant aspects of GRASS-(input)-layers 
+##################################################
+
+#################################################
+# Dictionary to store v.in.ascii-string for vector layers
+layers_vector_vinascii={}
+
+#################################################
+# Dictionary to store template for vector layer
+layers_template={}
+
+#################################################
+# Dictionary to store attribute column structure for vector layers
+layers_vector_columns={}
+
+#################################################
+# Dictionary to store numeric type of raster layers
+layers_raster_type={}
+
+#################################################
+# Dictionary to store 2D slice names for 3D rast3d volume layers
+layers_raster3d_slices={}
+
+##################################################
+# Access to central dictionaries
+
+def global_layers_template_put(the_layer,the_template):
+    """! Put a layer template in the layer template dictionary under its layer name"""
+    global the_layers_template
+    layers_template[the_layer]=the_template
+
+def global_layers_raster_type_put(the_layer,the_type):
+    """! Put a raster layers typ in the raster type dictionary under its layer name"""
+    global layers_raster_type
+    layers_raster_type[the_layer]=the_type
+    
+def global_layers_vector_vinascii_put(the_layer,the_string):
+    """! Put a vector layer v.in.ascii string in the layer v.in.ascii dictionary under its layer name"""
+    global layers_vector_vinascii
+    layers_vector_vinascii[the_layer]=the_string
+
+def global_layers_vector_columns_put(the_layer,the_columns):
+    """! Put a vector layers columns description in the vector column dictionary under its layer name"""
+    global layers_vector_columns
+    layers_vector_columns[the_layer]=the_columns
+
+def global_layers_rast3d_slices_put(the_layer,the_slices):
+    """! Put a slices info (list?) of a volume layer in the volume layer slices dictionary under its layer name"""
+    global layers_raster3d_slices
+    layers_raster3d_slices[the_layer] = the_slices
+    
+def global_layers_template_get(the_layer):
+    """! Retrieve a layer template from the layer template dictionary by its layer name"""
+    global the_layers_template
+    return layers_template[the_layer]
+
+def global_layers_raster_type_get(the_layer):
+    """! Retrieve a raster layer type from the raster type dictionary by its layer name"""
+    global layers_raster_type
+    return layers_raster_type[the_layer]
+    
+def global_layers_vector_vinascii_get(the_layer):
+    """! Retrieve a vector layer v.in.ascii string from the vector v.in.ascii dictionary by the layer name"""
+    global layers_vector_vinascii
+    return layers_vector_vinascii[the_layer]
+
+def global_layers_vector_columns_get(the_layer):
+    """! Retrieve a vector layer column string from the vector column dictionary by the layer name"""
+    global layers_vector_columns
+    return layers_vector_columns[the_layer]
+    
+    
+def global_layers_rast3d_slices_get(the_layer):
+    """! Retrieve the slices info (list?) of a volume layer from the volume layer slices dictionary by its layer name"""
+    global layers_raster3d_slices
+    return layers_raster3d_slices[the_layer]
+
+
+
+#######################################################################
+#######################################################################
+#######################################################################
+## Program cleanup epilogue
+#######################################################################
+
+
+def cleanup():
+    """!Function: Final cleanup routine of g.infer module"""
+    # tbd: Ensure that all temp files are removed.
+    grass.debug(_("[cleanup] g.infer: completed"))
+
+
+
+    
+#######################################################################
+#######################################################################
+#######################################################################
+## TOOLS
+#######################################################################
+
+
+######################################################################
+# General Sanity Checks for input data: 
+# Ensure that all input parameters are valid and don't contradict each other
+
+def sanity_checks_input_layers(facts_rasters,facts_raster3ds,facts_vectors,facts_file,rulebase_file):
+    """!Ensure that sufficient input layers are provided to process by g.infer"""
+    fact_sources = 4
+    # fact sources can be either raster,volumes, vector layers or fact files.
+    if not facts_rasters: fact_sources = fact_sources -1
+    if not facts_raster3ds: fact_sources = fact_sources -1 
+    if not facts_vectors: fact_sources = fact_sources -1
+    if not facts_file: fact_sources = fact_sources -1
+    if (fact_sources == 0):
+        grass.fatal(_("None of the parameters <raster>, <raster3d> or <vector> is set."))
+    return "ok"
+
+def detect_input_layer(string_list,set_a,set_b):
+    """! Naming conflict detection: Each layer name (coming from vector/raster/voxel input layers) must be unique."""
+    this_count = 0
+    this_list = [] 
+    for this_item in str(string_list).split(','): 
+        this_count = this_count + 1
+        this_list.append(this_item)
+        if (this_item in set_a) or (this_item in set_b):
+            grass.fatal(_("Naming conflict: Layer " + this_item + " can not be used as raster, raster3d and vector input source simultanously. Renaming is recommended."))
+    this_set=set(this_list)
+    return this_count,this_set
+
+def norules_nofacts_noservice():
+    """! A failsafe to stop the g.infer module if neither rules nor facts are available"""
+    #Note:  the built-in reference knowledgebase (2013) contains both rules and facts, which overrides the requirements of this function
+    rules_sum = len(GLOBAL_CLIPS__ENVIRONMENT.RuleList())
+    facts_sum = len(GLOBAL_CLIPS__ENVIRONMENT.FactList())
+    #if not reference_knowledgebase:
+    if (facts_sum < 1):
+        grass.fatal(_("Execution terminated: No facts available "))
+        sys.exit()
+    if (rules_sum < 1):
+        grass.fatal(_("Execution terminated: No rules available "))
+        sys.exit()
+
+#####################################################
+#####################################################
+#####################################################
+#####################################################
+## PyCLips related wrappers (for use at the CLIPS prompt).
+#####################################################
+
+# Scope: The wrappers can be used in PyCLIPS functions and via the CLIPS prompt
+
+#####################################################
+# Wrapper for SendCommand [PyCLIPS-API] for usage in CLIPS shell
+def pyclips_send_command(this_command):
+    """! Wrapper for CLIPS-command execution on the (interactive) PyCLIPS shell"""
+    grass.message(_("[pyclips_send_command]: " + str(this_command)))	
+    clips.SendCommand(str(this_command)) # works.
+
+
+    #works: (python-call pyclips_send_command (assert (foo bar)))
+    #works: (python-call pyclips_send_command "(assert (bar))")
+
+    # Issue:
+    #CLIPS[19/1]> (python-call pyclips_send_command (load 'upload_test.clp'))
+    #[ARGACCES2] Function load was unable to open file 'upload_test.clp'.
+    #nil
+    #CLIPS[20/1]> (python-call pyclips_send_command (load #'/home/loewe/Dokumente/g.infer/2013/upload_test.clp'))
+    #[ARGACCES2] Function load was unable to open file #'/home/loewe/Dokumente/g.infer/2013/upload_test.clp'.
+    # returns nil but thats ok
+
+#####################################################
+# Wrapper for load/Batchstar for usage in CLIPS shell
+def pyclips_batchstar(this_file):
+    """! Wrapper for load/Batchstar [CLIPS-command] for usage in CLIPS shell"""
+    grass.message(_("[pyclips_batchstar: " + str(this_file)))	
+    ingest_rulebase_file(str(this_command)) 
+#  internal name (might change) is mapped to reference name for clips shell use.
+# Works: (python-call ingest_rulebase_file baz.clp)
+
+
+#####################################################
+#####################################################
+#####################################################
+#####################################################
+## GRASS Python-API related wrappers (for use at the CLIPS prompt).
+#####################################################
+
+#######################################################################
+## GRASS region 3D support: 
+##  (TAKEN and CHANGED from (GRASS) CORE.py)
+def region3():
+    """!Returns the output from running the GRASS command "g.region -g", as a
+    dictionary. Example:
+
+    \code
+    >>> region = grass.region()
+    >>> [region[key] for key in "nsew"]
+    [228500.0, 215000.0, 645000.0, 630000.0]
+    >>> (region['nsres'], region['ewres'])
+    (10.0, 10.0)
+    \endcode
+
+    @return dictionary of region values
+    """
+    s = grass.read_command("g.region", flags='3g')
+    reg = grass.parse_key_val(s, val_type = float)
+    for k in ['rows', 'cols']:
+	reg[k] = int(reg[k])
+    return reg
+
+#####################################################
+# Wrapper for grass.run [GRASS-Python-API] for usage in CLIPS
+def grass_run_command(command,*args):
+    """! Run a GRASS command  on Python level- and return the results"""
+    thekw = {}
+    theargs = ""
+    foo = ""
+    for arg in args:
+        if "=" in str(arg):
+            thekey,thevalue=arg.split('=')
+            thekw[thekey.strip(' ')]=thevalue.strip(' ')   
+        else:
+            theargs += arg.lstrip('-').strip(' ')
+    #argstuple = tuple(theargs)
+    #WORKS: grass.run_command("r.stats","cl",input="geology",fs="_")
+    result = grass.run_command(command,theargs, **thekw)
+
+#
+# WORKS !!! (python-call grass_run_command "g.list" "f" "type=rast,vect")
+# WORKS !!! (python-call grass_run_command "r.stats" "cl" "input=geology" "fs=_")
+
+#works: (python-call grass_run_command "g.version")
+#works: (python-call grass_run_command "g.version" "c")
+
+def grass_read_command(command,*args):
+    """! Read a GRASS command  [GRASS-Python-API] on Python level - and return the results"""
+    thekw = {}
+    theargs = "" 
+    foo = ""
+    for arg in args:
+        if "=" in str(arg):
+            thekey,thevalue=arg.split('=')
+            thekw[thekey.strip(' ')]=thevalue.strip(' ')   
+        else:
+            theargs += arg.lstrip('-').strip(' ')
+    result = grass.read_command(command,theargs, **thekw)
+    return result
+
+#####################################################
+# Wrapper for grass.start for usage in CLIPS
+
+def grass_start_command(prog, flags = "", overwrite = False, quiet = False, verbose = False, **kwargs):
+    """! Start a GRASS command [GRASS-Python-API]  on Python level- and return the results"""
+    grass.start_command(prog, flags = "", overwrite = False, quiet = False, verbose = False, **kwargs) 
+    
+ #   @param prog GRASS module
+ #   @param flags flags to be used (given as a string)
+ #   @param overwrite True to enable overwriting the output (<tt>--o</tt>)
+ #   @param quiet True to run quietly (<tt>--q</tt>)
+ #   @param verbose True to run verbosely (<tt>--v</tt>)
+ #   @param kwargs module's parameters
+
+ #Role model:
+ #clips.RegisterPythonFunction(pyread)
+ #
+ #py_printout1 = GLOBAL_CLIPS__ENVIRONMENT.BuildFunction("ginfer_printout","?logical-name $?args","""(if (member$ python-call (get-function-list)) then (funcall python-call pyprintout ?logical-name $?args) else (progn$ (?arg $?args)(printout ?logical-name ?arg)))""")
+ #
+ #bashstar_printout1="(deffunction ginfer_printout (?logical-name $?args)(if (member$ python-call (get-function-list)) then (funcall python-call pyprintout ?logical-name $?args) else (progn$ (?arg $?args)(printout ?logical-name ?arg))))"
+ #prelude_upload(bashstar_printout1)
+
+# like this:
+#py_grass_run =
+# GLOBAL_CLIPS__ENVIRONMENT.BuildFunction("ginfer_grassrun","$?args","""(if (member$ python-call (get-function-list)) then (funcall python-call pyprintoutRUN $?args) else (progn$ (?arg $?args)(printoutRUN ?arg)))""")
+# ... triffts nicht.
+
+
+
+#####################################################
+### Raster Layer Category Dictionary:
+def raster_categories(the_raster):
+    """Returns a dictionary of all categories of a GRASS raster layer """
+
+    # the VAL option must be used for FLOAT maps.
+    # evtl stattdessen r.stats -il (mit labeln und floats als int betrachten)
+    
+    #p = grass.pipe_command('r.category',map=the_raster,fs=':', quiet='TRUE')
+    p = grass.pipe_command('r.stats',flags = 'il',input=the_raster,fs=':', quiet='TRUE')
+    result = {}
+    count = 0
+    category_list=""
+    raster_category_dictionary=dict()
+    for line in p.stdout:
+      the_cat = line.split(':')
+      raster_category_dictionary.update({the_cat[0]:the_cat[1].rstrip()})
+    return raster_category_dictionary
+
+
+#####################################################
+# Wrapper for grass.raster.info [GRASS-Python-API] for usage in CLIPS
+def grass_raster_info(the_raster):
+    """! Print info abouta GRASS raster layer  on Python level"""
+    grass.raster_info(the_raster)
+
+
+#####################################################
+# Wrapper for grass.message [GRASS-Python-API] for usage in CLIPS
+def grass_message(the_message):
+    """! Wrapper for GRASS message construct (for use in PYCLIPS/Prompt)"""
+    grass.message(_(the_message))
+
+#####################################################
+# Wrapper for grass.fatal for usage in CLIPS
+def grass_fatal(the_message):
+    """! Wrapper for grass.fatal [GRASS-Python-API] for usage in CLIPS"""
+    grass.fatal(_(the_message))
+
+#####################################################
+# Wrapper for grass.message [GRASS-Python-API] for usage in CLIPS
+def grass_debug(the_message):
+    """! Wrapper for GRASS debug message"""
+    grass.debug(_(the_message))
+
+
+
+#####################################################
+#####################################################
+#####################################################
+#####################################################
+## Tools for CLIPS-facts
+#####################################################
+
+
+
+def facts_total(atemplate):
+    """! Provide the overall number of facts for a template"""
+    count = 0
+    try:
+        position = fact_first(atemplate)
+        count=count+1
+        while (fact_next_exists(atemplate, position) == 1):
+            count=count+1
+            position=fact_next(atemplate, position)
+           #print count 
+        return count
+    except TypeError:
+        count = (count - 1)
+        # count one down as the first + 1 increment for fact_first seems to be executed even if the rest croaks.
+        return count 
+    except AttributeError:
+        count = (count - 1)
+        return count
+
+def facts_any(atemplate):
+    """! Check whether any facts exist for a specific template """
+    count = 0
+    try:
+        position = fact_first(atemplate)
+        count=count+1
+        return True
+    except TypeError:
+        return False 
+
+def printable_fact(afact):
+    """! PrettyPrint the fact"""
+    return afact.CleanPPForm()
+  
+def fact_first(atemplate):
+    """! Return the first fact of the template"""
+    try:
+        a = atemplate.InitialFact()
+        return a
+    except TypeError:
+        return 0
+
+def fact_first_retract(atemplate):
+    """! Return the content of the first known fact of the template and retract it"""
+    try:
+        a = atemplate.InitialFact()
+        atemplate.InitialFact().Retract()
+        return 1
+    except TypeError:
+        return 0
+  
+def fact_next(atemplate, afact):
+    """! Return the next fact for a template which follows on the provided fact."""
+    try:
+        a = atemplate.NextFact(afact)
+        return a
+        #return atemplate.NextFact(afact)
+    except TypeError:
+        return 0
+
+def fact_next_exists(atemplate, afact):
+    """! Tests for the template whether another fact remains after the provided fact"""
+    try:
+        while atemplate.NextFact(afact):
+            return 1
+    except TypeError:
+        return 0
+
+def get_slot(thefact,theslot):
+    """! Returns the actual value of a given slot for a fact.""" 
+    try:
+        return thefact.Slots[theslot]
+    except TypeError:
+        return False 
+
+def facts_all_integer(atemplate,aslot):
+    """! Check for all facts by the template whether a given slot contains exclusively integer values."""
+    all_integer = True
+    try:
+
+         position = fact_first(atemplate)
+         slotvalue = get_slot(position,aslot)
+         if not is_null_integer(slotvalue):
+	     all_integer = False
+             # printable_fact(position)
+         while (fact_next_exists(atemplate, position) == 1):
+             position=fact_next(atemplate, position)
+             slotvalue = get_slot(position,aslot)
+             if not is_null_integer(slotvalue):
+	         all_integer = False
+             return all_integer
+
+    except TypeError:
+        return False 
+#tbd: Build similar for isfloat and isnumber ! 
+
+
+#####################################################
+#####################################################
+#####################################################
+#####################################################
+## Tools for strings (Python)
+#####################################################
+
+def cat_filter (catstring):
+    """! Replace all 'cat'-strings by 'cat_' in agiven string and return result """
+    return catstring.replace(' cat ', ' cat_ ')   
+
+def vectorimport_get_name_type_payload(i):
+    """! Split a payload string in three segments (name/type/length) and return these"""
+    i=i.replace('[','')
+    i=i.replace(']','')
+    i=i.strip()
+    attr_name,attr_type,attr_length=i.split(",")
+    attr_name=attr_name.strip("'")
+    attr_type=attr_type.rstrip("'").lstrip(" '")
+    return attr_name,attr_type,attr_length
+
+
+
+
+#####################################################
+#####################################################
+#####################################################
+#####################################################
+## Tools for numbers (Python)
+#####################################################
+
+def is_integer(number):
+    """! Check whether a number is a) a number and b) it's an Integer. Returns True or False."""
+    try:
+        thefloat = float(number)
+        theint = int(number)
+        if thefloat - theint != 0.0:
+            return False
+        else:
+            return True   
+    except ValueError:
+        return False
+
+def is_null_integer(number):
+    """! Check whether a number is a) a number and b) it's an Integer. Returns True or False. If a NULL value is given, INTEGER is considered as true."""
+    if is_null(number):
+        return True
+    else:
+        return is_integer(number)
+
+def is_float(number):
+    """! Check whether a number is a) a number and b) it's an Float. Returns True or False."""
+    try:
+        thefloat = float(number)
+        theint = int(number)
+        if thefloat - theint != 0.0:
+            return True
+        else:
+            return Flase   
+    except ValueError:
+            return False
+
+def is_number(number):
+    """! Check whether a (float) number is a) a number. Returns True or False."""
+    try:
+        thefloat = float(number)
+        return True   
+    except ValueError:
+        return False
+
+def is_null(number):
+    """! Check whether a value is a GRASS NULL valuer ("*"). Returns True or False."""
+    if number == "*":
+        return True   
+    else:
+        return False
+
+
+
+
+###########################################################################
+###########################################################################
+###########################################################################
+###########################################################################
+###########################################################################
+## IMPORT
+###########################################################################
+###########################################################################
+
+
+def import_layer_test(the_layer,the_type):
+    """! Test whether a vector|rast|rast -typed input GRASS layer exists""" 
+    layer_exists=""
+    result = grass.find_file(name = the_layer, element = the_type)
+    layer_exists=str(result['file'])
+    if (layer_exists == ""):
+          grass_fatal("Input map not found: " + str(the_layer))
+    return 0                                                
+
+def import_vector_test(the_layer):
+    """! Test whether a vector input GRASS layer exists"""
+    import_layer_test(the_layer,'vector')
+        
+def import_raster_test(the_layer):    
+    """! Test whether a raster input GRASS layer exists"""  
+    import_layer_test(the_layer,'cell')
+                                                
+# The mechanism used in import_layer|vector test does not work for raster. Here comes a workaround    
+def import_rast3d_test(the_layer):
+    """! Test whether a rast3d input GRASS layer exists"""
+    #import_layer_test(the_layer,'rast3d')
+    gisenv = grass.gisenv()
+    gisenv_mapset = gisenv['MAPSET']
+    listofmaps=grass.list_grouped('rast3d')[gisenv_mapset]
+    if (the_layer) not in listofmaps:
+          grass_fatal("Rast3d layer does not exist:" + str(the_layer))
+          sys.exit(1)
+                                        
+        
+        
+########################################################################
+####VECTOR IMPORT
+########################################################################
+                                          
+
+
+def ingest_facts_vectors(facts_vectors,inference_map):
+    """! Ingestion of all user-provided GRASS vector layers, and (optional) an output vector layer to be created in GRASS"""
+    inference_map_vinascii_string = "" 
+    #^^^^ Failsafe to ensure that no empty string will be returned.
+    vectors_list = str(facts_vectors).split(',')
+    for index in range(0,len(vectors_list)):
+        this_vector = vectors_list[index]
+        import_layer_test(this_vector,'vector')
+                    
+        if grassvector_test_valid(this_vector):          
+            if grassvector_ensure_points(this_vector):              
+                assert_vector_metadata(this_vector)                       
+                voutascii_columns,attribute_list=grassvector2factlayer(this_vector, vector_get_attribute_structure(this_vector))    
+                grassvector2factlayer_assert(this_vector,voutascii_columns,attribute_list)
+                #### This is a potential ISSUE: grassvector2factlayer_assert ingests the real point data.
+                #### What if this is an empty inference-result vector ?
+                #### Outdated logic ?
+                if vectors_list[index] == inference_map:
+                    #Remember ths visnascci_sequence for the output layer.
+                    inference_map_vinascii_string = the_vinascii_string
+        else:
+             grass.message(_("Unable to open vector map "+this_vector+": The map must contain only points-data. " ))
+    return inference_map_vinascii_string  #IS THIS EVER NEEDED ??
+
+
+
+
+def grassvector_new(the_vector, attributelist):
+    """! Creates (touch) a new empty GRASS vector (to contain inference results)"""
+    # v.in.ascii -e 
+    #grass_message(str("GRASSVECTOR_NEW: " + str(the_vector) + "  " + str(attributelist)))
+    grass.run_command("v.in.ascii","e",input='-',output=the_vector, x=1, y=2, columns=attributelist, overwrite='True', quiet='TRUE')
+    #grass_message(str("*** GRASSVECTOR: " + str(the_vector) + " HAS BEEN CREATED ***"))
+
+
+def grassvector2factlayer(the_vector,the_attributelist):
+    """! Import a GRASS vector and create a custom fact-template according to the vectors database attributes"""
+
+    #tbd: Extension for an optional attribute as an addtitional paramater needed 1)Name 2)Type 3)Value
+    gisenv = grass.gisenv()
+    gisenv_mapset = gisenv['MAPSET']
+         
+    #mymessage="grassvector2factlayer:  " + str(the_vector)+  " columns = " + str(the_attributelist)
+    #grass.message(_(mymessage))
+    voutascii_columns=""
+    vinascii_columns=""
+    columns_list=[]
+
+    if grassvector_test_3d(the_vector):
+      z_column = True   
+    else:
+      z_column = False
+
+    # construct strings to generate templates both on pyclips and clips level:
+    buildtemplate_template = "(slot x)(slot y)"
+    if z_column:
+      buildtemplate_template += "(slot z)"
+    bashstar_template = "(deftemplate " + the_vector + " (slot x)(slot y)"
+
+    if z_column:
+      bashstar_template += "(slot z)"
+
+    attribute_list = []
+    attribute_list.append("x")
+    attribute_list.append("y")
+
+    if z_column:
+      attribute_list.append("z")
+
+    attribute_list.append("numcat") 
+
+    attributes = the_attributelist
+
+    if isinstance(the_attributelist, types.ListType):
+       #iterate over all existing attributes and append them to the template-construction-strings
+       for i in attributes:
+	  i=i.replace('[','')
+	  i=i.replace(']','')
+	  i=i.strip()
+	  attr_name,attr_type,attr_length=i.split(",")
+	  attr_name=attr_name.strip("'")
+	  attr_type=attr_type.rstrip("'").lstrip(" '")
+
+	  if ((attr_name != 'x') and (attr_name != 'y')) and (attr_name != 'z'):
+	    attr_length=attr_length.rstrip("'").lstrip(" '")
+	    buildtemplate_template = buildtemplate_template + "(multislot "+ attr_name +")"
+	    bashstar_template = bashstar_template + "(multislot "+ attr_name +")"
+	    voutascii_columns = voutascii_columns + attr_name + ","
+	    attribute_list.append(attr_name)
+
+	    if attr_type == 'INTEGER':
+	      export_type = 'int'
+	    elif attr_type == 'DOUBLE PRECISION':
+	      export_type = 'double precision'
+	    elif attr_type == 'CHARACTER':
+	      export_type = 'varchar('+attr_length+')'
+	    else:
+	      grass.fatal(_("Unkown attribute type: "+attr_type))
+	  else:
+	    print ""
+            #print "[grassvector2factlayer] Filtered out: " + attr_name + " " + attr_type 
+     
+       vinascii_columns = vinascii_columns + " " + attr_name  + " " + export_type + ","
+       columns_list.append(attr_name)
+ 
+    elif isinstance(the_attributelist, types.StringTypes):
+        attributeline=str(attributes).strip("'")
+        attributelist=attributeline.split(',')
+        #^^^ husk single quotes
+
+	for i in attributelist:
+	  attr_name,ignore,attr_type = i.strip().partition(" ")
+	  attr_name.strip()
+	  attr_type.strip()
+	  export_type='double precision'
+	  #^^^--- fallback option: works for x and y
+	  if ((attr_name != 'x') and (attr_name != 'y')) and (attr_name != 'z'):
+	    buildtemplate_template = buildtemplate_template + "(multislot "+ attr_name +")"
+	    bashstar_template = bashstar_template + "(multislot "+ attr_name +")"
+	    voutascii_columns = voutascii_columns + attr_name + ","
+	    attribute_list.append(attr_name)
+	    if attr_type == 'int':
+	      export_type = 'int'
+	    elif attr_type == 'double precision':
+	      export_type = 'double precision'
+	    elif attr_type.startswith('varchar'):
+	      #tbd: filter out actual length !!!!!
+	      export_type = 'varchar(255)'
+	    else:
+	      grass.fatal(_("Unkown attribute type:"+attr_type))
+
+	  else:
+	    grass.message(_(" "))
+	  columns_list.append(attr_name)
+     
+	  vinascii_columns = vinascii_columns + " " + attr_name  + " " + export_type + ","
+
+
+    voutascii_columns = voutascii_columns.rstrip(",")
+    #strip trailing comma
+    #-> is needed to assert cector data wird 
+
+    vinascii_columns = "'"+vinascii_columns.rstrip(",")+"'"
+    #strip trailing comma and add quotation
+    
+    bashstar_template = bashstar_template + ")"
+
+    #Instantiate the new template in PyClips
+    quoted_template = buildtemplate_template
+
+    the_new_template = GLOBAL_CLIPS__ENVIRONMENT.BuildTemplate(the_vector,quoted_template,"GRASS VECTOR")
+
+    #Instantiate the new template in Clips
+    prelude_upload(bashstar_template)
+    # !!! REFACTORING: prelude_upload uses a write to tempfile approach. Better alternative: Use the here document function !
+    
+    global_layers_template_put(the_vector,the_new_template)
+    global_layers_vector_vinascii_put(the_vector,vinascii_columns)
+    global_layers_vector_columns_put(the_vector,columns_list)
+    
+    return voutascii_columns,attribute_list
+   
+
+
+def grassvector2factlayer_internal(the_vector):
+    """! Internal Version: Import a GRASS vector and create a custom fact-template according to the vectors database attributes"""
+    grassvector2factlayer(the_vector,vector_get_attribute_structure(the_vector))
+    return True
+
+
+
+def grassvector_KB_load_vector(the_vector):
+    """! Creates a template and asserts the facts for a GRASS vector - to be used with internal knowledgebases  """ 
+    if grassvector_test_valid(thie_vector):          
+        if grassvector_ensure_points(thie_vector):        
+            assert_vector_metadata(the_vector)
+            print str(vector_get_attribute_structure(the_vector))                                          
+            voutascii_columns,attribute_list = grassvector2factlayer(the_vector, vector_get_attribute_structure(the_vector))
+            grassvector2factlayer_assert(the_vector,voutascii_columns,attribute_list)
+        else:
+            grass.message(_("[grassvector_KB_load_vector]: Unable to open vector map "+this_vector+": The map must contain only points-data. " ))
+    else:
+        grass.message(_("[grassvector_KB_load_vector]: Unable to open vector map "+this_vector+": Invalid vector. " ))
+
+def grassvector_ensure_points(the_vector):
+    """! Checks a GRASS vector layer whether all geometry objects are points. Returns false otherwise """
+#REFACTORING OPPORTUNITY: pipe stuff ...  
+    #p = grass.pipe_command('v.info',flags='t',map=the_vector, quiet='TRUE')
+    #result = {}
+    #count = 0
+    #vinfo={}
+    #for line in p.stdout:
+    #    the_line = line.strip().split("=") 
+    #    vinfo[the_line[0]]=the_line[1]
+    vinfo = grass.vector_info_topo(the_vector)
+    points_count=vinfo['points']
+    primitives_count=vinfo['primitives']
+    if points_count == primitives_count:
+         return True
+    else:
+         return False
+
+def grassvector_test_3d(the_vector):
+    """! Tests a GRASS vector layer for the 3d attribute (-> z column exists) . Returns false otherwise """
+    vinfo = grass.vector_info_topo(the_vector)
+    #grass_message("GRASSVECTOR_TEST_3D: " +  str(the_vector) + "   " +  str(vinfo))
+    is_map3d = vinfo['map3d']
+
+    #[grassvector_test_3d]:{'kernels': 0, 'lines': 0, 'centroids': 0, 'boundaries': 0, 'points': 25, 'faces': 0, 'primitives': 25, 'islands': 0, 'nodes': 25, 'map3d': False, 'areas': 0}
+
+    if (str(is_map3d) == "False"):
+         return False
+    else:
+         return True
+    #Important: False can indicate a broken vector topology !
+    #Criteria: A vector lacking any nodes would be inavlid 
+
+def grassvector_test_valid(the_vector):
+    """! Tests a GRASS vector layer for the 3d attribute (-> z column exists) . Returns false otherwise """
+    
+    vinfo = grass.vector_info_topo(the_vector)
+    if 'nodes' in vinfo:
+         return True
+    else:
+         grass.message(_("grassvector_test_valid ERROR: "+ str(the_vector)))
+         return False     
+
+def grassvector2factlayer_assert(the_vector,voutascii_columns,attribute_list):
+    """! Asserts facts for a GRASS vector via v.out.ascii (after the custom template for the vector has been previously defined) """
+    #GRASS String attributes concatining whitespaces are correctly asserted. 
+    p = grass.pipe_command('v.out.ascii',columns=voutascii_columns,input=the_vector, quiet='TRUE')
+    result = {}
+    count = 0
+    for line in p.stdout:
+        count = count + 1
+        the_line = line.strip().split("|") 
+        to_assert="(" + the_vector + " "
+        for index in range(len(attribute_list)):
+          if not attribute_list[index] == "numcat":
+          # numcat is a workaround for the dual cat provision by v.out.ascii
+          # it is filtered out as it is not defined (or used) in the template defined above..
+            to_assert=to_assert+"("+attribute_list[index]+" "+the_line[index] + ")"        
+        to_assert=to_assert+" )"
+	GLOBAL_CLIPS__ENVIRONMENT.Assert(to_assert) 
+
+
+def vector_get_attribute_structure(the_vector):
+    """! Return attribute structure of a vector"""
+    dbdescribe = grass.db_describe(the_vector)
+    #ingest the attribute structure information
+    line = str(dbdescribe).strip("{}")
+    nrows,ignore,cdrline = line.partition(",")
+    cdrline,ingore,ncols = cdrline.rpartition(",")
+    ignore,ignore,attributes = cdrline.partition(":")
+    attributes = attributes.split("],")
+    return attributes
+
+
+
+########################################################################
+#### SET VECTOR METADATA FACTS
+########################################################################
+
+    #grass.vector_columns('soils')
+    
+    #grass.vector_db('soils')
+    # Prints the database connection
+    
+    #grass.vector_db_select('soils')
+    # Prints the range of existing values.
+    
+    #grass.db_describe('soils')
+    # Describes the attribute table
+    # >>  grass.db_describe('soils')
+    # >> {'nrows': 54, 'cols': [['cat', 'INTEGER', '11'], ['label', 'CHARACTER', '13']], 'ncols': 2}
+    # !!! For type CHAR the maximum string length is returned. 
+
+
+def assert_vector_metadata(thevector):
+    """!Assert the metadata for a GRASS vector layer as facts in the CLIPS environment
+    #grass.vector_info_topo('soils')
+    # Lists, numbers of  Boundaries, Points, Primitives, Islands, Lines, Centroids, Nodes
+    """
+    if grassvector_test_valid(thevector):
+    
+        topology = grass.vector_info_topo(thevector)
+        topo_nodes = topology['nodes']
+        topo_points = topology['points']
+        #topo_lines = topology['lines']
+        #topo_boundaries = topology['boundaries']
+        #topo_centroids = topology['centroids']
+        #topo_areas = topology['areas']
+        #topo_islands = topology['islands']
+        #topo_faces = topology['faces']
+        #topo_kernels = topology['kernels']
+        topo_primitives = topology['primitives']
+        topo_map3d = topology['map3d']
+        assert_t_nodes = "( TOPOLOGY_NODES " + thevector +" " + str(topo_nodes) + " )" 
+        assert_t_points = "( TOPOLOGY_POINTS " + thevector +" " + str(topo_points) + " )" 
+        #assert_t_lines = "( TOPOLOGY_LINES " + thevector +" " + str(topo_lines) + " )" 
+        #assert_t_boundaries = "( TOPOLOGY_BOUNDARIES " + thevector +" " + str(topo_boundaries) + " )" 
+        #assert_t_centroids = "( TOPOLOGY_CENTROIDS " + thevector +" " + str(topo_centroids) + " )" 
+        #assert_t_areas = "( TOPOLOGY_AREAS " + thevector +" " + str(topo_areas) + " )" 
+        #assert_t_islands = "( TOPOLOGY_ISLANDS " + thevector +" " + str(topo_islands) + " )" 
+        #assert_t_faces = "( TOPOLOGY_FACES " + thevector +" " + str(topo_faces) + " )" 
+        #assert_t_kernels = "( TOPOLOGY_KERNELS " + thevector +" " + str(topo_kernels) + " )" 
+        assert_t_primitives = "( TOPOLOGY_PRIMITIVES " + thevector +" " + str(topo_primitives) + " )" 
+        assert_t_map3d = "( TOPOLOGY_MAP3D " + thevector +" " + str(topo_map3d) + " )" 
+    
+        GLOBAL_CLIPS__ENVIRONMENT.Assert(assert_t_nodes )
+        GLOBAL_CLIPS__ENVIRONMENT.Assert(assert_t_points)
+        #GLOBAL_CLIPS__ENVIRONMENT.Assert(assert_t_lines)
+        #GLOBAL_CLIPS__ENVIRONMENT.Assert(assert_t_boundaries)
+        #GLOBAL_CLIPS__ENVIRONMENT.Assert(assert_t_centroids)
+        #GLOBAL_CLIPS__ENVIRONMENT.Assert(assert_t_areas)
+        #GLOBAL_CLIPS__ENVIRONMENT.Assert(assert_t_islands)
+        #GLOBAL_CLIPS__ENVIRONMENT.Assert(assert_t_faces)
+        #GLOBAL_CLIPS__ENVIRONMENT.Assert(assert_t_kernels)
+        GLOBAL_CLIPS__ENVIRONMENT.Assert(assert_t_primitives)
+        GLOBAL_CLIPS__ENVIRONMENT.Assert(assert_t_map3d)
+
+        #dto:
+        dbconnection = grass.vector_db(thevector)
+        mymessage="*** vector_dbconncetion = " + str(dbconnection)
+        grass.debug(_(mymessage))
+ 
+        columns = grass.vector_columns(thevector)
+
+        mymessage="*** vector columns = " + str(columns)
+        grass.debug(_(mymessage))
+        #?? Is there a similar API interface to v.info -g (vectors region). ?? 
+    else:
+        #grass.message(_("g.infer: Something really wrong with vector" + str(thevector)))
+        sys.exit(1)
+
+
+
+#######################################################################
+## RASTER IMPORT
+#######################################################################
+
+
+def ingest_facts_rasters(facts_rasters,ignore_raster_labels):
+    """! Ingestion of all user-provided GRASS raster layers. Option: Ignore GRASS raster labels"""
+    facts_rasters_list=[]
+    count_maps = 0
+    gisenv = grass.gisenv()
+    gisenv_mapset = gisenv['MAPSET']                        
+    for this_facts_raster in str(facts_rasters).split(','): 
+        grass.debug(_("Ingesting Raster: "+this_facts_raster))
+        count_maps = count_maps + 1
+        
+        #gisenv = grass.gisenv()
+        #gisenv_mapset = gisenv['MAPSET']         
+        #listofmaps=grass.list_grouped('rast')[gisenv_mapset]
+        #if (this_facts_raster) not in listofmaps:
+        #    grass_fatal("g.infer: Raster layer does not exist:" + str(this_facts_raster))
+        #    sys.exit(1)        
+            
+        import_raster_test(this_facts_raster)
+        
+        is_elevation_level = False
+        facts_rasters_list.append(this_facts_raster)
+        grassraster2factlayer(this_facts_raster,"GRASS RASTER",ignore_raster_labels,is_elevation_level)
+    return set(facts_rasters_list)
+
+
+
+    
+def grassraster2factlayer(the_raster,the_comment_string="GRASS RASTER",ignore_raster_labels=False,elevationlevel=False):
+    """! Generate facts from a GRASS raster layer including the coordinates, the digital number AND the value attribute
+    test for categories: r.category --quiet geology fs=: 0> 1:metamorphic or 1: 
+    """
+
+    #TO BE INCLUDED:
+    ## test for input raster map
+    #result = grass.find_file(name = map_name, element = 'cell', quiet = True)
+    #if not result['file']
+    #grass.fatal("Raster map <%s> not found" % map_name)
+
+    #check for category strings:
+    raster_with_labels = True
+    the_categories = raster_categories(the_raster)
+    if len(the_categories) < 1:
+       raster_with_labels = False
+    # find map in search path
+    mapset = G_find_cell2(the_raster, '') 
+
+    #Attribute recognition doesnt work for rast3d rasters
+
+    # determine the inputmap type (CELL/FCELL/DCELL) 
+    typename = 'undefined'
+    data_type = G_raster_map_type(the_raster, mapset)
+    if data_type == CELL_TYPE:
+       ptype = POINTER(c_int)
+       type_name = 'CELL'
+    elif data_type == FCELL_TYPE:
+       ptype = POINTER(c_float)
+       type_name = 'FCELL'
+    elif data_type == DCELL_TYPE:
+       ptype = POINTER(c_double)
+       type_name = 'DCELL'
+  
+    # construct strings to generate templates both on pyclips and clips level:
+ 
+    buildtemplate_template = "(slot x)(slot y)"
+    bashstar_template = "(deftemplate " + the_raster + " (slot x)(slot y)"
+
+    attribute_list = []
+    attribute_list.append("x")
+    attribute_list.append("y")
+
+    if elevationlevel:
+       buildtemplate_template = buildtemplate_template + "(slot z)"
+       bashstar_template = bashstar_template  + "(slot z)"
+       attribute_list.append("z")
+    #Append a column for elevation if this raster layer stems from a rast3d layer, aka has a z-Value constant attached to it
+
+    attr_name_value = 'value'
+
+    attr_name_attribute = 'attribute' 
+
+    if type_name == 'CELL':
+        export_type_value = 'integer'
+      ### UNTESTED !!!! 
+    else:
+        export_type_value = 'double precision'
+    ###^^^--- The datdtype is defined below: CELL/FCELL/DCELL -> fix  !
+
+    #export_type_attribute = "varchar(" + str(GLOBAL_ATTRIBUTE_TYPE) + ")"
+
+    # generate low level GRASS structures 
+
+    infd = G_open_cell_old(the_raster, mapset)
+    inrast = G_allocate_raster_buf(data_type) 
+    inrast = cast(c_void_p(inrast), ptype)
+
+    rows = G_window_rows()
+    cols = G_window_cols()
+
+    hd=struct_Cell_head()
+    G_get_cellhd(the_raster,mapset,byref(hd))
+
+
+    ###############################
+
+    if raster_with_labels and not ignore_raster_labels:    
+        buildtemplate_template = buildtemplate_template + "(slot "+ attr_name_value +")"+ "(multislot "+ attr_name_attribute +")"
+        bashstar_template = bashstar_template + "(slot "+ attr_name_value +")" + "(multislot "+ attr_name_attribute +")"+")" 
+        attribute_list.append(attr_name_value)
+        attribute_list.append(attr_name_attribute)       
+    else:
+        buildtemplate_template = buildtemplate_template + "(slot "+ attr_name_value +")"
+        bashstar_template = bashstar_template + "(slot "+ attr_name_value +") )"
+        attribute_list.append(attr_name_value)
+     
+        
+    #Instantiate the new template in PyClips
+    the_new_template = GLOBAL_CLIPS__ENVIRONMENT.BuildTemplate(the_raster,buildtemplate_template,the_comment_string)
+    #Instantiate the new template in Clips
+    prelude_upload(bashstar_template)
+
+    for rown in xrange(rows):
+        therow = G_get_raster_row(infd, inrast, rown, data_type)
+     
+        for coln in xrange(cols):
+            coo_col = G_col_to_easting(coln, byref(hd))
+            coo_row = G_row_to_northing(rown, byref(hd))
+            the_value=inrast[coln]
+            fallback=''
+            the_category=the_categories.get(str(the_value),fallback)
+            to_assert = "(" + the_raster + " (x " + str(coo_col) + ") (y " + str(coo_row) + ")"
+            if elevationlevel: 
+                to_assert =  to_assert + "(z "+ str (elevationlevel) + ")"
+
+            to_assert =  to_assert + "(value " + str(the_value) + ")"
+            if raster_with_labels and not ignore_raster_labels:
+                to_assert =  to_assert + "(attribute " + str(the_category) + ")"
+
+            to_assert =  to_assert + ")"          
+            GLOBAL_CLIPS__ENVIRONMENT.Assert(to_assert)
+
+    G_close_cell(infd)
+    G_free(inrast)
+
+    global_layers_template_put(the_raster,the_new_template) 
+    global_layers_raster_type_put(the_raster,type_name)
+
+    return
+
+
+def grassraster_KB_load_raster(the_raster):
+    """! Creates a template and asserts the facts for a GRASS raster - to be used with internal knowledgebases  """ 
+    ### !!! Requires a failsafe to test whether the layer exists at all !
+    is_elevation_level = False
+    ignore_raster_labels = FALSE
+    #facts_rasters_set = set(facts_rasters_list.append(the_raster))
+    #^^ is only set otherwise during explicit raster upload in MAIN.
+    # !!!allow for update option
+    grassraster2factlayer(the_raster,"GRASS RASTER",ignore_raster_labels,is_elevation_level)
+
+
+########################################################################
+#### RASTER METADATA FACTS
+########################################################################
+
+#TBD: Provide the metadata for a GRASS raster as CLIPS facts for use in the inference process.
+
+
+# grass.raster_info
+# grass.raster_history
+
+# tbd: Actual region/coverage a raster layer: r.region
+# tbd: r.support
+# tbd: stats: r.median, r.quantile, r.statistics, r.univar
+# tbd: number format (integer, floats, etc)
+# r.info ?
+
+
+#######################################################################
+## VOLUME IMPORT 
+#######################################################################
+
+
+def ingest_factsraster3ds(facts_raster3ds):
+    """! Ingestion of all user-provided GRASS raster3D (volume) layers"""
+    facts_raster3ds_list=[]
+    count_maps = 0
+                     
+    for this_facts_raster3d in str(facts_raster3ds).split(','): 
+        grass.message(_("Ingesting Raster3D: "+this_facts_raster3d))
+        import_rast3d_test(this_facts_raster3d)
+        #listofmaps=grass.list_grouped('rast3')[gisenv_mapset]
+        #if (this_facts_raster) not in listofmaps:
+        #    grass_fatal("g.infer: Raster layer does not exist:" + str(this_facts_raster))
+        #    sys.exit(1)                                                                                
+        count_maps = count_maps + 1
+        facts_raster3ds_list.append(this_facts_raster3d)
+        grassvolume2factlayer(this_facts_raster3d) 
+    return set(facts_raster3ds_list)
+
+
+
+def grassvolume2factlayer(the_volume):
+    """! Generate facts from a GRASS volume layer including the 3d coordinates and the digital number"""
+    the_raster = str(the_volume)+"_slice_"
+
+    #the_layers_template = global_layers_template_get(the_volume)
+ 
+    #layers_raster_type = global_layers_raster_type_get(the_volume)
+
+    #global_layers_rast3d_slices_get(the_volume)
+
+    p = grass.pipe_command('r3.to.rast',flags='rm',input=the_volume, output=the_raster.rstrip("_"), quiet='TRUE')
+    # tbd: replace the_raster by a randomly generated name.
+
+    grass.debug("grassvolume2factlayer: Sleeping 10 sec")
+    time.sleep(10) 
+    #SLEEP to ensure that the pipe returns in time. This is ugly and need to be improved.
+    # get height of layerstack
+    region = region3()
+    stack_height=region['depths']
+    stack_res=region['tbres']
+
+    this_raster3d_raster_slices_list = []
+    #create a container for all raster_file_names for this raster3d volume
+
+    #ITERATE OVER THE stack of raster layerswhich were creared
+    for level in range(1, int(stack_height)):
+      if level < 10:
+         levelstring="0000"+str(level)
+      elif level < 100:
+         levelstring="000"+str(level)
+      elif level < 1000:
+         levelstring="00"+str(level)
+      elif level < 10000:
+         levelstring="0"+str(level)  
+      current_raster=the_raster+levelstring
+    #^^ use the real elevations ( not the levels) level*elevationelta=ELEVATIONVARIABLE
+
+
+      grass.debug("Raster-Level: "+current_raster)
+      this_raster3d_raster_slices_list.append(current_raster)
+      this_elevation=stack_res * level 
+      the_ignore_label_flag = True
+      #the_template,raster_type = grassraster2factlayer(current_raster,"GRASS VOLUME",the_ignore_label_flag,this_elevation)
+
+      #the_layers_template[current_raster]=the_template
+      #layers_raster_type[current_raster]=raster_type
+      grassraster2factlayer(current_raster,"GRASS VOLUME",the_ignore_label_flag,this_elevation)
+
+      ###^^ to be returned !
+    #global_layers_template_put(the_volume,the_layers_template)
+ 
+    #global_layers_raster_type_put(the_volume,layers_raster_type)
+
+    global_layers_rast3d_slices_put(the_volume,this_raster3d_raster_slices_list)
+    
+    #return the_layers_template, layers_raster_type, this_raster3d_raster_slices_list
+
+
+
+def grassvolume2factlayer_internal(the_volume):
+    """! Internal Use: Generate facts from a GRASS volume layer including the 3d coordinates and the digital number"""
+    grassvolume2factlayer(the_volume) 
+
+########################################################################
+#### VOLUME METADATA FACTS
+########################################################################
+
+#TBD: Provide the metadata for a GRASS raster3D volume as CLIPS facts for use in the inference process.
+
+# r3.timestamp
+# r3.stats
+# r3.univar
+
+
+
+
+##############################################################
+##############################################################
+##############################################################
+##############################################################
+##############################################################
+##############################################################
+## METADATA
+##############################################################
+##############################################################
+
+##########################################################
+## GRASS SESSION METADATA to FACTS
+##########################################################
+    
+def assert_region():
+    """! Creates facts for all GRASS region parameters"""
+    region = region3()
+    region_rows = region['rows']
+    region_cols = region['cols']
+    region_cells = region['cells']
+    region_ewres = region['ewres']
+    region_nsres = region['nsres']
+    region_n = region['n']
+    region_s = region['s']
+    region_e = region['e']
+    region_w = region['w']
+
+    # Accomodate for 3D region parameters:
+    region_t = region['t']
+    region_b = region['b']
+    region_tbres = region['tbres'] 
+    region_ewres3 = region['ewres3']
+    region_nsres3 = region['nsres3']   
+    region_rows3 = region['rows3']
+    region_cols3 = region['cols3']
+    region_depths = region['depths']
+    region_cells3 = region['cells3']
+ 
+
+    assert_region_rows = "( REGION_ROWS " + str(region_rows) + " )" 
+    assert_region_cols = "( REGION_COLS " + str(region_cols) + " )"
+    assert_region_cells = "( REGION_CELLS " + str(region_cells) + " )" 
+    assert_region_ewres = "( REGION_EWRES " + str(region_ewres) + " )"
+    assert_region_nsres = "( REGION_NSRES " + str(region_nsres) + " )" 
+    assert_region_n = "( REGION_N " + str(region_n) + " )"
+    assert_region_s = "( REGION_S " + str(region_s) + " )" 
+    assert_region_e = "( REGION_E " + str(region_e) + " )"
+    assert_region_w = "( REGION_W " + str(region_w) + " )"
+
+    #  Region 3D parameters:
+    assert_region_rows3 = "( REGION_ROWS3 " + str(region_rows3) + " )" 
+    assert_region_cols3 = "( REGION_COLS3 " + str(region_cols3) + " )"
+    assert_region_cells3 = "( REGION_CELLS3 " + str(region_cells3) + " )" 
+    assert_region_ewres3 = "( REGION_EWRES3 " + str(region_ewres3) + " )"
+    assert_region_nsres3 = "( REGION_NSRES3 " + str(region_nsres3) + " )" 
+    assert_region_tbres = "( REGION_TBRES " + str(region_tbres) + " )" 
+    assert_region_t = "( REGION_T " + str(region_t) + " )"
+    assert_region_b = "( REGION_B " + str(region_b) + " )" 
+    assert_region_depths = "( REGION_DEPTHS " + str(region_depths) + " )" 
+
+    GLOBAL_CLIPS__ENVIRONMENT.Assert(assert_region_rows)
+    GLOBAL_CLIPS__ENVIRONMENT.Assert(assert_region_cols)
+    GLOBAL_CLIPS__ENVIRONMENT.Assert(assert_region_cells)
+    GLOBAL_CLIPS__ENVIRONMENT.Assert(assert_region_nsres)
+    GLOBAL_CLIPS__ENVIRONMENT.Assert(assert_region_ewres)
+    GLOBAL_CLIPS__ENVIRONMENT.Assert(assert_region_n)
+    GLOBAL_CLIPS__ENVIRONMENT.Assert(assert_region_s)
+    GLOBAL_CLIPS__ENVIRONMENT.Assert(assert_region_e)
+    GLOBAL_CLIPS__ENVIRONMENT.Assert(assert_region_w)
+
+    GLOBAL_CLIPS__ENVIRONMENT.Assert(assert_region_rows3)
+    GLOBAL_CLIPS__ENVIRONMENT.Assert(assert_region_cols3)
+    GLOBAL_CLIPS__ENVIRONMENT.Assert(assert_region_cells3)
+    GLOBAL_CLIPS__ENVIRONMENT.Assert(assert_region_nsres3)
+    GLOBAL_CLIPS__ENVIRONMENT.Assert(assert_region_ewres3)
+    GLOBAL_CLIPS__ENVIRONMENT.Assert(assert_region_tbres)
+    GLOBAL_CLIPS__ENVIRONMENT.Assert(assert_region_t)
+    GLOBAL_CLIPS__ENVIRONMENT.Assert(assert_region_b)
+    GLOBAL_CLIPS__ENVIRONMENT.Assert(assert_region_depths)
+
+
+   
+def assert_gisenv():
+    """!Assert all GRASS environmental variables (GISENV / Location / Mapset) as facts in the CLIPS environment"""
+    gisenv = grass.gisenv()
+    gisenv_gisdbase = gisenv['GISDBASE']
+    gisenv_location_name = gisenv['LOCATION_NAME']
+    gisenv_mapset = gisenv['MAPSET']
+    gisenv_grass_gui = gisenv['GRASS_GUI']
+  
+    assert_gisdbase = "( GISDBASE " + gisenv_gisdbase + " )" 
+    assert_location_name = "( LOCATION_NAME " + gisenv_location_name + " )" 
+    assert_mapset = "( MAPSET " + gisenv_mapset + " )" 
+    assert_grass_gui= "( GRASS_GUI " + gisenv_grass_gui + " )" 
+
+    # More variables to be included !
+    
+    GLOBAL_CLIPS__ENVIRONMENT.Assert(assert_gisdbase)
+    GLOBAL_CLIPS__ENVIRONMENT.Assert(assert_location_name)
+    GLOBAL_CLIPS__ENVIRONMENT.Assert(assert_mapset)
+    GLOBAL_CLIPS__ENVIRONMENT.Assert(assert_grass_gui)
+
+
+
+
+########################################################################
+#### GRASS7 TEMPORAL METADATA FACTS
+########################################################################
+
+# tbd: no python support yet
+
+########################################################################
+#### DATABASE CONNECTIVITY METADATA FACTS
+########################################################################
+
+#TBD: Integrate this metadata as CLIPS facts for use in the inference process.
+
+# grass.db_connection
+# grass.db_describe
+# grass.db_select
+
+
+##########################################################################
+##########################################################################
+##########################################################################
+##########################################################################
+##########################################################################
+##########################################################################
+## EXPORT from CLIPS constructs to GRASS layers
+##########################################################################
+##########################################################################
+
+
+# Export sanity checks needed ?
+
+
+def fact2rastercell(afact,raster_name,integer_case):
+   """! Returns for  a (raster-) fact the structured content of a GRASS - raster cell"""
+   the_x = float(afact.Slots['x'])
+   the_y = float(afact.Slots['y'])
+   if integer_case:
+      the_value = int(afact.Slots['value'])
+   else:
+      the_value = float(afact.Slots['value'])
+   ###^^ not everything is FLOAT !
+   
+   if 'attribute' in afact.Slots.keys():
+      #the_attribute=afact.Slots['attribute']
+      #alternative to deal with multiple string content - works for vector, untested here.
+      the_attribute=""
+      multifield_list = afact.Slots['attribute']
+      allitems=""
+      for item in multifield_list:
+       the_attribute=the_attribute + str(item).rstrip() + " "
+      the_attribute.rstrip(" ")
+   else: 
+      the_attribute=False
+
+   if 'z' in afact.Slots.keys():
+       the_elevation = float(afact.Slots['z'])
+   else: 
+      the_elevation=False
+   return the_x,the_y,the_value,the_attribute,the_elevation
+
+#######################################################################
+## RASTER EXPORT
+####################################################################### 
+
+def factslayer_fromraster2grassraster_internal(rastername,ignore_labels=False):
+  """! Internal Use: Exports a grassraster facts to GRASS vector (point) layer which are transformed into a GRASS raster layer"""
+  factslayer_fromraster2grassraster(rastername,ignore_labels,False)
+
+
+def factslayer_fromraster2grassraster(rastername,ignore_labels=False,raster_type=False):
+  """! Exports a grassraster facts to GRASS vector (point) layer which are transformed into a GRASS raster layer""" 
+  ### tbd: take care of Z-column for rast3d !
+
+  ### start a dictionary to track all attribute/value pairs 
+
+#  global layers_template
+  thetemplate = global_layers_template_get(rastername) 
+  raster_type = global_layers_raster_type_get(rastername) 
+
+# test: if exists: use ELSE: False
+  layers_raster_type[rastername] = raster_type
+  #??? is this the right ordering ?
+
+  attribute_dict = {}
+
+  #Check for number types:
+  if raster_type:
+     if raster_type == "CELL":
+        integer_case = TRUE
+        grass.debug("[factslayer_fromraster2grassraster] INTEGER LIKE INPUT MAP")
+     else:
+        integer_case = FALSE
+        grass.debug("[factslayer_fromraster2grassraster] FLOAT LIKE INPUT MAP")
+        # we don't care what kind of float it is
+  else:
+     # no raster type provided, we must check the facts to figure it out.
+     grass.message("[factslayer_fromraster2grassraster] No raster map type defined: PROBING FACTS TO DEFINE OUTPUT MAP TYPE")
+     integer_case = facts_all_integer(thetemplate,'value')
+
+  #define array to collect random access info from facts
+  if integer_case:
+     raster_output = garray.array(dtype=numpy.int32)
+     grass.debug("[factslayer_fromraster2grassraster] Integer Array")
+  else:
+     grass.debug("[factslayer_fromraster2grassraster] Float Array")
+     raster_output = garray.array()
+
+  #### GRASS LOW LEVEL COMMANDS start here
+  #setup GRASS helpers to transform coordinates into columns and rows.
+  mapset = G_find_cell2(rastername, '') 
+  hd=struct_Cell_head()
+  G_get_cellhd(rastername,mapset,byref(hd))
+
+  thisfact = fact_first(thetemplate)
+
+  if thisfact:   
+     now_x,now_y,now_value,now_attribute,now_elevation = fact2rastercell(thisfact,rastername,integer_case)
+     # now_elevation is currently not used further. 
+     # the z-component is ignored -> the z/level info is also part of the template name.
+     coo_col = int(G_easting_to_col(now_x, byref(hd)))
+     coo_row = int(G_northing_to_row(now_y, byref(hd)))
+     if now_attribute:
+         attribute_dict.update({str(now_attribute):now_value})
+            # push attribute into attribute dictionary if is does not exist yet. 
+     if integer_case:
+         raster_output[coo_row,coo_col] = numpy.int32(now_value)
+     else:
+         raster_output[coo_row,coo_col] = float(now_value)
+
+     count = 1
+     carry_on = 1
+
+  while carry_on:
+     count = count +1
+     thisfact = fact_next(thetemplate, thisfact)
+     if thisfact:
+         now_x,now_y,now_value,now_attribute,now_elevation = fact2rastercell(thisfact,rastername,integer_case)
+         coo_col = int(G_easting_to_col(now_x, byref(hd)))
+         coo_row = int(G_northing_to_row(now_y, byref(hd)))
+         if now_attribute:
+               attribute_dict.update({str(now_attribute):now_value})
+         if integer_case:
+               raster_output[coo_row,coo_col] = numpy.int32(now_value)
+         else:
+               raster_output[coo_row,coo_col] = float(now_value)
+     else:
+         carry_on = 0
+  #!!! coordinate skew is still there !: add +0.5 ?
+  
+  # Remove previous version of layer in GRASS domain:
+  grass.run_command('g.remove', rast=rastername, quiet='TRUE')
+  
+  #write changed raster out
+  raster_output.write(rastername)
+
+  #writeout attributes if any exist
+  if attribute_dict.keys():
+     grassfeed = grass.feed_command("r.category",rules='-',map=rastername, quiet='TRUE')
+     for key in attribute_dict.keys():
+         this_attribute  = str(int(attribute_dict[key])) + ":" + str(key)+"\n"
+         grassfeed.stdin.write(this_attribute)
+     grassfeed.stdin.close()
+
+  #get rid of NULL values (untested) #FACTNULL ist der UGLY interne Wert !
+  grass.run_command('r.null', map=rastername, setnull=FACT_NULL, quiet='TRUE')
+
+  #IF INTEGER: ^^^^
+  # IF FLOAT: Handle * => nan case for NULL value
+
+
+
+########################################################################
+####VECTOR EXPORT
+########################################################################
+
+
+
+def vector_facts2grassvector_string(afact,thecolumnslist):
+    """!Builds and returns a GRASS-formatted string from the facts associated to a GRASS vector """
+    #(grassraster (name foo) (x 596203) (y 4915149)(hanni 42)(nanni 43))
+
+    myresult = str(afact.Slots['x'])+"|"+ str(afact.Slots['y'])
+    multifield_list = list()
+    #^^dummy-define variable for later use
+     
+    for column in thecolumnslist:
+        if (column != 'x')and( column !='y'):
+            multifield_list = afact.Slots[column]
+            allitems=""    
+        if (len(multifield_list) > 0):
+            for item in multifield_list:
+                allitems=allitems + str(item).rstrip() + " "    
+            myresult = myresult+"|"+ allitems.rstrip(" ")
+
+    grass.debug(_("vector_facts2grassvector_string:" + myresult))
+    myresult = myresult + "\n"
+    return myresult
+
+
+def factslayer2grassvector_internal(vectorname):
+    """! Internal Use: Creates a GRASS vector from a factslayer"""
+    factslayer2grassvector(vectorname) 
+    # ^^^Untested ! 
+
+
+
+def factslayer2grassvector(vectorname):
+    """! Creates a GRASS vector from a factslayer"""
+    #!! To be considered: Shall the name  of a newly to be created  output vector is to be included ?
+    #
+
+    #!! In case that a OUTPUT layer has been created with COLUMNS, but remains empty:
+    #   v.in.ascii -e creates only an empty layer.
+    count = 0
+    thetemplate = global_layers_template_get(vectorname)  # --> Could cause a problem in a "new vector (Xanadu)" case. Otherwise: optional argument ?
+    the_columns = global_layers_vector_vinascii_get(vectorname)
+    the_columns_list = global_layers_vector_columns_get(vectorname)
+    #complete_columns= cat_filter('x double precision, y double precision,' + the_columns.strip("\'"))
+    #^^^ original version: assumes that x/y columns are NOT provided by the user.
+    complete_columns= cat_filter('' + the_columns.strip("\'"))
+    # works for now ^^^
+    #20120508: This must be discussed:
+    # is it a good thing if the user has to define X and Y columns when entering the columns-description ?
+    # con: x/X y/Y can be misleading -> internal import assumes that x/y are the needed coordinates.
+    #!!!
+    #print str(vectorname) +" Facts =>  "+str(facts_total(thetemplate))
+    if (facts_total(thetemplate) < 1):
+        # ^^^^FACTS_TOTAL needs a FAILSAFE for the NULL case !
+        #g.message(_("Export stopped: No facts found for export vector: " + the_template))
+        grass.message(_("[factslayer2grassvector]: No facts found for export vector: " + str(vectorname) + " --> EMPTY VECTOR CREATED"))
+        grass.run_command("v.in.ascii","e",input='-',output=vectorname, x=1, y=2, columns=complete_columns, overwrite='True', quiet='TRUE')
+     
+    else:
+        mystring = str(vectorname) + "-facts-count: "+ str(facts_total(thetemplate))
+        #g.message(_("Export continues: " + mystring))
+        grassfeed = grass.feed_command("v.in.ascii",input='-',output=vectorname, x=1, y=2, columns=complete_columns, overwrite='True',   quiet='TRUE')
+
+     
+        firstfact = fact_first(thetemplate)
+        thisfact = firstfact
+        if thisfact: 
+            carry_on = 1
+            grassfeed.stdin.write(vector_facts2grassvector_string(firstfact,the_columns_list))
+            count = 1
+            while carry_on:
+                count = count +1
+                thisfact = fact_next(thetemplate, thisfact)
+                if thisfact:
+                    grassfeed.stdin.write(vector_facts2grassvector_string(thisfact,the_columns_list))
+                else:
+                  carry_on = 0
+        grassfeed.stdin.close()
+    return count
+
+#######################################################################
+## VOLUME EXPORT
+#######################################################################
+
+### !!! The foofact.Slot.keys() mechanism allows to check whether a Z-value exists  
+### -> for now none is handed over.
+### Volume import/export could not be achieved via 2D rasters otherwise.
+
+def factslayer_fromraster3d2grassraster3d_internal(the_inference_map):
+   """! Internal USe: Update an existing GRASS volume layer from its CLIPS facts representation"""
+   factslayer_fromraster3d2grassraster3d(the_inference_map)
+# ^^ UNTESTED !
+
+
+def factslayer_fromraster3d2grassraster3d(the_inference_map):
+    """! Update an existing GRASS volume layer from its CLIPS facts representation"""
+    # for each item in the slices list: 
+    #   get the corresponding template from the vinasciss/templates list 
+    #   launch GRASSRASTER generation processess
+    # bundle rasters into a raster3d
+ 
+    #global_layers_raster_type_get(the_volume)
+    # shouldn't this one be handed over, too ?
+  
+    the_slices_list = global_layers_rast3d_slices_get(the_inference_map)
+    slices_list_string=""
+    for this_slice in the_slices_list:
+        layers_templates = global_layers_template_get(this_slice)   
+        slices_list_string=slices_list_string+","+str(this_slice)
+        #generate raster slice:
+        factslayer_fromraster2grassraster(this_slice,False) 
+
+    slices_list_string.lstrip(',')
+    #^^^remove leading comma 
+    p = grass.pipe_command('r.to.rast3',input=slices_list_string, output=the_inference_map, quiet='TRUE', overwrite='TRUE')
+
+
+##########################################################################
+##########################################################################
+##########################################################################
+##########################################################################
+##########################################################################
+##########################################################################
+## CLIPS Engine Settings
+##########################################################################
+##########################################################################
+
+#######################################################################
+## CLIPS Save options for knowledge items
+
+
+def clips_save(inference_map,save_option):
+    """! Write CLIPS information to file""" 
+     
+    if save_option.find("facts") > -1:
+        grass.debug(_("SAVE: Facts"))
+        forensics_facts=inference_map+"_facts.clips"
+        GLOBAL_CLIPS__ENVIRONMENT.SaveFacts(forensics_facts)
+ 
+    if save_option.find("constructs") > -1:
+        grass.debug(_("SAVE: Constructs"))
+        forensics_constructs=inference_map+"_constructs.clips"
+        GLOBAL_CLIPS__ENVIRONMENT.Save(forensics_constructs)
+
+    if save_option.find("instances") > -1:
+        grass.debug(_("SAVE: Instances"))
+        forensics_instances=inference_map+"_instances.clips"
+        GLOBAL_CLIPS__ENVIRONMENT.SaveInstances(forensics_instances)
+
+def clips_bsave(inference_map,save_option):
+    """! Write CLIPS information to file"""      
+    binary_export = 0
+
+    if save_option.find("facts") > -1:
+        grass.debug(_("BSAVE: Facts"))
+        forensics_facts=inference_map+"_facts.clips"
+        GLOBAL_CLIPS__ENVIRONMENT.SaveFacts(forensics_facts)
+ 
+    if save_option.find("constructs") > -1:
+        grass.debug(_("BSAVE: Constructs"))
+        forensics_constructs=inference_map+"_constructs.bin"
+        GLOBAL_CLIPS__ENVIRONMENT.BSave(forensics_constructs)
+ 
+    if save_option.find("instances") > -1:
+        grass.debug(_("BSAVE: Instances"))     
+        forensics_instances=inference_map+"_instances.bin"
+        GLOBAL_CLIPS__ENVIRONMENT.BSaveInstances(forensics_instances)
+     
+#######################################################################
+## CLIPS Set Config
+
+def clips_config(config_option):
+    """! Set CLIPS engine config-setting"""
+    config_string = "auto-float-dividend,dynamic-constraint-checking,fact-duplication,incremental-reset,reset- globals,sequence-operator-recognition,static-constraint-checking"
+    config_list = str(config_string).split(',')
+    for item in config_list:        
+        if watch_option.find(item) > -1:
+            grass.message(_("(set-"+str(item)+" TRUE )"))
+            now = GLOBAL_CLIPS__ENVIRONMENT.SendCommand("(set-"+str(item)+" TRUE )")
+
+#######################################################################
+## CLIPS Set Watch
+
+def clips_watch(watch_option):
+    """! Set CLIPS engine watch-setting"""
+    watch_string = "activations,compilations,facts,functions,genericfunctions,globals,methods,messagehandlers,messages,rules,slots,statistics,all"
+    watch_list = str(watch_string).split(',')
+    for item in watch_list:        
+       if watch_option.find(item) > -1:
+         grass.message(_("(watch "+ str(item)+" )"))
+         now = GLOBAL_CLIPS__ENVIRONMENT.SendCommand("(watch "+ str(item)+" )")
+
+#######################################################################
+## CLIPS Set list
+
+def clips_list(list_option):
+    """! Set CLIPS engine option-settings"""
+    if list_option.find("agenda") > -1:
+      GLOBAL_CLIPS__ENVIRONMENT.PrintAgenda()
+    if list_option.find("breakpoints") > -1:
+      GLOBAL_CLIPS__ENVIRONMENT.PrintBreakpoints()
+    if list_option.find("classes") > -1:
+      GLOBAL_CLIPS__ENVIRONMENT.PrintClasses()
+    if list_option.find("deffacts") > -1:
+      GLOBAL_CLIPS__ENVIRONMENT.PrintDeffacts()
+    if list_option.find("definstances") > -1:
+      GLOBAL_CLIPS__ENVIRONMENT.PrintDefinstances()
+    if list_option.find("facts") > -1:
+      GLOBAL_CLIPS__ENVIRONMENT.PrintFacts()
+    if list_option.find("focusstack") > -1:
+      GLOBAL_CLIPS__ENVIRONMENT.PrintFocusStack()
+    if list_option.find("functions") > -1:
+      GLOBAL_CLIPS__ENVIRONMENT.PrintFunctions()
+    if list_option.find("generics") > -1:
+      GLOBAL_CLIPS__ENVIRONMENT.PrintGenerics()
+    if list_option.find("globals") > -1:
+      GLOBAL_CLIPS__ENVIRONMENT.ShowGlobals()
+      #"show" display the variables AND their values
+    if list_option.find("instances") > -1:
+      GLOBAL_CLIPS__ENVIRONMENT.PrintInstances()
+    if list_option.find("messagehandlers") > -1:
+      GLOBAL_CLIPS__ENVIRONMENT.PrintMessagehandlers()
+    if list_option.find("modules") > -1:
+      GLOBAL_CLIPS__ENVIRONMENT.PrintModules()
+    if list_option.find("rules") > -1:
+      GLOBAL_CLIPS__ENVIRONMENT.PrintRules()
+    if list_option.find("templates") > -1:
+      GLOBAL_CLIPS__ENVIRONMENT.PrintTemplates()
+      
+#######################################################################
+## CLIPS Set dribble
+
+def clips_dribble(inference_map,toggle_dribble):
+    """! Set CLIPS engine dribble-setting"""
+    if toggle_dribble:
+      grass.message(_("(dribble-on "+str(inference_map)+".dribble )"))
+      now = GLOBAL_CLIPS__ENVIRONMENT.SendCommand("(dribble-on "+str(inference_map)+".dribble )")
+
+
+#######################################################################
+## CLIPS Set external traceback
+
+def clips_external_traceback(toggle_external_traceback):
+    """! Toggle CLIPS engine traceback-setting"""
+    if toggle_external_traceback:
+      clips.SetExternalTraceback(True)
+      #WORKS: confirmed 20120302
+
+#######################################################################
+## CLIPS Module stack seeding
+
+def clips_module_stack(inference_focus_module):
+    """! Set CLIPS engine focus-setting on a specific KB module"""
+    if inference_focus_module:
+        #iterate over comma seperated inference_focus_module AAA,BBB,CCCC and build up "focus AAA BBB CCC" string.
+        grass.message(_("clips_module_stack: Under development"))
+        clips.PrintFocusStack()
+        ### clips command: (focus AAA BB CC)
+        focus = GLOBAL_CLIPS__ENVIRONMENT.SendCommand("(focus AAA BBB CCC )")
+
+        
+        #FindModule($modulename) !! - finds an existing module 
+        # BuildModule
+        #popFocus
+        #printFocusStack
+        #
+        #clips.SetCurrent() / SetFocus / PopFocus
+        #CLIPS: (list-focus-stack) (clear-focus-stack) (focus fi fa fo)
+        #tbd: strip string "inference_focus_module" off commata ("A,B,C") -> "A B C" and assign GLOBAL_CLIPS__ENVIRONMENT.SendCommand("(focus "+str(STTINGSANSCOMMATA)+".dribble )")
+    else:
+        grass.message(_("CLIPS_MODULE_STACK => ELSE:this should not happen"))
+
+#######################################################################
+## CLIPS Set class-default
+
+def clips_classdefault(classdefault_option):
+    """! Set CLIPS engine class-default-setting"""
+    #(set‑class-defaults-mode <mode>)
+    if classdefault_option.find("convenience") > -1:
+        now = GLOBAL_CLIPS__ENVIRONMENT.SendCommand("( set‑class-defaults-mode convenience)")
+    if classdefault_option.find("conservation") > -1:
+        now = GLOBAL_CLIPS__ENVIRONMENT.SendCommand("( set‑class-defaults-mode conservation)")
+
+
+####################################################################### 
+###########SET DEBUG SETTING#########################
+    ###?? GLOBAL_CLIPS__ENVIRONMENT.Memory[Options] Object P42 pyclips manual
+    
+    #CLIPS Debug Settings which could be provided to the user for forensics.
+    
+    # Conserve: TRUE / False
+    # EnvironmentErrosEnabled
+    # Free()
+    # PPBuffersize
+    # Requests: readonly!
+    # Used: readonly !
+    # NumberOffEnvironmenst
+    
+
+
+##########################################################################
+##########################################################################
+##########################################################################
+##########################################################################
+##########################################################################
+## INFERENCE RUN
+##########################################################################
+##########################################################################
+
+
+##########################################################
+# Interactive mode.
+# code snippet adapted from http://pyclips.sourceforge.net/web/?q=node/19 author: franzg
+##########################################################
+
+# Description: TBD
+
+# needed: uo/down keys to navigate a history similar to the bash shell history.
+
+class interactive_shell(object):
+    """an interactive CLIPS prompt activated via the i-Flag"""
+ 
+    def __init__(self):
+        self.__ps1 = "g.infer CLIPS prompt[%(cmdno)s/%(lineno)s] (Exit: Ctrl-D)> "
+        self.__ps2 = "g.infer CLIPS prompt[%(cmdno)s/%(lineno)s] (Exit: Ctrl-D): "
+        self.__cmdno = 1
+        self.__lineno = 1
+ 
+    def __cmdcomplete(self, cms):
+        """check if CLIPS command is complete (stolen from 'commline.c')"""
+        def eat_ws(s, i):
+            """eat up whitespace"""
+            while i < len(s) and s[i] in _string.whitespace: i += 1
+            return i
+        def eat_string(s, i):
+            """eat up strings"""
+            if s[i] != '"' or i >= len(s): return i
+            i += 1
+            while i < len(s):
+                if s[i] == '"': return i + 1
+                else:
+                    if s[i] == '\\': i += 1
+                    i += 1
+            if i > len(s): raise ValueError, "non-terminated string"
+            return i
+        def eat_comment(s, i):
+            """eat up comments"""
+            if s[i] != ';' or i >= len(s): return i
+            while i < len(s) and s[i] not in '\n\r': i += 1
+            return i + 1
+        s = cms.strip()
+        if len(s) == 0: return False
+        depth = 0
+        i = 0
+        while i < len(s):
+            c = s[i]
+            if c in '\n\r' and depth == 0: return True
+            elif c == '"': i = eat_string(s, i)
+            elif c == ';': i = eat_comment(s, i)
+            elif c == '(': depth += 1; i += 1
+            elif c == ')': depth -= 1; i += 1
+            elif c in _string.whitespace: i = eat_ws(s, i)
+            else: i += 1
+            if depth < 0: raise ValueError, "invalid command"
+        if depth == 0: return True
+        else: return False
+ 
+    def Run(self):
+        """start or resume an interactive CLIPS shell"""
+        exitflag = False
+        while not exitflag:
+            self.__lineno = 1
+            s = ""
+            dic = { 'cmdno': self.__cmdno, 'lineno': self.__lineno }
+            prompt = self.__ps1 % dic
+            try:
+                while not self.__cmdcomplete(s):
+                    if s: s += " "
+                    s += raw_input(prompt).strip()
+                    self.__lineno += 1
+                    dic = { 'cmdno': self.__cmdno, 'lineno': self.__lineno }
+                    prompt = self.__ps2 % dic
+            except ValueError, e:
+                sys.stderr.write("[SHELL] %s\n" % str(e))
+            except EOFError:
+                clips.ErrorStream.Read()
+                exitflag = True
+                # tbd: allow also an "graceful" exit using a (exit) command!
+            try:
+                if not exitflag:
+                    GLOBAL_CLIPS__ENVIRONMENT.SendCommand(s, True)
+            except clips.ClipsError, e:
+                sys.stderr.write("[PYCLIPS] %s\n" % str(e))
+            self.__cmdno += 1
+            r0 = clips.StdoutStream.Read()
+            r1 = clips.DisplayStream.Read()
+            tx = clips.TraceStream.Read()
+            r = ""
+            if r0: r += r0
+            if r1: r += r1
+            t = clips.ErrorStream.Read()
+            if r: r = "%s\n" % r.rstrip()
+            if t: t = "%s\n" % t.rstrip()
+            if tx: t = "%s\n" % tx.rstrip() + t
+            #^^^2013_Feb19: This throws an error if WATCH is not set:
+            # TypeError: cannot concatenate 'str' and 'NoneType' objects
+
+
+            if t: sys.stderr.write(t)
+            if r: sys.stdout.write(r)
+ 
+##########################################################################
+# CLI Interface code
+# taken from http://commentsarelies.blogspot.de/2008/07/using-printout-and-readline-in-pyclips.html
+# Author: Johan Lindberg, 2008-07-14
+
+# Description: code to provide an interactive CLIPS shell for g.infer sessions.
+
+def pyprintout(*args):
+    """! TBD"""
+    for arg in args[1]:
+        if arg.cltypename().upper() == "SYMBOL":
+            if arg.upper() == "CRLF":
+               print
+            elif arg.upper() == "TAB":
+               print "\t",
+            else:
+              print arg,
+
+        else:
+            print arg,
+
+
+def pyreadline(*args):
+    """! TBD"""
+    return raw_input()
+
+def pyread(*args):
+    """! TBD"""
+    return raw_input()
+
+#######################################################################
+## CLIPS LAYER BATCHSTAR SEEDING
+
+
+def prelude_upload(the_string):
+    """! CReate a tempfile on the GRASS_level,and announce this file at the CLIPS level for BatchSTar usage?"""
+    #generate prelude for batchstar and write it out to a tempfile
+    tempfile = grass.read_command('g.tempfile',pid=random.randint(1,1000000))
+    file = open(tempfile, 'w')
+    file.write(the_string)
+    file.close()
+    # Make the template definitions available on the BatchStar level.
+    GLOBAL_CLIPS__ENVIRONMENT.BatchStar(tempfile)
+    # Remove the template
+    os.remove(tempfile)
+
+
+#######################################################################	
+## Set CLIPS engine options
+
+def set_inference_strategy(inference_strategy):
+    """! Set CLIPS engine inference strategy accoring to user input"""
+    global GLOBAL_CLIPS__ENVIRONMENT
+    strategy_was = GLOBAL_CLIPS__ENVIRONMENT.EngineConfig.Strategy
+    istrat = GLOBAL_CLIPS__ENVIRONMENT.SendCommand("(set-strategy "+str(inference_strategy)+")")
+    strategy_is = GLOBAL_CLIPS__ENVIRONMENT.EngineConfig.Strategy
+    mymessage = "Inference strategy="+str(inference_strategy)
+    grass.debug(_(mymessage))
+
+def set_salience_evaluation_behaviour(salience_evaluation_behaviour):
+    """! Set CLIPS salience evaluation accoring to user input"""
+    global GLOBAL_CLIPS__ENVIRONMENT
+    behaviour_was = GLOBAL_CLIPS__ENVIRONMENT.EngineConfig.SalienceEvaluation
+    is_behave = GLOBAL_CLIPS__ENVIRONMENT.SendCommand("(set-salience-evaluation "+str(salience_evaluation_behaviour)+")")
+    mymessage = "Salience evaluation strategy="+str(salience_evaluation_behaviour)
+    grass.debug(_(mymessage))
+
+
+#######################################################################
+## Ingest knowledge data: rulebases, facts, instances
+
+
+def ingest_rulebase_file(rulebase_file):
+    """! Ingestion of a user-provided rulebase file (KB)"""
+    global GLOBAL_CLIPS__ENVIRONMENT
+    if os.path.isfile(rulebase_file):
+        GLOBAL_CLIPS__ENVIRONMENT.BatchStar(rulebase_file)
+    else:
+        grass.fatal(_("File does not exist: " + rulebase_file))
+
+def ingest_facts_file(facts_file):
+    """! Ingestion of all user-provided facts file"""
+    global GLOBAL_CLIPS__ENVIRONMENT
+    if os.path.isfile(facts_file):
+        GLOBAL_CLIPS__ENVIRONMENT.LoadFacts(facts_file)
+        grass.debug(_("[ingest_facts_file] Facts ingested from: " + facts_file))
+    else:
+        grass.fatal(_("File does not exist: " + facts_file))
+
+def ingest_instances_ascii_file(instances_ascii_file):
+    """! Ingestion of all user-provided ASCII instances (COOL, etc) file"""
+    global GLOBAL_CLIPS__ENVIRONMENT
+    GLOBAL_CLIPS__ENVIRONMENT.LoadFacts(facts_file)
+    if os.path.isfile(instances_ascii_file):
+        GLOBAL_CLIPS__ENVIRONMENT.LoadInstances(instances_ascii_file)
+        grass.message(_("Instances (ascii) ingested from: " + instances_ascii_file))
+    else:
+        grass.fatal(_("File does not exist: " + instances_ascii_file))
+
+def ingest_instances_binary_file(instances_binary_file):
+    """! Ingestion of all user-provided binary instances (COOL, etc) file"""
+    global GLOBAL_CLIPS__ENVIRONMENT
+    GLOBAL_CLIPS__ENVIRONMENT.LoadFacts(facts_file)
+    if os.path.isfile(instances_binary_file):
+     GLOBAL_CLIPS__ENVIRONMENT.BLoadInstances(instances_binary_file)
+     grass.message(_("Instances (binary) ingested from: " + instances_binary_file))
+    else:
+     grass.fatal(_("File does not exist: " + instances_binary_file))
+
+#######################################################################
+## Invoke inference process
+
+def launch_inference(max_rule_firing=False):
+    """! Invoke inference process, with the option to limit the maximum number of firing rules"""
+    global GLOBAL_CLIPS__ENVIRONMENT
+    grass.debug(_("[launch_inference]-----Inference starts-------"))
+    if max_rule_firing:
+       GLOBAL_CLIPS__ENVIRONMENT.Run(int(max_rule_firing))
+    else:
+       GLOBAL_CLIPS__ENVIRONMENT.Run()
+    grass.debug(_("[launch_inference]-----Inference stops-------"))
+
+
+
+##########################################################################
+##########################################################################
+##########################################################################
+##########################################################################
+##########################################################################
+## KNOWLEDGEBASES
+##########################################################################
+##########################################################################
+
+
+#2013-01-16: Exported into seperate files
+# tbd: Provide mechanisms to manage external KB as simple text-files (not *.PY)
+	
+##########################################################################
+##########################################################################
+##########################################################################
+##########################################################################
+##########################################################################
+## G.INFER SESSION SETUP
+##########################################################################
+##########################################################################
+	
+####################
+# Clips to Python/GRASS downlink tools:
+
+def register_grass_functions_in_clips():
+    """! Register several GRASS-related functions for use on the Rule level."""
+    #Usage: GLOBAL_CLIPS__ENVIRONMENT.Eval("python-call g.message _(/"hello world/") "))
+
+    # pyCLIPS CLI i/o code: 
+    clips.RegisterPythonFunction(pyprintout)
+    clips.RegisterPythonFunction(pyreadline)
+    clips.RegisterPythonFunction(pyread)
+
+    # !!! Keep an eye on this stuff and how it works (documenatation!) 
+    # The functions (below) rely on the already registered Python functions (right above).
+    ############################################
+    #Build CLIPS function: GINFER_PRINTOUT (on the CLIPS and pyCLIPS levels)
+    py_printout1 = GLOBAL_CLIPS__ENVIRONMENT.BuildFunction("ginfer_printout","?logical-name $?args","""(if (member$ python-call (get-function-list)) then (funcall python-call pyprintout ?logical-name $?args) else (progn$ (?arg $?args)(printout ?logical-name ?arg)))""")
+    bashstar_printout1="(deffunction ginfer_printout (?logical-name $?args)(if (member$ python-call (get-function-list)) then (funcall python-call pyprintout ?logical-name $?args) else (progn$ (?arg $?args)(printout ?logical-name ?arg))))"
+    prelude_upload(bashstar_printout1)
+
+    ############################################
+    #Build CLIPS function: GINFER_READLINE (on the CLIPS and pyCLIPS levels)
+    py_readline1 = GLOBAL_CLIPS__ENVIRONMENT.BuildFunction("ginfer_readline","$?logical-name","""(if (> (length$ $?logical-name) 0) then (bind ?logical-name (first$ $?logical-name)) else (bind ?logical-name t)) (if (member$ python-call (get-function-list)) then (funcall python-call pyreadline ?logical-name) else (readline ?logical-name)))  """)
+    bashstar_readline1 = "(deffunction ginfer_readline ($?logical-name)"
+    bashstar_readline1 = bashstar_readline1 + "(if (> (length$ $?logical-name) 0) then (bind ?logical-name (first$ $?logical-name)) else (bind ?logical-name t))" 
+    bashstar_readline1=bashstar_readline1 + "(if (member$ python-call (get-function-list)) then (funcall python-call pyreadline ?logical-name) else (readline ?logical-name)))"
+    prelude_upload(bashstar_readline1)
+
+    ############################################
+    #Build CLIPS function: GINFER_READ (on the CLIPS and pyCLIPS levels)
+    py_read1 = GLOBAL_CLIPS__ENVIRONMENT.BuildFunction("ginfer_read","$?logical-name","""(if (> (length$ $?logical-name) 0) then (bind ?logical-name (first$ $?logical-name)) else (bind ?logical-name t)) (if (member$ python-call (get-function-list)) then (eval (funcall python-call pyread ?logical-name)) else (read ?logical-name))) """)
+    bashstar_read1="(deffunction ginfer_read ($?logical-name) (if (> (length$ $?logical-name) 0) then (bind ?logical-name (first$ $?logical-name)) else (bind ?logical-name t)) (if (member$ python-call (get-function-list)) then (eval (funcall python-call pyread ?logical-name)) else (read ?logical-name)))"
+    prelude_upload(bashstar_read1)
+
+    #############################################
+    # Pyclips stuff (to be accessible in rules and on the CLIPS prompt
+    # issue a grass(?) command:
+    clips.RegisterPythonFunction(pyclips_send_command)
+    #upload and execute facts/rules/whatnot from a file
+    clips.RegisterPythonFunction(pyclips_batchstar)
+
+    # GRASS stuff:
+    clips.RegisterPythonFunction(grass_message)
+    clips.RegisterPythonFunction(grass_fatal)
+    #clips.RegisterPythonFunction(grass.message)
+    clips.RegisterPythonFunction(assert_vector_metadata)
+    clips.RegisterPythonFunction(grassvector2factlayer)
+    clips.RegisterPythonFunction(grassvector2factlayer_internal)
+    clips.RegisterPythonFunction(grassraster2factlayer)
+    #clips.RegisterPythonFunction(grassraster2factlayer_internal) #removed 2013-05-16
+    clips.RegisterPythonFunction(grassvolume2factlayer)
+    clips.RegisterPythonFunction(grassvolume2factlayer_internal)
+    #clips.RegisterPythonFunction(factslayer_fromraster2grassraster_internal)
+    #clips.RegisterPythonFunction(factslayer_fromraster3d2grassraster3d_internal)
+    #clips.RegisterPythonFunction(factslayer2grassvector_internal)
+    #^^^ These functions require a central storgae place for INPUT INFORMATION
+    clips.RegisterPythonFunction(assert_region)
+    clips.RegisterPythonFunction(assert_gisenv)
+
+    clips.RegisterPythonFunction(grass.mapcalc)
+    clips.RegisterPythonFunction(grass_raster_info)
+    clips.RegisterPythonFunction(grass_run_command)
+    clips.RegisterPythonFunction(grass_read_command)
+
+    clips.RegisterPythonFunction(grass_start_command)
+    #clips.RegisterPythonFunction(LOADFACTS)
+    #clips.RegisterPythonFunction(ASSERT_RASTER_METADATA)
+    #clips.RegisterPythonFunction(DATENBANKZEUGS)
+    #clips.RegisterPythonFunction(MAPCALC)
+    #clips.RegisterPythonFunction("GRASS_LAMBDA")
+    #tbd:
+    # r.mapcalc
+    # raster/vector layer import
+    # database queries
+
+#####################################################
+## EXPERIMENTAL:
+
+#def KB_layers_spearfish():
+    #these KB layers will be imported BEFORE the rulebase is loaded.
+    #this assures that the rules can become valid as the templates they are referring to
+    #have already been instantiated.
+    #
+    #2013-02-19: Currently the check for the Spearfish location is done as rule #1.
+    # the check needs to be executed BEFORE the Spearfish layers are attempted to be uploaded.
+    #
+    # Maybe a simple failsafe in grassraster_KB_load_raster: Test for existance of layer.
+    #
+
+
+    ################SPEARFISH Raster Layers#########################################
+    #grass.message(_("SPEARFISH RASTER LAYER RUSHMORE: Loading"))            
+    #grassraster_KB_load_raster("geology")
+    #grassraster_KB_load_raster("rushmore")
+    #grassraster_KB_load_raster("landuse")
+    #grassraster_KB_load_raster("soils")
+    #grassraster_KB_load_raster("vegcover")
+
+    ################SPEARFISH Vector Layers#########################################
+    #grass.message(_(""SPEARFISH VECTOR LAYER bugsites: starting...")) 
+    #grassvector_KB_load_vector("archsites")
+    #grassvector_KB_load_vector("bugsites") #Mountain Pine Beetle Damage
+##
+#####################################################
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+##########################################################################
+##########################################################################
+##########################################################################
+##########################################################################
+##########################################################################
+##########################################################################
+##########################################################################
+##########################################################################
+## MAIN
+##########################################################################
+
+def main():
+ 
+                               
+    #################################################
+    ##### Sanity Check 1: Ensure that g.infer is run within a GRASS environment
+    if "GISBASE" not in os.environ:
+      print "You must be in GRASS GIS to run this program."
+      sys.exit(1)
+
+    #################################################
+    #### Import parameters provided from the GRASS GUI
+    
+     
+    #################################################
+    #### GRASS GUI Flags
+    
+    toggle_dribble = flags['d']
+    toggle_external_traceback = flags['e']
+    interactive_mode = flags['i']
+    ignore_raster_labels = flags['l']
+    toggle_suddendeath_mode = flags['x']
+
+    #################################################
+    #### GRASS GUI Options
+        
+    ## GRASS input layers
+    facts_rasters = options['rast']
+    facts_vectors = options['vector']
+    facts_raster3ds = options['rast3d']
+
+    # CLIPS knowledge items
+    facts_file = options['facts']
+    instances_binary_file = options['bload_instances']
+    instances_ascii_file = options['load_instances']
+
+    instances_binary_output = options['bsave_instances']
+    instances_ascii_output = options['save_instances']
+
+    ## GRASS output layers
+    inference_map = options['output']
+    output_maps = options['export'] 
+    result_columns = options['columns']
+
+    ## CLIPS parameters
+    max_rule_firing = options['limit']
+    inference_strategy = options['strategy']
+    salience_evaluation_behaviour = options['salience']
+    inference_focus_module = options['module']
+    #^^^--- tbd: remains to be switched on & tested  
+    # CLIPS: (set-current-module FOO)
+    # (focus module2 module1 )
+    
+    save_option = options['save_rulebase']
+    bsave_option = options['bsave_rulebase']
+    config_option = options['config']
+    watch_option = options['watch']
+    print_option = options['print']
+    classdefault_option = options['classdefault']
+    #^-tbd
+    #structure can be either default (builtin template) or custom (user-provided template - this requries a proper SQL description in the payload file)
+    # even better: remove the XOR option: Its either a deafault with a defined value, OR a STRUCTstring has to be provided
+
+    ## Knowledge bases 
+    rulebase_file = options['rulebase']
+    builtin_rulesbase_files = options['library']
+
+
+    #################################################
+    #Set Variables and Data Structures 
+    #################################################
+    
+    #Initialize dictionary to keep the attribute structures for all vectors:
+    global layers_vector_vinascii
+
+    global layers_template
+    global layers_vector_columns
+    global layers_raster_type
+    global layers_raster3d_slices
+
+    facts_vectors_set={}
+    facts_rasters_set={}
+    facts_raster3ds_set={}
+
+    ###^^^^ REFACTOR !
+
+
+
+    #################################################
+    ##### Invoke GRASS Ctype low level  interface
+    #################################################
+    G_gisinit('g.infer')
+    
+  
+
+    #################################################
+    ## Initialize the CLIPS session 
+    #################################################    
+    global GLOBAL_CLIPS__ENVIRONMENT
+    xps = clips.Environment()
+    GLOBAL_CLIPS__ENVIRONMENT=xps
+
+    #################################################
+    ## Register additional Python modules with CLIPS session 
+    register_grass_functions_in_clips()
+    
+    #################################################
+    ## change inference strategy
+    if inference_strategy:
+       set_inference_strategy(inference_strategy)
+
+    #################################################
+    ## set salience evaluation behaviour 
+    if salience_evaluation_behaviour:
+       set_salience_evaluation_behaviour(salience_evaluation_behaviour)
+
+
+    #################################################
+    ## load knowledge base module stack
+    if inference_focus_module:
+       focus_string = "(focus"
+       for this_module in str(inference_focus_module).split(','): 
+           grass.message(_("> Module: "+this_module))
+           focus_string += " "+this_module
+       focus_string += ")"
+       #GLOBAL_CLIPS__ENVIRONMENT.SendCommand(focus_string)
+    ### ^^^Refactor / Encapsulate
+
+    #################################################
+    ##### CLIPS options
+    clips_dribble(inference_map,toggle_dribble)
+  
+    clips_external_traceback(toggle_external_traceback)
+
+    if save_option: 
+        clips_save(inference_map,save_option)
+
+    if bsave_option: 
+        clips_bsave(inference_map,save_option)
+
+    if config_option: 
+        clips_config(config_option)
+
+    if watch_option: 
+        clips_watch(watch_option)
+
+    if print_option: 
+        clips_list(print_option)
+
+    if classdefault_option: 
+        clips_classdefault(classdefault_option)
+
+
+    #################################################
+    ## Sanity Checks of Input Layers
+    #################################################
+    sanity_checks_input_layers(facts_rasters,facts_raster3ds,facts_vectors,facts_file,rulebase_file)
+    
+
+
+    #################################################
+    ## DETECT VECTORS
+    #################################################
+    #Iterate over all input vector layers (if existing): create a set and count total 
+    if facts_vectors > "":
+        count_vectors,facts_vectors_set=detect_input_layer(facts_vectors,facts_rasters_set,facts_raster3ds_set)
+
+    #################################################
+    ## DETECT RASTER
+    #################################################
+    #Iterate over all input raster layers (if existing): create a set and count total 
+    if facts_rasters > "":
+        count_maps,facts_rasters_set=detect_input_layer(facts_rasters,facts_vectors_set,facts_raster3ds_set)
+
+    #################################################
+    ## DETECT RASTER3D (Volume)
+    #################################################
+    #Iterate over all input raster layers (if existing): create a set and count total 
+ 
+    if facts_raster3ds > "":
+        count_maps,facts_raster3ds_set=detect_input_layer(facts_raster3ds,facts_vectors_set,facts_rasters_set)
+
+
+    #################################################
+    # DETECT AND ACCESS OUTPUT MAP  
+    #################################################
+
+    if inference_map:
+        if not result_columns:
+            grass.fatal(_("Unable to create output vector map: Parameter <columns> missing."))
+        else:
+            create_vector=TRUE  
+            #grass_message(str("[MAIN: INFERENCE MAP DETECTED] Export Vector: " + inference_map +  " columns = " + result_columns))
+
+            grassvector_new(inference_map,result_columns)
+            grassvector2factlayer(inference_map,result_columns)
+            #grass_message(str("*** [MAIN: INFERENCE MAP CREATED !] *** "))
+
+    #################################################
+    ## INGEST VECTORS
+    #################################################
+    # Iterate over all vector layers and create grassvector-facts for each one from the provided attribute
+
+    if facts_vectors:
+        ingest_facts_vectors(facts_vectors,inference_map)
+
+    #################################################
+    ## INGEST RASTER
+    #################################################
+    # Iterate over all raster layers and create grassraster-facts for each one and return total count as list 
+    if facts_rasters: 
+        facts_rasters_set = ingest_facts_rasters(facts_rasters,ignore_raster_labels)
+
+    #################################################
+    ## INGEST RASTER3D
+    #################################################
+    # Iterate over all raster3d layers and create grassraster-facts for each one and return total count as list 
+    if facts_raster3ds: 
+        facts_raster3ds_set = ingest_factsraster3ds(facts_raster3ds)
+
+    #################################################
+    ## Ingest GRASS Session Metadata facts 
+    #################################################
+    region3() #ensure the 3d settings are available
+    assert_region()
+    assert_gisenv()
+
+       
+    #################################################
+    ## load built-in knowledge bases
+    #################################################
+
+    if builtin_rulesbase_files:
+        #grass.debug(_(""PREBUILT KB BEING LOADED !"))
+        this_count = 0
+        for this_kb in str(builtin_rulesbase_files).split(','): 
+            this_count = this_count + 1
+            __import__(this_kb)
+            kb_mods=sys.modules[this_kb]
+            grass.message(_("[g.infer Main] Using library KB: " + str(this_kb)))
+            prelude_upload(kb_mods.knowledgebase())
+        if interactive_mode:
+            grass.message(_("[-i Flag:]: Built-in knowledgebase has been loaded:")) 
+            grass.message(_("[-i Flag:]: Enter (run) on the CLIPS prompt to start."))
+            grass.message(_("[-i Flag:]: [Ctrl-D to leave CLIPS-prompt]"))
+         
+    #################################################
+    ## INGEST RULEBASE
+    #################################################
+    #### Upload rulebase payload into CLIPS space
+    if rulebase_file:
+        ingest_rulebase_file(rulebase_file)
+
+
+    #################################################
+    ## INGEST FACTS
+    #################################################
+    # This has to be done AFTER the payload has been ingested -> payload (may) have to include fact templates first !
+    if facts_file:
+        ingest_facts_file(facts_file)
+
+    #################################################
+    ## INGEST INSTANCES
+    #################################################
+    # This has to be done AFTER the  has been ingested -> payload (may) have to include object definitions for instances !
+
+    if instances_ascii_file:
+        ingest_instances_ascii_file(instances_ascii_file)
+ 
+    if instances_binary_file:
+        ingest_instances_binary_file(instances_binary_file)
+
+
+   #################################################
+   ##### Interactive mode
+    if interactive_mode:
+        grass.debug(_("[i-Flag]: Entering interactive mode "))
+        clips_shell = interactive_shell()
+        clips_shell.Run()
+ 
+
+    #################################################
+    ##### "No rules, no facts, no inference" abort option:
+    norules_nofacts_noservice()
+
+   #################################################
+   ##### Pre-Inference Early Abort
+    if toggle_suddendeath_mode:
+        grass.message(_("Pre-inference abort by user request (s-flag)"))
+        sys.exit()
+
+    #################################################
+    ##### Start Main Inference Loop 
+    launch_inference(max_rule_firing)
+
+   #################################################
+   ## SAVE INSTANCES
+   #################################################
+    if instances_ascii_output:
+        GLOBAL_CLIPS__ENVIRONMENT.SaveInstances(instances_ascii_output)
+        grass.message(_("Instances saved to ASCII-file: " + instances_ascii_output))
+
+    if instances_binary_output:
+        GLOBAL_CLIPS__ENVIRONMENT.BLoadInstances(instances_binary_output)
+        grass.message(_("Instances saved to binary file: " + instances_binary_output))
+
+    #################################################
+    ##### Create new output or updates of an input layer ?
+    #################################################
+    if output_maps: 
+        for export_map in str(output_maps).split(','):
+            if export_map in facts_raster3ds_set:
+                factslayer_fromraster3d2grassraster3d(export_map)
+            elif export_map in facts_rasters_set:
+                factslayer_fromraster2grassraster(export_map,ignore_raster_labels)
+            elif export_map in facts_vectors_set:
+                factslayer2grassvector(export_map)
+            else:
+                grass.fatal(_("g.infer [MAIN]: Strange Export Map Error: this should never happen."))
+    ### ^^^ REFACTOR / ENCAPSLUATE 
+
+
+    if inference_map:
+       #grass.message(_(""MAIN: commencing EXPORT-Layer writeout " + inference_map))
+       factslayer2grassvector(inference_map)
+
+if __name__ == "__main__":
+    options, flags = grass.parser()
+    atexit.register(cleanup)
+    sys.exit(main())
+    main()
+
+
+
+	
+	
+
+
+


Property changes on: grass-addons/grass6/general/g.infer/g.infer
___________________________________________________________________
Added: svn:executable
   + *

Added: grass-addons/grass6/general/g.infer/reference.py
===================================================================
--- grass-addons/grass6/general/g.infer/reference.py	                        (rev 0)
+++ grass-addons/grass6/general/g.infer/reference.py	2013-07-17 09:20:50 UTC (rev 57185)
@@ -0,0 +1,735 @@
+# -*- coding: utf-8 -*-
+
+#######################################################################
+### Reference Knowledgebase with Demos
+#######################################################################
+
+def knowledgebase():
+#this function returns a huge here document, which is ingested by CLIPS instead or in addition to an external rulebase.
+# the string contains a rulebase containing demo rule-based actions in GRASS.
+# Some of these actions require a specific GRASS LOcation and will refuse to work otherwise [tbd]
+	
+	payload="""
+   (deffacts startup "Set the attract mode" (attract mode))
+	(assert (attract mode))
+
+(defrule welcome (declare (salience 100)) (attract mode)  => 
+ (ginfer_printout t " " crlf)
+ (ginfer_printout t "******************************************************" crlf)
+ (ginfer_printout t "*** Welcome to the g.inferreference knowledgebase ***  " crlf)
+ (ginfer_printout t "******************************************************" crlf)
+ (ginfer_printout t " " crlf)
+ (ginfer_printout t " " crlf)
+ (ginfer_printout t "Available Demonstrations:" crlf)
+ (ginfer_printout t " " crlf)
+ (ginfer_printout t "[a]  Overview g.infer extensions to CLIPS" crlf)
+ (ginfer_printout t "[b]  CLIPS output and user input" crlf)
+
+ (ginfer_printout t "[c] Ordered Facts"  crlf)
+ (ginfer_printout t "[d] tbd: Unordered Facts and Templates "  crlf)
+ (ginfer_printout t "[e] tbd: LHS Variables / Pattern Matching"  crlf)
+ (ginfer_printout t "[f] tbd: RHS Variables"  crlf)
+ (ginfer_printout t "[g] tbd: Conditionals"  crlf)
+ (ginfer_printout t "[h] tbd: Saving / loading of rules"  crlf)
+ (ginfer_printout t "[i]- Time-enabled rules demo" crlf)
+ (ginfer_printout t "[j] tbd: Salience"  crlf)
+ (ginfer_printout t "[k] tbd: Modules to partition a rulebase"  crlf)
+ (ginfer_printout t " " crlf)
+ (ginfer_printout t "Please select a demo by entering its number/letter:" crlf)
+ (ginfer_printout t " " crlf)
+ (ginfer_printout t "Hint: this knowledgebase can be written to file using (save FILENAME) from the CLIPS prompt." crlf)
+
+ (assert (demo_selection (ginfer_read t)))
+ (assert (demo_selection_completed))
+)
+
+(defrule welcome_selection_01 (demo_selection_completed) (demo_selection a) => (ginfer_printout t "Selection= g.infer extensions overview" crlf)(assert (g.infer commands)))
+(defrule welcome_selection_04 (demo_selection_completed) (demo_selection b) => (ginfer_printout t "Selection= CLI-based user input demo" crlf)(assert (readline demo)))
+(defrule welcome_selection_04 (demo_selection_completed) (demo_selection c) => (ginfer_printout t "Selection= CLI-based user input demo" crlf)(assert (orderedfacts demo)))
+
+
+
+(defrule welcome_selection_05 (demo_selection_completed) (demo_selection 5) => (ginfer_printout t "Selection= CLIPS time-enabled rules demo" crlf)(assert (time demo)))
+(defrule welcome_selection_06 (demo_selection_completed) (demo_selection 6) => (ginfer_printout t "Selection= Raster processing demo" crlf)(assert (raster demo)))
+(defrule welcome_selection_07 (demo_selection_completed) (demo_selection 7) => (ginfer_printout t "Selection= Vector processing demo" crlf)(assert (vector demo)))
+(defrule welcome_selection_08 (demo_selection_completed) (demo_selection 8) => (ginfer_printout t "Selection= GRASS location/region demo" crlf)(assert (region demo)))
+(defrule welcome_selection_09 (demo_selection_completed) (demo_selection 9) => (ginfer_printout t "Selection= bootstrap loader demo" crlf)(assert (bootstrap demo)))
+(defrule welcome_selection_A (demo_selection_completed) (demo_selection A) => (ginfer_printout t "Selection= Cellular automata demo" crlf)(assert (ca demo)))
+(defrule welcome_selection_B (demo_selection_completed) (demo_selection B) => (ginfer_printout t "Selection= R.mapcalc analogue demo" crlf)(assert (rmapcalc_rules demo)))
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+; G.INFER EXTENSION COMMANDS [WORKS]:
+
+(defrule extensions_001 (g.infer commands)  => 
+ (ginfer_printout t "=============================================================== " crlf)
+ (ginfer_printout t " " crlf)
+ (ginfer_printout t "Special g.infer commands for the CLIPS command line interface: " crlf)
+(ginfer_printout t "" crlf)
+(ginfer_printout t " ==>   Invoke the commands by (python-call YOURCOMMAND) <== " crlf)
+(ginfer_printout t " " crlf)
+ (ginfer_printout t "*** GENERAL: ***" crlf)
+ (ginfer_printout t "* grass_run_command  " crlf)
+ (ginfer_printout t "* grass_read_command  " crlf)
+ (ginfer_printout t "* grass_start_command  " crlf)
+ (ginfer_printout t "* ginfer_printout: CLIPS printout analog" crlf)
+ (ginfer_printout t "* grass_message: Print a text message on the GRASS prompt" crlf)
+ (ginfer_printout t "* grass_fatal: Print a warning message on the GRASS prompt and exit GRASS" crlf)
+(ginfer_printout t "" crlf)
+(ginfer_printout t "***  REGION / VARIABLES: ***" crlf)
+(ginfer_printout t "* assert_region  " crlf)
+(ginfer_printout t "* assert_gisenv  " crlf)
+(ginfer_printout t "* grass.mapcalc  " crlf)
+(ginfer_printout t "" crlf)
+(ginfer_printout t "*** VECTOR: ***" crlf)
+(ginfer_printout t "* assert_vector_metadata: Create fatcs from the metadata of a GRASS vector layer" crlf)
+(ginfer_printout t "* grassvector2factlayer: Import a GRASS vector layer as facts  " crlf)
+(ginfer_printout t "* grassvector2factlayer_internal  " crlf)
+(ginfer_printout t "" crlf)
+(ginfer_printout t "*** RASTER: ***" crlf)
+(ginfer_printout t "* grass_raster_info  " crlf)
+(ginfer_printout t "* grassraster2factlayer " crlf)
+(ginfer_printout t "* grassraster2factlayer_internal  " crlf)
+(ginfer_printout t "* grassvolume2factlayer  " crlf)
+(ginfer_printout t "* grassvolume2factlayer_internal  " crlf)
+(ginfer_printout t "" crlf)
+(ginfer_printout t "*** OTHER: ***" crlf)
+(ginfer_printout t "* pyprintout " crlf)
+(ginfer_printout t "* pyreadline  " crlf)
+(ginfer_printout t "* pyread  " crlf)
+(ginfer_printout t "* pyclips_load " crlf)
+(ginfer_printout t "^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^  " crlf)
+(ginfer_printout t "" crlf)
+(ginfer_printout t "" crlf)
+(ginfer_printout t "[ *** Hit return, please *** ]" crlf)
+(assert (userfeedback (ginfer_read t)))
+;(reset)
+;(run)
+; doesn't work
+)
+
+
+;;;AUSSTEHEND:
+
+; #clips.RegisterPythonFunction(grass.raster_info)
+; #clips.RegisterPythonFunction(LOADFACTS)
+; #clips.RegisterPythonFunction(ASSERT_RASTER_METADATA)
+; #clips.RegisterPythonFunction(DATENBANKZEUGS)
+; #clips.RegisterPythonFunction(MAPCALC)
+; #clips.RegisterPythonFunction("GRASS_LAMBDA")
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;READ and PRINT DEMO [WORKS]
+(defrule readline_test0 (readline demo) => 
+ (ginfer_printout t "[READ/PRINT #00]...Readline test begins..." crlf)
+)
+
+(defrule readline_test1 (readline demo) => 
+ (ginfer_printout t "[READ/PRINT #01]: Enter your, please:" crlf)
+ (assert (userfeedback (ginfer_read t)))
+ (ginfer_printout t "[READ/PRINT #01]:  Thank you." crlf)
+ (ginfer_printout t " " crlf)
+)
+
+(defrule readline_test2 (readline demo) (userfeedback ?feedback) => 
+;What to do when ?feedback contains mutliple strings ?
+ (ginfer_printout t "[READ/PRINT #02]: Your input:" $?feedback crlf)
+; $? = multifield feedback
+; ? = single field feedback
+ (ginfer_printout t " " crlf)
+ (ginfer_printout t "[READ/PRINT #02]: Enter RETURN to leave demo." crlf)
+ (assert (ending (ginfer_read t)))
+ (ginfer_printout t "[READ/PRINT #02] ========================= " crlf)
+)
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;ORDERED FACTS [WORKS]
+
+(defrule readline_of0 (orderedfacts demo) => 
+ (ginfer_printout t "[ORDERED FACTS #00]... test begins..." crlf)
+ (ginfer_printout t "[ORDERED FACTS #00]... asserting Duck fact: (duck quack)..." crlf)
+ (assert (duck quack))
+)
+
+; (facts)
+; (assert (a) (b) (c))
+; (facts 0)
+; (facts 2)
+
+
+;STRINGS: "foo"
+; (assert (duck "Joe")
+; (assert (age 43)
+; (assert (coordinates 11.1 22.4))
+;Since spaces are used to separate multiple fields, it follows that spaces cannot simply be included in facts.
+; (assert (double-quote "\"duck\""))
+
+
+; retract a fact by its number:
+;(retract 2)
+; (retract 0 2)  all facts between 0 - 2
+; (retract *) ;retract all
+
+; Before a fact can be retracted, it must be specified to CLIPS. To retract a fact from a rule, the fact-address ; first must be bound to a variable on the LHS.
+; (defrule get-married    ?duck <- (bachelor Dopey) =>    (printout t "Dopey is now happily married "  ?duck crlf)   (retract  ?duck))
+
+
+;;;WILDCARDS
+; The simplest form of wildcard is called a single-field wildcard and is shown by a question mark, "?". The "?" is also called a single-field constraint. A single‑field wildcard stands for exactly one field, as shown following.
+; (defrule dating-ducks (bachelor Dopey ?)=>   (printout t "Date Dopey" crlf))
+
+; multifield wildcard. This is a dollar sign followed by a question mark, "$?", and represents zero or more fields. Notice how this contrasts with the single-field wildcard which must match exactly one field.
+
+;(defrule duck (animal-is duck) => (assert (sound-is quack)))
+; (ppdefrule duck)
+
+; (defrule duck (animal-is duck) => (printout t "quack" crlf))
+
+;;CONDITIONALS/MATCHES
+;(defrule take-a-vacation
+;
+;   (work done)                 ; Conditional element 1
+;
+;   (money plenty)              ; Conditional element 2
+;
+;   (reservations made)         ; Conditional element 3
+;=>
+;   (printout t "Let's go!!!" crlf))
+
+;;;;;;;;;;;;;;
+;assert-string                       Performs a string assertion by taking a string as argument and asserted as ;a nonstring fact.
+
+;str-cat                                   Constructs a single-quoted string from individual items by string ;concatenation
+
+;str-index                               Returns a string index of first occurrence of a substring
+
+;sub-string                             Returns a substring from a string.
+
+;str-compare                        Performs a  string compare
+
+;str-length                              Returns the string length which is the length of a string:
+
+;sym-cat                                Returns a concatenated symbol.
+;;;;;;;;;;;;;;;;;;
+
+;Asserting of Variables:
+;(defrule make-quack   (duck-sound ?sound) =>   (assert (sound-is ?sound)))
+
+; The first time a variable is bound it retains that value only within the rule, both on the LHS and also on the RHS, unless changed on the RHS.
+
+ 
+;;;;;;;;;;;;;;CONSTRAINTS
+; A way of handling this case is to use a field constraint to restrict the values that a pattern may have on the LHS. The field constraint acts like constraints on patterns.
+
+;One type of field constraint is called a connective constraint. There are three types of connective constraints. The first is called a ~ constraint. Its ;symbol is the tilde "~". The ~ constraint acts on the one value that immediately follows it and will not allow that value.
+
+;The second connective constraint is the bar constraint, "|". The "|" connective constraint is used to allow any of a group of values to match.
+; (defrule cautious   (light yellow|blinking-yellow) =>   (printout t "Be cautious" crlf))
+
+;The third type of connective constraint is the & connective constraint. The symbol of the & connective constraint is the ampersand, "&". The & constraint forces connected constraints to match in union.The & constraint normally is used only with the other constraints, otherwise it's not of much practi­cal use. 
+;As an example, suppose you want to have a rule that will be triggered by a yellow or blinking-yellow fact. 
+; That's easy enough—j­ust use the | connective constraint as you did in a previous example. 
+; But suppose that you also want to identify the light color?
+; The solution is to bind a variable to the color that is matched using the "&" and then print out the variable.
+;(defrule cautious   (light ?color&yellow|blinking-yellow) =>   (printout t "Be cautious because light is " ?color crlf))
+
+;The variable ?color will be bound to whatever color is matched by the field yellow|blinking-yellow.
+;
+;The "&" also is useful with the "~". For example, suppose you want a rule that triggers when the light is not yellow and not red.
+; (defrule not-yellow-red   (light ?color&~red&~yellow)=>   (printout t "Go, since light is " ?color crlf))
+
+
+;;NUMBERS
+
+;CLIPS provides basic arithmetic and math functions +, /, *, -, div, max, min, abs, float, and integer. For more details, see the CLIPS Reference Manual.
+
+;  Functions can be used on the LHS and the RHS. For example, the following shows how the arithmetic operation of addition is used on the RHS of a rule to assert a fact containing the sum of two numbers ?x and ?y.
+
+;;(defrule addition (numbers ?x ?y) =>  (assert (answer-plus (+ ?x ?y))))     ; Add ?x + ?y
+
+;A function can be used on the LHS if an equal sign, =, is used to tell CLIPS to evaluate the following expression rather than use it literally for pattern matching. 
+;The following example shows how the hypotenuse is calculated on the LHS and used to pattern match against some stock items. 
+;The exponentiation, "**", function is used to square the x and y values. 
+;The first argument of exponentiation is the number which is to be raised to the power of the second argument.
+;(defrule addition (numbers ?x ?y) (stock ?ID =(sqrt (+ (** ?x 2) (** ?y 2)))) ; Hypotenuse
+;=>
+;   (printout t "Stock ID=" ?ID crlf))
+
+
+;(assert (answer-plus (+ ?x ?y ?z))))       ; ?x + ?y + ?z
+
+;  (+ 2 2.0)     ; mixed arguments give float result
+; (+ 2 2)       ;both integer arguments give integer
+; (integer (+ 2.0 2.0))   ; convert float to integer
+; (float (+ 2 2))         ;convert integer to float
+
+
+;;;;;;;;;;;;TEST CONDITIONAL ELEMENT
+;The test conditional element provides a very powerful way by which to compare numbers, variables, and strings on the LHS. 
+;The (test) is used as a pattern on the LHS. A rule will only be triggered if the (test) is satisfied together with other patterns.
+
+Logical: not an or
+Arithmetic: / * + -
+Comparison: any tpye: eq neq  numeric:  = <> <= >= > <
+
+; A predicate function is one which returns a FALSE or a non-FALSE value. The colon ":" followed by a predicate function is called a predicate constraint. The ":" may be preceded by "&", "|", or "~" or may stand by itself as in the pattern (fact :(> 2 1)). It is typically used with the & connective constraint as "&:"
+
+;(evenp <arg>)                      even number
+;(floatp <arg>)                       floating-point number
+;(integerp <arg>)                  integer
+;(lexemep <arg>)                 symbol or string
+;(numberp <arg>)                 float or integer
+;(oddp <arg>)                        odd number
+;(pointerp <arg>)                  external address
+;(sequencep <arg>)             multifield value
+;(stringp <arg>)                    string
+;(symbolp <arg>)                 symbol
+
+
+ ;;;EVAL / BUILD 
+;The evaluation function, eval, is used for evaluating any string or symbol except the "def" type constructs such as defrule, deffacts, etc.,  as if entered ;at the top‑level. The build function takes care of the "def" type constructs. The (build) function is the complement of (eval). The build function evaluates ;a string or symbol as if it were entered at the top-level and returns TRUE if the argument is a legal def-type construct such as (defrule), (deffacts), and ; ;so forth.
+
+;;;;;;;;BINDING VARIABLES
+; The analog to assigning a value to a variable on the LHS by pattern matching is binding a value to a variable on the RHS using the bind function. It's convenient to bind variables on the RHS if the same values will be repeatedly used.
+
+;(defrule addition   (numbers ?x ?y)=>   (assert (answer (+ ?x ?y)))   (bind ?answer (+ ?x ?y))   (printout t "answer is " ?answer crlf))
+
+
+;The following rule illustrates some variable bindings on the RHS. The multifield value function, create$, is used to create a multifield value.
+; (bind ?duck-bachelors (create$ Dopey Dorky Dinky))
+
+; WATCH STUFF
+;(watch facts)
+
+; (watch instances)        ; used with objects
+
+; (watch slots)            ; used with objects
+
+; (watch rules)
+
+; (watch activations)
+
+; (watch messages)         ; used with objects
+
+; (watch message-handlers) ; used with objects
+
+; (watch generic-functions)
+
+; (watch methods)          ; used with objects
+
+; (watch deffunctions)
+
+; (watch compilations)     ; on by default
+
+; (watch statistics)
+
+; (watch globals)
+
+; (watch focus)
+
+; (watch all) 
+; THERE IS A PROBLEM IN THE CURRENT SHELL (Feb 2013) WITH TH WATCH COMMANDS;
+   
+;CLIPS[2/1]> (assert (fpp ff))
+;Traceback (most recent call last):
+;  File "g.infer.clips_RC2_20130219.py", line 2902, in <module>
+;    sys.exit(main())
+;  File "g.infer.clips_RC2_20130219.py", line 2850, in main
+;    clips_shell.Run()
+;  File "g.infer.clips_RC2_20130219.py", line 2314, in Run
+;    if tx: t = "%s\n" % tx.rstrip() + t
+;TypeError: cannot concatenate 'str' and 'NoneType' objects
+
+
+;DEFFACTS
+; (deffacts walk "Some facts about walking"  (foo) (baz))
+; (reset)
+; -> damit die KB restarten.
+; (undeffacts walk)       
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;BOOTSTRAP/LOAD TEST [BROKEN]
+;tbd: einen rule-getriggerten load eines weiteren CLIPS (ASCII) programms - upload on demand. Wird das auch der rulebase zugefügt ?
+;batchstar ?
+
+;(python-call ingest_rulebase_file upload_test.clp)
+
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;RASTER WMS Import [WORKS]
+
+;; import
+;; -- file r.in.gdal
+; r.in.wms output=akl_srtm mapserver="http://onearth.jpl.nasa.gov/wms.cgi" -c layers=worldwind_dem format=geotiff style=short_int maxcols=100 maxrows=100
+
+(defrule grassrun_rinwms (raster_wms demo) => (python-call grass_message "** RHS: r.in.wms **") (python-call grass_run_command r.in.wms "c" output=akl_srtm mapserver=http://onearth.jpl.nasa.gov/wms.cgi  layers=worldwind_dem format=geotiff style=short_int maxcols=100 maxrows=100) (assert (rinwms done)))
+
+(defrule grassrun_rinwms_remove (rinwms done) => (python-call grass_message "** RHS: r.in.wms remove raster2 **") (python-call grass_run_command g.remove rast=akl_srtm.2) (assert (rinwms_remove done)))
+
+(defrule grassrun_rinwms_rename (rinwms_remove done) => (python-call grass_message "** RHS: r.in.wms rename raster1 **") (python-call grass_run_command g.rename rast=akl_srtm.1,rhs_srtm) (assert (rinwms_rename done)))
+
+(defrule grassrun_rinwms_display2 (rinwms_rename done) => (python-call grass_message "** RHS: r.in.wms display **") (python-call grass_run_command d.mon start=x0) (python-call grass_run_command d.rast map=rhs_srtm) (assert (rinwms_display1 done)))
+
+(defrule grassrun_rinwms_display1 (rinwms_display1 done) => (ginfer_printout t "Demo: Feedback, please:" crlf) (assert (ducky1 (ginfer_read t))) (assert (rinwms_display2 done)))
+
+(defrule grassrun_rinwms_display3 (rinwms_display2 done) => (python-call grass_message "** RHS: r.in.wms display cleanup **") (python-call grass_run_command d.mon stop=x0)(assert (rinwms_display_shutdown done)))
+
+(defrule grassrun_rinwms_display4 (rinwms_display_shutdown done) => (python-call grass_message "** RHS: r.in.wms purge raster **") (python-call grass_run_command g.remove rast=rhs_srtm)(assert (rinwms_gremove done)))
+
+; g.remove akl_srtm.2
+; g.rename rast=akl_srtm.1,rhs_strm
+; r.colors rhs_srtm
+; d.mon d.rast
+; g.erase rhs_srtm
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; CLIPS TIME [WORKS]
+; Muss noch angeschaltet werden !
+
+
+;(defrule grassrun_timetest1 (timetest) => (python-call grass_message "** RHS: TIMETEST 1 **") (bind ?early (time)) (ginfer_printout t "Before" ?early) (assert (timetest1)) (assert (timestamp ?early)))
+;(defrule grassrun_timetest2 (timetest1) => (python-call grass_message "** RHS: TIMETEST 2 **") (bind ?wait (time)) (ginfer_printout t "Now" ?later crlf) (assert (timetest2)))
+;(defrule grassrun_timetest3 (timetest2) => (python-call grass_message "** RHS: TIMETEST 3 **") (bind ?later (time)) (ginfer_printout t "Now" ?later crlf) (assert (timetest done)))
+
+(deftemplate event (slot tstamp (default-dynamic (time))) (slot value))
+
+(assert (event (value 1)))
+
+(defrule time1
+ ?foo <- (event (tstamp ?t1)(value 3))
+ (start-time ?t2)
+ (test (> (- ?t1 ?t2) 0.01))
+ =>
+ (retract ?foo)
+ (ginfer_printout t "TIME DEMO: Retracting" ?t1 ?t2 crlf)
+ )
+
+(defrule time2
+ (time test)
+  =>
+ (assert (event (value 3)))
+ (ginfer_printout t "TIME DEMO: Timing=ON" (time) crlf)
+ )
+
+(defrule launch_time_demo 
+   (time demo) 
+   => 
+   (assert (event (value 2)))
+   (assert (start-time (time)))
+ )
+
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+; CELLULAR AGENTS
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;UHRWERK;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;; Erzeuge zwei Zustaende Tick und Tack
+;; Das System pendelt zwischen diesen beiden Zustaenden
+;; Die TACK Regel leistet Tick -> Tack
+;; TICK leistet Tack -> Tick
+;; Der Zaehler in Tack wird dabei herabgezaehlt (durch TACK). Bei O stoppt das System.
+;; Die TACKTACK Regel erzeugt ein Rasterabbild, welches in GRASS die Zustaende darstellt
+;; 
+;;WICHTIG: AM BESTEN KEINE REGELN MIT SALIENCE KLEINER ALS 400 FUER DIE
+;; AGENTEN SELBST HERSTELLEN (350 und 300 sind vergeben)
+(deftemplate state (slot name) (slot active)(slot count))
+
+(defrule CA_Demo_wind_up_clock 
+  (ca demo) 
+  =>
+  (printout t "Cellular Automata Demo: Set up for 10 clicks " crlf)
+  (assert (state (name tick)(active 1)(count 0)))
+  (assert (state (name tack)(active 0)(count 10)))
+  ; ^^^10 = 10 Lebenstakte
+)
+(defglobal MAIN ?*grass* = (create$ ))
+;^^^ a globale variable for CellualrAutomata
+
+(defrule tack_action (declare (salience 300))(state (name tack) (active 1) (count ?c&:(> ?c 0)))
+	 => (printout t "[tack_action] count="?c crlf)
+	 (if (neq ?*grass* (create$ )) then
+	 (progn
+         (printout t "[tack_action] *Writeout Opportunity*" crlf)
+	 ;2013: (r.to.grass (str-cat "state."?c))
+         ;2013: Gegen passende Funktion ersetzen.
+
+	 ;(bind ?*grass* (create$ )) 
+	 ;;Das Auskommentieren erhaelt die letzten Zustaende, also eine Zeitkarte der Entwicklung (gut fuer mobile Agenten die "Spuren" hinterlassen).
+	 )))
+	    ;Nulle GlobalVar fuer neuen Lauf
+	    
+(defrule tick_action (declare (salience 300))(state (name tick) (active 1) (count ?c))
+	 => (printout t "[tick_action]: Slacking !" crlf))
+
+(defrule to_tack  ?tack<-(state (name tack) (active 0) (count ?tackc&:(> ?tackc 0)))
+	       ?tick<-(state (name tick) (active 1) (count ?tickc))
+=> (modify ?tack (active 1) (count (- ?tackc 1)))
+   (modify ?tick (active 0))
+   (printout t "[tick]          tick->tack" crlf)
+)
+
+(defrule to_tick  ?tack<-(state (name tack) (active 1) (count ?tackc))
+	       ?tick<-(state (name tick) (active 0) (count ?tickc))
+=> (modify ?tack (active 0) )
+   (modify ?tick (active 1) )
+   (printout t "[tack]          tack->tick" crlf)
+   ;(p (str-cat "sleep 0;")) ;;<<< does not work in g.infer
+)
+
+(defrule tack_completed 
+         (declare (salience 300))
+         (state (name tack) (active 1) (count ?c&:(> ?c 0)))
+	 ;2013:  ?done <- (done (id ?id)(value ?x))
+         ?done <- (done ?id ?value)
+	 => 
+	;2013: (printout t "[tackdone] TACK cleared:" ?id crlf)	
+        (printout t "[tack_completed] TACK cleared"  crlf)	
+	(retract ?done)
+)
+; DONE IST DER MAGISCHE KLEBER ZWISCHEN DEM UHRWERK UND DER ARBEITSEBENE.
+; Sobald in einem Takt die CA ihre AUfgabe fertig haben setzen sie ein DONE mit iherer ID (oder Koorindaten?)
+; Am Ende des Tack-Tackts werden die DONES entfernt und ie CA beginnen von neuem.
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;Conways Game of LIFE:
+;; implemented as cellular automata (CA) in CLIPS
+;; Original code by Peter Loewe, 2003
+;;
+;;
+;; Examine each grid position and spawn/kill CA according to these rules:
+;; Law 1: (alive self) AND "2 or 3" neighbours: CA lives on
+;; Law 2: (alive self) AND "< 2 or >3" neighbours: CA dies
+;; Law 3: (dead self) AND "==3" neighbours: New CA spawned
+
+(deftemplate cell (slot x) (slot y) (slot id) (slot alive)(slot neighbours))
+;Cellular agent (CA) definition template - the CA contains info about its position, its binary health (alive|dead) and the number of neighbours (which are alive, too) 
+
+(defrule ca__set_neighbours_zero (declare (salience 450))
+  ?this <-(cell (x ?x) (y ?y) (id ?id) (alive ?a)(neighbours ?n&:(> ?n 0)))
+  =>
+  (modify ?this (neighbours 0))
+)
+; Rule to reset the number of known neighbours in a CA.
+
+(defrule east (declare (salience 400))
+  ?this <- (cell (x ?x) (y ?y) (id ?id) (alive ?a)(neighbours ?n))
+  ;(cell (x ?nx&:(= ?nx (+ ?x 1))) (y ?ny)(id ?nid) (alive TRUE) (neighbours ?nn))
+  ?alive <- (cell (x ?cx) (y ?cy) (id ?nid)(alive TRUE) (neighbours ?fuk))
+  ;(cell (x ?x) (y ?ny&:(= (- ?ny ?y) -1))(id ?nid) (alive FALSE) (neighbours ?nn))
+  (test (and (eq (+ ?x 1) ?cx) (eq ?y ?cy )))
+ =>
+  (printout t "yebo" crlf)
+  (modify ?this (neighbours (+ 1 ?n)))
+)
+; Rule to test whether a CA is alive on the relative position "x+1" ("East")
+
+
+(defrule west (declare (salience 420))
+  ?this <-(cell (x ?x) (y ?y) (id ?id) (alive ?a)(neighbours ?n))
+  (cell (x ?nx&:(= ?nx (- ?x 1))) (y ?ny) (id ?nid) (alive TRUE) (neighbours ?nn))
+ =>
+  (modify ?this (neighbours (+ 1 ?n)))
+)
+; Rule to test whether a CA is alive on the relative position "x-1" ("West")
+
+(defrule north (declare (salience 420))
+  ?this <-(cell (x ?x) (y ?y) (id ?id) (alive ?a)(neighbours ?n))
+  (cell (x ?nx) (y ?ny&:(= ?ny (+ ?y 1))) (id ?nid) (alive TRUE) (neighbours ?nn))
+ =>
+  (modify ?this (neighbours (+ 1 ?n)))
+)
+; Rule to test whether a CA is alive on the relative position "y+1" ("North")
+
+(defrule south (declare (salience 420))
+  ?this <-(cell (x ?x) (y ?y)(id ?id)  (alive ?a)(neighbours ?n))
+  (cell (x ?nx) (y ?ny&:(= ?ny (- ?y 1))) (id ?nid)(alive TRUE) (neighbours ?nn))
+ =>
+  (modify ?this (neighbours (+ 1 ?n)))
+)
+; Rule to test whether a CA is alive on the relative position "y-1" ("South")
+
+(defrule southwest  (declare (salience 420))
+?this <-(cell (x ?x) (y ?y)(id ?id)  (alive ?a)(neighbours ?n))
+(cell (x ?nx&:(= ?nx (- ?x 1))) (y ?ny&:(= ?ny (- ?y 1))) (id ?nid)(alive TRUE) (neighbours ?nn))
+=>
+(modify ?this (neighbours (+ 1 ?n)))
+)
+; Rule to test whether a CA is alive on the relative position "x-1, y-1" ("Southwest")
+
+(defrule southeast  (declare (salience 420))
+  ?this <-(cell (x ?x) (y ?y)(id ?id)  (alive ?a)(neighbours ?n))
+  (cell (x ?nx&:(= ?nx (+ ?x 1))) (y ?ny&:(= ?ny (- ?y 1))) (id ?nid)(alive TRUE) (neighbours ?nn))
+ =>
+  (modify ?this (neighbours (+ 1 ?n)))
+)
+; Rule to test whether a CA is alive on the relative position "x+1, y-1" ("Southeast")
+
+(defrule northwest  (declare (salience 420))
+  ?this <-(cell (x ?x) (y ?y)(id ?id)  (alive ?a)(neighbours ?n))
+  (cell (x ?nx&:(= ?nx (- ?x 1))) (y ?ny&:(= ?ny (+ ?y 1))) (id ?nid)(alive TRUE) (neighbours ?nn))
+ =>
+ (modify ?this (neighbours (+ 1 ?n)))
+)
+; Rule to test whether a CA is alive on the relative position "x-1, y+1" ("Northwest")
+
+(defrule northeast  (declare (salience 420))
+  ?this <-(cell (x ?x) (y ?y)(id ?id)(alive ?a)(neighbours ?n))
+  (cell (x ?nx&:(= ?nx (+ ?x 1))) (y ?ny&:(= ?ny (+ ?y 1))) (id ?nid)(alive TRUE) (neighbours ?nn))
+ =>
+  (modify ?this (neighbours (+ 1 ?n)))
+)
+; Rule to test whether a CA is alive on the relative position "x-1, y-1" ("Northeast")
+
+(defrule conway_law1 (declare (salience 410))
+  ?this <- (cell (x ?x) (y ?y) (id ?id) (alive TRUE) (neighbours ?n&:(and (>= ?n 2) (<=  ?n 3))))
+ =>
+  ;2013: (assert (done (id ?id)(value TRUE)))
+  (assert (foo 2013))
+)
+; Conway's Life Law 1: CA has 2 - 3 neighbours and survives.
+
+(defrule conway_law2 (declare (salience 410))
+  ?this <- (cell (x ?x) (y ?y) (id ?id) (alive TRUE) (neighbours ?n&:(or (< ?n 2) (> ?n 3))))
+ =>
+  ;2013: (assert (done (id ?id)(value FALSE)))
+  (assert (done ?id FALSE))
+  (modify ?this (alive FALSE))
+)
+; Conway's Life Law 2: CA has less than 2 or more than 3 neighbours and dies.
+
+(defrule conway_law3 (declare (salience 410))
+  ?this <- (cell (x ?x) (y ?y) (id ?id) (alive FALSE) (neighbours ?n&: (= ?n 3)))
+ =>
+  ;2013: (assert (done (id ?id)(value TRUE)))
+  (assert (done ?id TRUE))
+  (modify ?this (alive TRUE))
+)
+; Conway's Life Law 3: A new CA is spawned at an empty location with 3 neighbours.
+
+(defrule dead (declare (salience 410))
+   (cell (x ?x) (y ?y) (id ?id)(alive FALSE) (neighbours ?n)) 
+  =>
+   (bind ?*grass* (create$ ?*grass* (format nil "%f %f 0" ?x ?y)) ) 
+)
+; rule to printout the coordinates of an deceased CA
+
+(defrule alive (declare (salience 410))
+   (cell (x ?x) (y ?y) (id ?id)(alive TRUE) (neighbours ?n)) 
+  => 
+   (bind ?*grass* (create$ ?*grass* (format nil "%f %f 100" ?x ?y)) ) 
+)
+; rule to printout the coordinates of an alive CA  
+
+(defrule CA_2013 
+  (ca demo DEACTIVATED) ; derzeit gehts in einen infinity loop! 
+ => 
+  (assert (cell (x 0) (y 0) (id (gensym*)) (alive FALSE) (neighbours 0)))
+  (loop-for-count (?x 0 5)
+	(loop-for-count (?y 0 5)
+	(assert (cell (x ?x) (y ?y) (id (gensym*)) (alive FALSE) (neighbours 0)))
+		))
+  ;;Loop to create CA from template for coordinates (x:[0-5] y:[0-5])
+
+  (assert (cell (x 1) (y 5) (id (gensym*)) (alive TRUE) (neighbours 0)))
+  (assert (cell (x 5) (y 5) (id (gensym*)) (alive TRUE) (neighbours 0)))
+  (assert (cell (x 1) (y 4) (id (gensym*)) (alive TRUE) (neighbours 0)))
+  (assert (cell (x 2) (y 4) (id (gensym*)) (alive TRUE) (neighbours 0)))
+  (assert (cell (x 3) (y 4) (id (gensym*)) (alive TRUE) (neighbours 0)))
+  (assert (cell (x 4) (y 4) (id (gensym*)) (alive TRUE) (neighbours 0)))
+  (assert (cell (x 1) (y 3) (id (gensym*)) (alive TRUE) (neighbours 0)))
+  (assert (cell (x 5) (y 3) (id (gensym*)) (alive TRUE) (neighbours 0)))
+  (assert (cell (x 4) (y 3) (id (gensym*)) (alive TRUE) (neighbours 0)))
+  ;;Explicit spawning of 9 CA on the 25 field "grid"
+)
+
+(defrule unify
+  ?dead <- (cell (x ?x) (y ?y) (id ?id)(alive FALSE) (neighbours 0))
+  ?alive <- (cell (x ?x) (y ?y) (id ?nid)(alive TRUE) (neighbours 0))
+=>
+  (printout t ?x" "?y crlf)
+  (retract ?dead)
+)
+;Rule to overwrite dead/nonexistent CA with new/alive ones: 
+; If both a dead and an alive CA exist for the same coordinate, the dead one is retracted. 
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+; R.mapcalc-like rule concatenation:
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;(assert (rmapcalc_rules demo))
+
+(defrule rmapcalc_rules_01 
+  (rmapcalc_rules demo) 
+ => 
+  (python-call grass_message "[rules like r.mapcalc] rule 01: Generate random GRASS raster") 
+  (python-call grass_run_command "r.mapcalc" "rmapcalc_rules_demo=rand(1,10)") 
+  (assert (stages_mapcalc done))
+)
+;Rule to create a new GRASS raster of random values
+
+
+(deftemplate rmapcalc_rules_demo (slot x)(slot y)(slot value))
+;Dummy template to ensure that the rules below will be parsed.
+
+(defrule rmapcalc_rules_02 
+  (stages_mapcalc done) 
+ => 
+  (python-call grass_message "[rules like r.mapcalc] rule 02: Create CLIPS facts from GRASS raster layer") 
+  (python-call grassraster2factlayer "rmapcalc_rules_demo" "the_comment" True False) 
+  (assert (stages_ingest done))
+)
+;Rule import the new GRASS raster of random values into the CLIPS environment.
+
+(defrule rmapcalc_rules_03_preparation 
+  (stages_ingest done)
+  (not (trigger ?x ?y))
+  (not (completed ?x ?y))
+  (rmapcalc_rules_demo (x ?x) (y ?y) (value ?value)) 
+  ; DAS TEMPLATE wird erst angelegt wenn der GRASSRASTER_FACTLAYER eingeladen wird. Das ist nachdem diese Regel eingelesen wird.
+  ;Ein Mechanismus wird gebraucht um das generisch zu loesen -> Anlegen des Template explizit hier im Skript....
+ => 
+  (python-call grass_message "[rules like r.mapcalc] rule 03: Generate Flag-facts for raster facts")
+  (assert (trigger ?x ?y))
+)
+; Rule to ensure that while for all facts created from the random raster layer there are (yet) no additional facs ("trigger"/"completed") sharing the same xy coordinate. While this applies (for all newly created raster-facts), an additional "trigger" fact is created for each coordinate tuple.
+
+(defrule rmapcalc_rules_04_execution 
+  ?thiscell <- (rmapcalc_rules_demo (x ?x) (y ?y) (value ?value)) 
+  ?thistrigger <- (trigger ?x ?y) (not (completed ?x ?y)) 
+ => 
+  (python-call grass_message "[rules like r.mapcalc] rule 04: Increase each raster facts by 1000000; flag as done")
+  (modify ?thiscell (value (+ 100000 ?value))) 
+  (retract ?thistrigger) 
+  (assert (completed ?x ?y)))
+
+;;;^^^ IF (aka: FOR ANY) there's a coordinate/location where there's a raster-layer-fact and a "trigger"-fact but no "completed"-fact, increase/MODIFY the attribute of the raster fact, remove the "trigger" fact and set a "completed" fact.
+
+(undeftemplate rmapcalc_rules_demo)
+
+; bzw: zwei verfahrenswege: 
+; 1) einlesen, multiplikation * 10 im CLIPS space, export
+; 2) zweiter RHS-rmapcalc aufruf zur multiplikation
+; Zeiten vergleichen
+; -> wenn Mapcalc versagt kann option 1) greifen !
+
+
+
+	"""
+	return payload
+


Property changes on: grass-addons/grass6/general/g.infer/reference.py
___________________________________________________________________
Added: svn:executable
   + *

Added: grass-addons/grass6/general/g.infer/spearfish.py
===================================================================
--- grass-addons/grass6/general/g.infer/spearfish.py	                        (rev 0)
+++ grass-addons/grass6/general/g.infer/spearfish.py	2013-07-17 09:20:50 UTC (rev 57185)
@@ -0,0 +1,537 @@
+# -*- coding: utf-8 -*-
+
+#######################################################################
+### Reference Knowledgebase with Demos for the SPEARFISH location
+#######################################################################
+
+def knowledgebase():
+#this function returns a huge here document, which is ingested by CLIPS instead or in addition to an external rulebase.
+# the string contains a rulebase containing demo rule-based actions in GRASS.
+
+	
+	payload="""
+	;(assert (attract mode))
+;attract mode sollte ein "fallback fact" werden, damit der user die KB wiederholt starten kann
+
+(defrule isspearfish (declare (salience 101)) (LOCATION_NAME spearfish60) => 
+  ;(ginfer_printout t "[Rule#1: Spearfish Location is confirmed]" crlf)
+  (assert (attract mode)))
+
+
+(defrule nospearfish (declare (salience 101)) (not (LOCATION_NAME spearfish60)) => (ginfer_printout t "PLEASE RESTART IN SPEARFISH LOCATION." crlf))
+
+(defrule welcome (declare (salience 100)) (attract mode)  (LOCATION_NAME spearfish60) => 
+ (ginfer_printout t " " crlf)
+ (ginfer_printout t "******************************************************" crlf)
+ (ginfer_printout t "*** Welcome to the g.infer Spearfish knowledgebase ***  " crlf)
+ (ginfer_printout t "******************************************************" crlf)
+ (ginfer_printout t " " crlf)
+ (ginfer_printout t " " crlf)
+ (ginfer_printout t "Available Demonstrations:" crlf)
+ (ginfer_printout t " " crlf)
+ (ginfer_printout t "[1]  Overview g.infer extensions to CLIPS" crlf)
+
+
+ ; something with a loop on RHS
+ ; something with variables on LHS
+ ; something with variables on RHS
+ ; mwas auf einem monitor darstellen
+ ; dummy template benutzen, dafuer regeln aufstezen, spater ein raster einlesen, auf das dummy template umkopieren, regeln feuern
+ (ginfer_printout t "[2] + GRASS: module call-up demo" crlf)
+ (ginfer_printout t "[3] partial GRASS: WMS for on-demand raster import / Monitor demo" crlf)
+
+ (ginfer_printout t "[4] + CLIPS: CLI-based user input demo" crlf)
+ (ginfer_printout t "[5] NO CLIPS time-enabled rules demo" crlf)
+ (ginfer_printout t "[6] + GRASS: Raster processing demo" crlf)
+ (ginfer_printout t "[7] + GRASS: Vector processing demo" crlf)
+ (ginfer_printout t "[8]- GRASS location/region manipulation demo" crlf)
+ (ginfer_printout t "[a] tbd CLIPS: Facts manipulation (create / modify / remove) "  crlf)
+ (ginfer_printout t "[b] tbd CLIPS: LHS Variables / Pattern Matching"  crlf)
+ (ginfer_printout t "[c] tbd CLIPS: RHS Variables"  crlf)
+ (ginfer_printout t "[d] tbd CLIPS: RHS sided loops/if then else"  crlf)
+ (ginfer_printout t "[c] tbd CLIPS: Salience"  crlf)
+ (ginfer_printout t "[e] tbd GRASS: Import a given Raster Layer during Inference runtime"  crlf)
+ (ginfer_printout t "[e] tbd GRASS: Change all values of a raster layer like r.mapcal-style"  crlf)
+
+(ginfer_printout t " " crlf)
+ (ginfer_printout t "Please select a demo by entering its number/letter:" crlf)
+ (ginfer_printout t " " crlf)
+ (ginfer_printout t "Hint: this knowledgebase can be written to file using (save FILENAME) from the CLIPS prompt." crlf)
+
+ (assert (demo_selection (ginfer_read t)))
+ (assert (demo_selection_completed))
+)
+
+(defrule welcome_selection_01 (demo_selection_completed) (demo_selection 1) => 
+ (ginfer_printout t "Selection= g.infer extensions overview" crlf)(assert (g.infer commands)))
+ 
+(defrule welcome_selection_02 (demo_selection_completed) (demo_selection 2) => 
+ (ginfer_printout t "Selection= GRASS modules demo" crlf)(assert (grassmodules demo)))
+
+(defrule welcome_selection_03 (demo_selection_completed) (demo_selection 3) => 
+ (ginfer_printout t "Selection= Raster WMS demo" crlf)(assert (raster_wms demo)))
+
+(defrule welcome_selection_04 (demo_selection_completed) (demo_selection 4) => 
+  (ginfer_printout t "Selection= CLIPS: User input / printout demo" crlf)(assert (readline demo)))
+
+(defrule welcome_selection_05 (demo_selection_completed) (demo_selection 5) => 
+  (ginfer_printout t "Selection= CLIPS time-enabled rules demo" crlf)(assert (time demo)))
+
+(defrule welcome_selection_06 (demo_selection_completed) (demo_selection 6) => 
+  (ginfer_printout t "Selection= Raster processing demo" crlf)(assert (raster demo)))
+
+(defrule welcome_selection_07 (demo_selection_completed) (demo_selection 7) => 
+  (ginfer_printout t "Selection= Vector processing demo" crlf)(assert (vector demo)))
+
+(defrule welcome_selection_08 (demo_selection_completed) (demo_selection 8) => 
+  (ginfer_printout t "Selection= GRASS location/region demo" crlf)(assert (region demo)))
+
+(defrule welcome_selection_09 (demo_selection_completed) (demo_selection 9) => 
+  (ginfer_printout t "Selection= bootstrap loader demo" crlf)(assert (bootstrap demo)))
+
+;(defrule welcome_selection_A (demo_selection_completed) (demo_selection A) => (ginfer_printout t "Selection= Cellular automata demo" crlf)(assert (ca demo)))
+;(defrule welcome_selection_B (demo_selection_completed) (demo_selection B) => (ginfer_printout t "Selection= R.mapcalc analogue demo" crlf)(assert (rmapcalc_rules demo)))
+
+(defrule welcome_selection_09a (demo_selection_completed) (demo_selection a) => 
+  (ginfer_printout t "Selection= CLIPS Facts manipulation demo" crlf)(assert (facts_101 demo)))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+; G.INFER EXTENSION COMMANDS [WORKS]:
+
+(defrule extensions_001 (g.infer commands)  => 
+ (ginfer_printout t "=============================================================== " crlf)
+ (ginfer_printout t " " crlf)
+ (ginfer_printout t "Special g.infer commands for the CLIPS command line interface: " crlf)
+ (ginfer_printout t "" crlf)
+ (ginfer_printout t " ==>   Invoke the commands by (python-call YOURCOMMAND) <== " crlf)
+ (ginfer_printout t " " crlf)
+ (ginfer_printout t "*** GENERAL: ***" crlf)
+ (ginfer_printout t "* grass_run_command  " crlf)
+ (ginfer_printout t "* grass_read_command  " crlf)
+ (ginfer_printout t "* grass_start_command  " crlf)
+ (ginfer_printout t "* ginfer_printout: CLIPS printout analog" crlf)
+ (ginfer_printout t "* grass_message: Print a text message on the GRASS prompt" crlf)
+ (ginfer_printout t "* grass_fatal: Print a warning message on the GRASS prompt and exit GRASS" crlf)
+(ginfer_printout t "" crlf)
+(ginfer_printout t "***  REGION / VARIABLES: ***" crlf)
+(ginfer_printout t "* assert_region  " crlf)
+(ginfer_printout t "* assert_gisenv  " crlf)
+(ginfer_printout t "* grass.mapcalc  " crlf)
+(ginfer_printout t "" crlf)
+(ginfer_printout t "*** VECTOR: ***" crlf)
+(ginfer_printout t "* assert_vector_metadata: Create fatcs from the metadata of a GRASS vector layer" crlf)
+(ginfer_printout t "* grassvector2factlayer: Import a GRASS vector layer as facts  " crlf)
+(ginfer_printout t "* grassvector2factlayer_internal  " crlf)
+(ginfer_printout t "" crlf)
+(ginfer_printout t "*** RASTER: ***" crlf)
+(ginfer_printout t "* grass_raster_info  " crlf)
+(ginfer_printout t "* grassraster2factlayer " crlf)
+(ginfer_printout t "* grassraster2factlayer_internal  " crlf)
+(ginfer_printout t "* grassvolume2factlayer  " crlf)
+(ginfer_printout t "* grassvolume2factlayer_internal  " crlf)
+(ginfer_printout t "" crlf)
+(ginfer_printout t "*** OTHER: ***" crlf)
+(ginfer_printout t "* pyprintout " crlf)
+(ginfer_printout t "* pyreadline  " crlf)
+(ginfer_printout t "* pyread  " crlf)
+(ginfer_printout t "* pyclips_load " crlf)
+(ginfer_printout t "^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^  " crlf)
+)
+
+
+;;;AUSSTEHEND:
+; #clips.RegisterPythonFunction(factslayer_fromraster2grassraster_internal)
+; #clips.RegisterPythonFunction(factslayer_fromraster3d2grassraster3d_internal)
+; #clips.RegisterPythonFunction(factslayer2grassvector_internal)
+; # Diese Funktionen erfordern das zentrale Speichern der EINGANGSINFORMATIONEN !
+; #clips.RegisterPythonFunction(grass.raster_info)
+; #clips.RegisterPythonFunction(LOADFACTS)
+; #clips.RegisterPythonFunction(ASSERT_RASTER_METADATA)
+; #clips.RegisterPythonFunction(DATENBANKZEUGS)
+; #clips.RegisterPythonFunction(MAPCALC)
+; #clips.RegisterPythonFunction("GRASS_LAMBDA")
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;GRASS RUN [WORKS]:
+(defrule grasscommandsdemo01 (grassmodules demo) => 
+; a very simple LHS triggers the lengthy RHS
+(python-call grass_message " ") 
+; note that other print functions like ginfer_printout (the ginfer wrapper for CLIPS printout) could also be used. grass_message is a g.infer wrapper for the GRASS g.message module 
+(python-call grass_message " ") 
+(python-call grass_message "==========================================================================") 
+ (python-call grass_message "-GRASS Modules Demo ")
+ (python-call grass_message "=> using the grass_run_command extension of g.infer to start GRASS modules") 
+ (python-call grass_message "------------------------------------------------------------------") 
+ (python-call grass_message "   Invoking: g.version -g -b") 
+ (python-call grass_message " ") 
+ (python-call grass_run_command "g.version" "gb" )
+ ;Note how the flags for g.version are provided without the leading "minus": Proper call on the GRASS shell would be "g.version -gb" or "g.version -g -b" 
+ (python-call grass_message "---------------------------") 
+ (python-call grass_message "   Invoking: g.region -p") 
+ (python-call grass_message " ") 
+ (python-call grass_run_command "g.region" "p" )
+ (python-call grass_message "---------------------------") 
+ (python-call grass_message "   Invoking g.list -f type=vect") 
+ (python-call grass_message " ")
+ (python-call grass_run_command "g.list" "f" "type=vect")
+ ;(python-call grass_message "---------------------------") 
+ (python-call grass_message " ")
+ (python-call grass_message "==========================================================================") 
+(python-call grass_message " ") 
+)
+
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;READLINE [WORKS]
+(defrule readline_test1 (readline demo) => 
+
+ (ginfer_printout t  " " crlf) 
+ (ginfer_printout t "==========================================================================" crlf) 
+ (ginfer_printout t "- CLIPS: User input / printout demo " crlf)
+ (ginfer_printout t "  Using ginfer_printout and ginfer_read g.infer extensions of the CLIPS commands printout and read" clrf)
+ (ginfer_printout t  " " crlf) 
+ (ginfer_printout  t "Type in some feedback, please:" crlf)
+ (assert (userfeedback (ginfer_read t)))
+ (ginfer_printout t "Thank you for your feedback." crlf)
+ ; TBD: Printout the feedback
+)
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;RASTER WMS Import [WORKS]
+
+;; import
+;; -- file r.in.gdal
+; r.in.wms output=akl_srtm mapserver="http://onearth.jpl.nasa.gov/wms.cgi" -c layers=worldwind_dem format=geotiff style=short_int maxcols=100 maxrows=100
+
+(defrule grassrun_rinwms (raster_wms demo) => 
+ ;(python-call grass_message "** RHS: r.in.wms **")
+ (ginfer_printout t  " " crlf) 
+ (ginfer_printout t "==========================================================================" crlf) 
+ (ginfer_printout t "- GRASS: Using a WMS to obtain a raster layer and a GRASS monitor to display it." crlf)
+  (ginfer_printout t "*** Online Access Mandatory ! ***" crlf)
+ (ginfer_printout t "  This uses r.in.wms, g.remove, g.rename, d.mon and d.rast on the RHS of multiple chained rules" clrf)
+ (ginfer_printout t  " " crlf) 
+ (ginfer_printout t  " 1) g.region region=landuse" crlf)
+ (python-call grass_run_command g.region rast=landuse)
+ (ginfer_printout t  " 2) r.in.wms -c -oo output=akl_srtm mapserver=http://onearth.jpl.nasa.gov/wms.cgi  layers=worldwind_dem format=geotiff style=short_int maxcols=100 maxrows=100" crlf) 
+ (python-call grass_run_command r.in.wms "c" "-o" output=akl_srtm mapserver=http://onearth.jpl.nasa.gov/wms.cgi  layers=worldwind_dem format=geotiff style=short_int maxcols=100 maxrows=100) 
+ (assert (rinwms done))
+ )
+
+(defrule grassrun_rinwms_remove (rinwms done) =>
+   (python-call grass_message "  3) r.in.wms remove raster2 **") 
+   (python-call grass_run_command g.remove rast=akl_srtm.2) 
+   (assert (rinwms_remove done)))
+
+(defrule grassrun_rinwms_rename (rinwms_remove done) => 
+   (python-call grass_message " 4) r.in.wms rename raster1 **") 
+   (python-call grass_run_command g.rename rast=akl_srtm.1,rhs_srtm) 
+   (ginfer_printout t " 5) Enter something to proceed:" crlf) 
+   (assert (feedback (ginfer_read t))) 
+   (assert (rinwms_rename done))
+ )
+
+(defrule grassrun_rinwms_display2 (rinwms_rename done) => 
+    (python-call grass_message " 5) r.in.wms display **") 
+    (python-call grass_run_command d.mon start=x0) 
+    (python-call grass_run_command d.rast map=rhs_srtm) 
+    (assert (rinwms_display1 done))
+ )
+
+(defrule grassrun_rinwms_display1 (rinwms_display1 done) => 
+ (ginfer_printout t "Demo: Feedback, please:" crlf) 
+ (assert (ducky1 (ginfer_read t))) 
+ (assert (rinwms_display2 done))
+ )
+
+(defrule grassrun_rinwms_display3 (rinwms_display2 done) => 
+ (python-call grass_message "** RHS: r.in.wms display cleanup **") 
+ (python-call grass_run_command d.mon stop=x0)
+ (assert (rinwms_display_shutdown done))
+)
+
+(defrule grassrun_rinwms_display4 (rinwms_display_shutdown done) => 
+  (python-call grass_message "** RHS: r.in.wms purge raster **") 
+  (python-call grass_run_command g.remove rast=rhs_srtm)
+  (assert (rinwms_gremove done))
+  )
+
+; g.remove akl_srtm.2
+; g.rename rast=akl_srtm.1,rhs_strm
+; r.colors rhs_srtm
+; d.mon d.rast
+; g.erase rhs_srtm
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; CLIPS TIME [WORKS]
+; Muss noch angeschaltet werden !
+
+
+;(defrule grassrun_timetest1 (timetest) => 
+; (python-call grass_message "** RHS: TIMETEST 1 **") (bind ?early (time)) (ginfer_printout t "Before" ?early) (assert (timetest1)) (assert (timestamp ?early)))
+
+;(defrule grassrun_timetest2 (timetest1) => 
+; (python-call grass_message "** RHS: TIMETEST 2 **") (bind ?wait (time)) (ginfer_printout t "Now" ?later crlf) (assert (timetest2)))
+
+;(defrule grassrun_timetest3 (timetest2) => 
+; (python-call grass_message "** RHS: TIMETEST 3 **") (bind ?later (time)) (ginfer_printout t "Now" ?later crlf) (assert (timetest done)))
+
+(deftemplate event (slot tstamp (default-dynamic (time))) (slot value))
+; A template for the time-activated rules.
+; Each instance consists of an automatically assigned timestamp and a user-assigned value
+
+(defrule timedemo0 (time demo) => 
+ (ginfer_printout t  " " crlf) 
+ (ginfer_printout t "==========================================================================" crlf) 
+ (ginfer_printout t "- CLIPS: Time-controlled Rule Demo" crlf)
+ (ginfer_printout t "  Added value: Rules can have expiry dates and duration...." clrf)
+ (ginfer_printout t  " " crlf) 
+ (assert (start-time (time)))
+)
+
+(defrule time0
+ (event (tstamp ?t1)(value 3))
+ =>
+ (ginfer_printout t "time0-rule: A value 3 event was detected. Its timestamp is=" ?t1 crlf)
+ )
+
+(defrule time1
+ ?foo <- (event (tstamp ?t1)(value 3))
+ ?now1 <- (time)
+ ;(test (> (- ?now1 ?t1) 0.01))
+ ;ES MAG ES NICHT WENN AUF DER LHS SCHON GETESTET WIRD ?!
+ =>
+ (retract ?foo)
+ (ginfer_printout t "time1-rule: Retracting" ?t1 ?now1 crlf)
+ )
+ 
+ (defrule time4
+ ?foo <- (event (tstamp ?t1)(value 3))
+ (start-time ?t2)
+ =>
+ 
+ (ginfer_printout t "time4-rule: There is Value 3 Event of time #1. Current time is #2:" ?t1 ?t2 crlf)
+ )
+
+(defrule time2
+ (time demo)
+  =>
+ (assert (event (value 3)))
+ (ginfer_printout t "time2-rule: Event of value 3 created at time=" (time) crlf)
+ )
+
+(defrule time3
+ ?foo <- (event (tstamp ?t1)(value 3))
+ (start-time ?t2)
+ ?now5 <- (time)
+ ;(test (> (- ?t1 ?t2) 0.01))
+ ;(test (> (- ?now5 ?t1) 0.01))
+ ;ES MAG ES NICHT WENN AUF DER LHS SCHON GETESTET WIRD ?!
+
+ =>
+ (retract ?foo)
+ (ginfer_printout t "time3-rule:  Value 3 Event has timestamp #1. Start time was #2. Now its #3 Retracting Event! " ?t1 ?t2 ?now5 crlf)
+ )
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+; RASTER MAPCALC [WORKS]
+
+;(assert (raster demo))
+
+(defrule grassrun_rmapcalc_random1 (raster demo) => (python-call grass_message "** RHS: r.mapcalc 1 **") (python-call grass_run_command "r.mapcalc" "rhs_mapcalc_1=rand(1,10)") (assert (mapcalc1 done)))
+
+(defrule grassrun_rmapcalc_random2 (raster demo) => (python-call grass_message "** RHS: r.mapcalc 2 **") (python-call grass_run_command "r.mapcalc" "rhs_mapcalc_2=rand(1,2)") (assert (mapcalc2 done)))
+
+; [r.surf.area] run
+
+; [r.null] run
+
+(defrule grassrun_rmapcalc1 (mapcalc1 done) (mapcalc2 done) => (python-call grass_message "** RHS: r.null **") (python-call grass_run_command r.null map=rhs_mapcalc_1 setnull=5) (assert (rnull done)))
+
+; [r.patch] run
+(defrule grassrun_rmapcalc2 (rnull done) => (python-call grass_message "** RHS: r.patch **") (python-call grass_run_command r.patch input=rhs_mapcalc_1,rhs_mapcalc_2 output=rhs_patch) (assert (rpatch done)))
+
+(defrule grassrun_rmapcalc3 (rpatch done) => (python-call grass_message "** RHS: r.stats **") (python-call grass_run_command r.stats "c" input=rhs_patch) (assert (rnull done)))
+
+
+
+;;;HIER FEHLT DIE VERKETTUNG ZU DEN FOLGENDEN RASTER-Subdemos
+
+(defrule grassrun_gremove (rnull done) => (python-call grass_message "[RASTER DEMO]** RHS: g.remove cleanup **") (python-call grass_run_command g.remove rast=rhs_patch,rhs_mapcalc_1,rhs_mapcalc_2) (assert (gremove done)))
+
+; [r.colors] run
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;
+; [r.stats] run
+;(defrule grassrun_rstats (verbose on) => (python-call grass_message "** RHS: r.stats run **") (python-call grass_run_command "r.stats" "cl" "input=geology" "fs=_"))
+
+; [r.quantile] read
+
+; [r.univar] read
+
+; [r.what] read
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;
+; [r.stats] read
+(defrule grassread_rstats (verbose on) => (python-call grass_message "** RHS: r.stats read **") (bind ?result (python-call grass_read_command "r.stats" "cl" "input=geology" "fs=_")) (ginfer_printout t "===========" crlf)(ginfer_printout t ?result) (ginfer_printout t "===========" crlf))
+
+
+;; export
+;; -- file r.out.gdal
+;; -- file r.in.gdal
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;## VECTOR
+
+;;
+;; v.in.external
+;; v.in.region
+;; v.random
+;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;(assert (vector demo))
+(defrule grassrun_vector1 
+ (vector demo) => 
+ (python-call grass_message "VECTOR DEMO:") 
+ (python-call grass_message "** v.random **")  
+ (python-call grass_run_command v.random output=rhs_random10 n=10) (assert (vrandom done))
+)
+
+(defrule grassrun_vector2 
+  (vrandom done) => 
+  (python-call grass_message "** v.info **") 
+  (python-call grass_run_command v.info map=rhs_random10) 
+  (assert (vinfo done)))
+
+(defrule grassrun_vector2a 
+  (vrandom done) => 
+  (python-call grass_message "** v.stats **") 
+ 
+  (python-call grass_run_command v.univar -ed map=rhs_random10)
+  (assert (vunivar done)))
+
+
+(defrule grassrun_vector3 
+  (vinfo done) (vunivar done) => 
+  (python-call grass_message "** g.remove vector **") 
+  (python-call grass_run_command g.remove vect=rhs_random10) (assert (gremove_vect done)))
+
+;; create empty vector
+;; v.in.ascii 
+;;
+;; create empty vector with structure
+;;
+;; query vector
+;; v.db.select READ
+;; v.db.univar READ
+;; v.distance
+;; v.normal
+;; v.univar READ
+;;
+;; modify vector ?
+;; v.db.addtable
+;; v.db.join
+;; v.db.update
+;; v.dissolve
+;; v.generalize
+;; v.patch
+;; v.type
+;; v.extract
+;;
+;; report on vector content
+;;
+;; report on vector topology
+;;
+;; convert vector (extract topo features)
+;;
+;;;; v.to.db
+;; v.to.r3
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+; R.mapcalc-like rule concatenation:
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;(assert (rmapcalc_rules demo))
+
+(defrule rmapcalc_rules_01 
+  (rmapcalc_rules demo) 
+ => 
+  (python-call grass_message "[rules like r.mapcalc] rule 01: Generate random GRASS raster by using r.mapcalc") 
+  (python-call grass_run_command "r.mapcalc" "rmapcalc_rules_demo=rand(1,10)") 
+  (assert (stages_mapcalc_01 done))
+)
+;Rule to create a new GRASS raster of random values
+
+(deftemplate rmapcalc_rules_demo (slot x)(slot y)(slot value))
+;Dummy template to ensure that the rules below will be parsed.
+
+;^^^ Damit gibts die Probleme !!!
+;**************************************
+;**************************************
+;**************************************
+
+(defrule rmapcalc_rules_02 
+  (stages_mapcalc_01 done) 
+ => 
+  (python-call grass_message "[rules like r.mapcalc] rule 02: Create CLIPS facts from GRASS raster layer") 
+  (python-call grassraster2factlayer "rmapcalc_rules_demo" "the_comment" True False) 
+  (assert (stages_ingest done))
+)
+;Rule import the new GRASS raster of random values into the CLIPS environment.
+
+;(defrule rmapcalc_rules_03_preparation 
+;  (stages_ingest done)
+;  (not (trigger ?x ?y))
+;  (not (completed ?x ?y))
+;  (rmapcalc_rules_demo (x ?x) (y ?y) (value ?value)) 
+;  ; DAS TEMPLATE wird erst angelegt wenn der GRASSRASTER_FACTLAYER eingeladen wird. Das ist nachdem diese Regel eingelesen wird.
+;  ;Ein Mechanismus wird gebraucht um das generisch zu loesen -> Anlegen des Template explizit hier im Skript....
+; => 
+;  (python-call grass_message "[rules like r.mapcalc] rule 03: Generate Flag-facts for raster facts")
+;  (assert (trigger ?x ?y))
+;)
+;; Rule to ensure that while for all facts created from the random raster layer there are (yet) no additional facs ("trigger"/"completed") sharing the same xy coordinate. While this applies (for all newly created raster-facts), an additional "trigger" fact is created for each coordinate tuple.
+
+;(defrule rmapcalc_rules_04_execution 
+;  ?thiscell <- (rmapcalc_rules_demo (x ?x) (y ?y) (value ?value)) 
+;  ?thistrigger <- (trigger ?x ?y) (not (completed ?x ?y)) 
+; => 
+;  (python-call grass_message "[rules like r.mapcalc] rule 04: Increase each raster facts by 1000000; flag as done")
+;  (modify ?thiscell (value (+ 100000 ?value))) 
+;  (retract ?thistrigger) 
+;  (assert (completed ?x ?y)))
+
+;;;^^^ IF (aka: FOR ANY) there's a coordinate/location where there's a raster-layer-fact and a "trigger"-fact but no "completed"-fact, increase/MODIFY the attribute of the raster fact, remove the "trigger" fact and set a "completed" fact.
+
+(undeftemplate rmapcalc_rules_demo)
+
+; bzw: zwei verfahrenswege: 
+; 1) einlesen, multiplikation * 10 im CLIPS space, export
+; 2) zweiter RHS-rmapcalc aufruf zur multiplikation
+; Zeiten vergleichen
+; -> wenn Mapcalc versagt kann option 1) greifen !
+
+
+
+	"""
+	return payload
+


Property changes on: grass-addons/grass6/general/g.infer/spearfish.py
___________________________________________________________________
Added: svn:executable
   + *



More information about the grass-commit mailing list