[GRASS-SVN] r57337 - in sandbox/turek/scatter_plot: . gui/wxpython/scatt_plot include include/defs lib/imagery

svn_grass at osgeo.org svn_grass at osgeo.org
Thu Aug 1 03:37:21 PDT 2013


Author: turek
Date: 2013-08-01 03:37:20 -0700 (Thu, 01 Aug 2013)
New Revision: 57337

Modified:
   sandbox/turek/scatter_plot/gui/wxpython/scatt_plot/controllers.py
   sandbox/turek/scatter_plot/gui/wxpython/scatt_plot/core_c.py
   sandbox/turek/scatter_plot/gui/wxpython/scatt_plot/dialogs.py
   sandbox/turek/scatter_plot/gui/wxpython/scatt_plot/plots.py
   sandbox/turek/scatter_plot/gui/wxpython/scatt_plot/sc_pl_core.py
   sandbox/turek/scatter_plot/include/defs/imagery.h
   sandbox/turek/scatter_plot/include/imagery.h
   sandbox/turek/scatter_plot/lib/imagery/scatt.c
   sandbox/turek/scatter_plot/lib/imagery/scatt_sccats.c
   sandbox/turek/scatter_plot/testing_patch.diff
Log:
scatter plot: new version optimization

Modified: sandbox/turek/scatter_plot/gui/wxpython/scatt_plot/controllers.py
===================================================================
--- sandbox/turek/scatter_plot/gui/wxpython/scatt_plot/controllers.py	2013-08-01 08:33:31 UTC (rev 57336)
+++ sandbox/turek/scatter_plot/gui/wxpython/scatt_plot/controllers.py	2013-08-01 10:37:20 UTC (rev 57337)
@@ -20,7 +20,7 @@
 
 from core.gcmd     import GException, GError, RunCommand
 
-from scatt_plot.sc_pl_core import Core, BandsToidScatt
+from scatt_plot.sc_pl_core import Core, idBandsToidScatt
 
 from scatt_plot.gthreading import gThread
 from core.gconsole         import EVT_CMD_DONE
@@ -65,7 +65,7 @@
             self.iclass_conn = None
 
         self.tasks_pids = {
-                            'add_scatt' : -1,
+                            'add_scatt' : [],
                             'set_data' : -1,
                             'set_edit_cat_data' : -1,
                             'mapwin_conn' : [],
@@ -79,6 +79,9 @@
         self.tasks_pids['set_data'] = self.thread.GetId()
         self.thread.Run(callable = self.core.SetData, bands = bands)
 
+        #for i in range(1):
+        #    self.AddScattPlot(i)
+
     def SetDataDone(self, event):
         self.data_set = True
         self.cats_mgr.InitCoreCats()
@@ -93,7 +96,7 @@
 
     def AddScattPlot(self, scatt_id):
 
-        self.tasks_pids['add_scatt'] = self.thread.GetId()
+        self.tasks_pids['add_scatt'].append(self.thread.GetId())
         self.thread.Run(callable = self.core.AddScattPlot, scatt_id = scatt_id)
 
     def RenderScattPlts(self):
@@ -117,11 +120,13 @@
         scatt_dt = self.scatts_dt.GetScatt(scatt_id)
         
         cats_attrs = self.cats_mgr.GetCategoriesAttrs()
+
         self.scatt_plts[scatt_id].Plot(scatt_dt, cats_attrs)
-
+        #for scatt in scatt_dt.itervalues():
+        #    del scatt 
         self.scatt_plts[scatt_id].GetParent().Show()
+        print "ok %d" % scatt_id
 
-
     def CleanUp(self):
         self.core.CleanUp()
 
@@ -156,7 +161,7 @@
             self.RenderScattPlts()
             return
             
-        if self.tasks_pids['add_scatt'] == event.pid:
+        if event.pid in self.tasks_pids['add_scatt']:
             self.AddScattPlotDone(event)
             return
 

Modified: sandbox/turek/scatter_plot/gui/wxpython/scatt_plot/core_c.py
===================================================================
--- sandbox/turek/scatter_plot/gui/wxpython/scatt_plot/core_c.py	2013-08-01 08:33:31 UTC (rev 57336)
+++ sandbox/turek/scatter_plot/gui/wxpython/scatt_plot/core_c.py	2013-08-01 10:37:20 UTC (rev 57337)
@@ -19,13 +19,15 @@
 try:
     from grass.lib.imagery import *
     from grass.lib.gis import Cell_head, G_get_window
+    #from grass.lib.raster import struct_Range
 
+
 except ImportError, e:
     sys.stderr.write(_("Loading imagery lib failed"))
 
 def ComputeScatts(region, scatt_conds, bands, n_bands, scatts, cats_rasts_in, cats_rasts_out):
 
-    #return _computeScattsProcess(region, scatt_conds, bands, n_bands, scatts, cats_rasts_in, cats_rasts_out)
+    return _computeScattsProcess(region, scatt_conds, bands, n_bands, scatts, cats_rasts_in, cats_rasts_out, None)
 
     # Queue object for interprocess communication
     q = Queue()
@@ -41,7 +43,7 @@
 
 def UpdateCatRast(patch_rast, region, cat_rast):
 
-    #return ComputeScattsProcess(region, scatt_conds, bands, n_bands, scatts, cats_rasts)
+    #return _computeScattsProcess(region, scatt_conds, bands, n_bands, scatts, cats_rasts, None)
     # Queue object for interprocess communication
 
     #_updateCatRastProcess(patch_rast, region, cat_rast, None)
@@ -73,19 +75,28 @@
     cell_head = _regionToCellHead(region)
 
     ret = I_compute_scatts(pointer(cell_head),
-                          pointer(scatt_conds_c),
-                          pointer(char_bands),
-                          n_bands,
-                          pointer(sccats_c),
-                          pointer(char_cats_rasts_in),
-                          pointer(char_cats_rasts_out))
+                           pointer(scatt_conds_c),
+                           pointer(char_bands),
+                           n_bands,
+                           pointer(sccats_c),
+                           pointer(char_cats_rasts_in),
+                           pointer(char_cats_rasts_out))
 
     I_sc_free_cats(pointer(sccats_c))
     I_sc_free_cats(pointer(scatt_conds_c))
 
-    output_queue.put((ret, scatts))
-    #return (ret, scatts)
+    #output_queue.put((ret, scatts))
+    return (ret, scatts)
 
+def _getBandcRange( band_info):
+    band_c_range = struct_Range()
+
+    band_c_range.max = band_info['max']
+    band_c_range.min = band_info['min']
+
+    return band_c_range
+
+
 def _regionToCellHead(region):
     cell_head = struct_Cell_head()
     G_get_window(pointer(cell_head))
@@ -138,24 +149,29 @@
             # if key is missing condition is always True (full scatter plor is computed)
             if cats[cat_id].has_key(scatt_id):
 
-                vals = dt["np_vals"]
-                #TODO hack
-                vals.shape = (256 * 256)
+                vals = dt['np_vals']
+                b1_info = dt['bands_info']['b1']
+                b2_info = dt['bands_info']['b2']
 
-                c_uint_p = ctypes.POINTER(ctypes.c_uint)
                 scatt_vals = scdScattData()
-                if cats_type == 0:
+
+                c_void_p = ctypes.POINTER(ctypes.c_void_p)
+
+                if cats_type == SC_SCATT_DATA:
                     vals[:] = 0
-                    scatt_vals.scatt_vals_arr = vals.ctypes.data_as(c_uint_p)
-
+                elif cats_type == SC_SCATT_CONDITIONS:
+                    pass
                 else:
-                    #TODO solve proble with short integer
-                    scatt_vals.b_conds_arr = vals.ctypes.data_as(c_uint_p)
+                    return None
 
+                b1_c_info = _getBandcRange(b1_info)
+                b2_c_info =_getBandcRange(b2_info)
+                data_p = vals.ctypes.data_as(c_void_p)
+                I_scd_init_scatt_data(pointer(scatt_vals), cats_type, len(vals), data_p, 
+                                      b1_c_info, b2_c_info)
+
                 vals_dt.append(scatt_vals)
 
-                #vals_dt.append(data_p)
-                vals.shape = (256, 256)
                 I_sc_insert_scatt_data(pointer(sccats),  
                                        pointer(scatt_vals),
                                        cat_id, scatt_id)

Modified: sandbox/turek/scatter_plot/gui/wxpython/scatt_plot/dialogs.py
===================================================================
--- sandbox/turek/scatter_plot/gui/wxpython/scatt_plot/dialogs.py	2013-08-01 08:33:31 UTC (rev 57336)
+++ sandbox/turek/scatter_plot/gui/wxpython/scatt_plot/dialogs.py	2013-08-01 10:37:20 UTC (rev 57337)
@@ -28,7 +28,7 @@
 
 from scatt_plot.controllers import ScattsManager
 from scatt_plot.toolbars    import MainToolbar, CategoriesToolbar
-from scatt_plot.sc_pl_core  import Core, BandsToidScatt
+from scatt_plot.sc_pl_core  import Core, idBandsToidScatt
 from scatt_plot.plots       import ScatterPlotWidget
 
 
@@ -213,7 +213,7 @@
 
 
         self._createWidgets()
-        self.group.SetValue("testovaci_1")
+        self.group.SetValue("B_sk")
 
     def _createWidgets(self):
 
@@ -439,7 +439,7 @@
             band_2 = band_1
             band_1 = band_2
 
-        self.scatt_id = BandsToidScatt(band_1, band_2, len(self.bands))
+        self.scatt_id = idBandsToidScatt(band_1, band_2, len(self.bands))
 
         event.Skip()
 

Modified: sandbox/turek/scatter_plot/gui/wxpython/scatt_plot/plots.py
===================================================================
--- sandbox/turek/scatter_plot/gui/wxpython/scatt_plot/plots.py	2013-08-01 08:33:31 UTC (rev 57336)
+++ sandbox/turek/scatter_plot/gui/wxpython/scatt_plot/plots.py	2013-08-01 10:37:20 UTC (rev 57337)
@@ -131,7 +131,7 @@
         """
       
         self.axes.clear()
-        for cat_id, cat in scatts.iteritems():
+        for cat_id, scatt in scatts.iteritems():
             if cat_id == 0:
                 cmap = matplotlib.cm.jet
                 cmap.set_bad('w',1.)
@@ -148,11 +148,25 @@
                 cmap._lut[:, 1] = int(colors[1])/255.0
                 cmap._lut[:, 2] = int(colors[2])/255.0
 
-            masked_cat = np.ma.masked_less_equal(cat, 0)
+            masked_cat = np.ma.masked_less_equal(scatt['np_vals'], 0)
 
-            self.axes.imshow(masked_cat, cmap = cmap,  interpolation='nearest')
 
+            b1_i = scatt['bands_info']['b1']
+            b2_i = scatt['bands_info']['b2']
+            
+            #self.axes.set_xlim((0, 270))
+            #self.axes.set_ylim((0, 270))
+            np.savetxt("/home/ostepok/Desktop/data.txt", scatt['np_vals'], fmt = '%d') 
+
+
+            #TODO needs optimization
+            img = self.axes.imshow(masked_cat, cmap = cmap,
+                                               origin = 'lower',
+                                               extent = (b1_i['min'] - 0.5, b1_i['max'] + 0.5, b2_i['min'] - 0.5, b2_i['max'] + 0.5), 
+                                               interpolation='nearest')
+            
             self.canvas.draw()
+
     
     def on_pick(self, event):
         pass

Modified: sandbox/turek/scatter_plot/gui/wxpython/scatt_plot/sc_pl_core.py
===================================================================
--- sandbox/turek/scatter_plot/gui/wxpython/scatt_plot/sc_pl_core.py	2013-08-01 08:33:31 UTC (rev 57336)
+++ sandbox/turek/scatter_plot/gui/wxpython/scatt_plot/sc_pl_core.py	2013-08-01 10:37:20 UTC (rev 57337)
@@ -15,6 +15,9 @@
 import os
 import sys
 
+#TODO
+import time
+
 import numpy as np
 
 from math import sqrt, ceil, floor
@@ -25,7 +28,8 @@
 
 import grass.script as grass
 
-from core_c import CreateCatRast, ComputeScatts, UpdateCatRast
+from core_c import CreateCatRast, ComputeScatts, UpdateCatRast, \
+                   SC_SCATT_DATA, SC_SCATT_CONDITIONS
 
 class Core:
     def __init__(self):
@@ -43,7 +47,7 @@
         n_bands = len(self.GetBands())
 
         self.scatts_dt.Create(n_bands)
-        self.scatt_conds_dt.Create(n_bands)        
+        self.scatt_conds_dt.Create(n_bands)
 
     def AddCategory(self, cat_id):
         self.scatts_dt.AddCategory(cat_id)
@@ -80,9 +84,16 @@
         cats_rasts_out = self.scatts_dt.GetCatsRastsOut()
         cats_rasts_in = self.scatts_dt.GetCatsRastsIn()
 
+
+        #for cat in scatts.itervalues():
+        #    for scatt_id in cat.itervalues():
+        #        print cat
+        #        scatt_id.values()[0].flush()
+        #        del scatt_id
+
         returncode, scatts = ComputeScatts(self.an_data.GetRegion(), scatt_conds, bands, 
                                            len(self.GetBands()), scatts, cats_rasts_in, cats_rasts_out)
-        self.scatts_dt.SetData(scatts)
+        #self.scatts_dt.SetData(scatts)
 
     def SetEditCatData(self, cat_id, scatt_id, bbox, value):
 
@@ -95,9 +106,13 @@
             bbox[k] = self._validExtend(v)
 
         arr[bbox['btm_y'] : bbox['up_y'], bbox['btm_x'] : bbox['up_x']] = value
+        arr.flush()
+        #del arr
 
+        start_time = time.clock()
         self.ComputeCatScatts([cat_id])
-
+        print "time"
+        print time.clock() - start_time
         return True
 
     def ComputeCatScatts(self, cats_ids):
@@ -120,7 +135,7 @@
         returncode, scatts = ComputeScatts(self.an_data.GetRegion(), scatt_conds, bands,
                                            len(self.GetBands()), scatts, cats_rasts_in, cats_rasts_out)
         
-        self.scatts_dt.SetData(scatts)
+        #self.scatts_dt.SetData(scatts)
 
     def CatRastUpdater(self):
         return self.cat_rast_updater
@@ -193,8 +208,8 @@
     def DeletedAreas(self, old_geoms, old_areas_cats):
 
         updated_cats = []
-        for i in range(len(old_geoms)):
-            self._updateCatRast(old_geoms[i], old_areas_cats[i], updated_cats)
+        #for i in range(len(old_geoms)):
+        #    self._updateCatRast(old_geoms[i], old_areas_cats[i], updated_cats)
 
         return updated_cats
 
@@ -323,17 +338,16 @@
 
     def __init__(self):
         
-        self.bands = None
-        self.bin_bands_f = []      
+        self.bands = []
+        self.bands_info = {}
 
-        self.region = {}
+        self.region = None
 
     def GetRegion(self):
         return self.region
 
     def Create(self, bands):
 
-        self.bands = None
         self.bands = bands
         self.region = None
 
@@ -345,11 +359,53 @@
         if  ret != 0:
             raise GException("g.region failed:\n%s" % msg)
 
+
+        self.bands_info = {}
+        for b in bands:
+            self.bands_info[b] = self._getRasterInfo(b)
+            if self.bands_info[b]["datatype"] != "CELL":
+                raise GException(_("Raster <%s> is not <CELL> type.") % (b))
+            #TODO size of raster check
+
         self.region = self._parseRegion(region)
 
+    def _getRasterInfo(self, rast):
+        """
+        """
+        ret, out, msg = RunCommand("r.info",
+                                    map = rast,
+                                    flags = "rg",
+                                    getErrorMsg = True,
+                                    read = True)
+
+        if  ret != 0:
+            raise GException("r.info failed:\n%s" % msg)
+
+        out = out.split("\n")
+        raster_info = {} 
+
+        for b in out:
+            if not b.strip():
+                continue
+            k, v = b.split("=")
+            if k == "datatype":
+                pass
+            elif k in ['rows', 'cols', 'cells', 'min', 'max']:
+                v = int(v)
+            else:
+                v = float(v)
+
+            raster_info[k] = v
+
+        return raster_info
+
     def GetBands(self):
         return self.bands
 
+    def GetBandInfo(self, band_id):
+        band = self.bands[band_id]
+        return self.bands_info[band]
+
     def _parseRegion(self, region_str):
 
         region = {}
@@ -371,10 +427,10 @@
 
         self.an_data = an_data
 
+        #TODO
         self.max_n_cats = 10
     
-        self.vals = 256 * 256
-
+        self.dtype = 'uint8'
         self.type = 1;
         self.CleanUp()
 
@@ -432,22 +488,30 @@
         if self.cats[cat_id].has_key(scatt_id):
             return 0
 
-        if self.type == 0:
-            np_vals = np.zeros(self.vals, dtype = 'uint32')
-        elif self.type == 1:
-            #TODO solve proble with short
-            np_vals = np.zeros(self.vals, dtype = 'uint32')
-        else:
-            return -1
+        b_i = self.GetBandsInfo(scatt_id)
 
-        np_vals.shape = (256, 256)#TODO hack do it general
+        shape = (b_i['b2']['max'] - b_i['b2']['min'] + 1, b_i['b1']['max'] - b_i['b1']['min'] + 1)
 
+        np_vals = np.memmap(grass.tempfile(), dtype=self.dtype, mode='w+', shape = shape)
+        np_vals.flush()
+
         self.cats[cat_id][scatt_id] = {
                                         'np_vals' : np_vals
                                       }
 
         return 1
 
+    def GetBandsInfo(self, scatt_id):
+        b1, b2 = idScattToidBands(scatt_id, len(self.an_data.GetBands()))
+
+        b1_info = self.an_data.GetBandInfo(b1)
+        b2_info = self.an_data.GetBandInfo(b2)
+
+        bands_info = {'b1' : b1_info,
+                      'b2' : b2_info}
+
+        return bands_info
+
     def DeleScattPlot(self, cat_id, scatt_id):
 
         if not self.cats.has_key(cat_id):
@@ -478,7 +542,8 @@
             for scatt_id in scatt_ids:
                 # if key is missing condition is always True (full scatter plor is computed)
                 if self.cats[cat_id].has_key(scatt_id):
-                    cats[cat_id][scatt_id] = {'np_vals' : self.cats[cat_id][scatt_id]['np_vals']}
+                    cats[cat_id][scatt_id] = {'np_vals' : self.cats[cat_id][scatt_id]['np_vals'],
+                                              'bands_info' : self.GetBandsInfo(scatt_id)}
                         
         return cats
 
@@ -500,6 +565,8 @@
 
         ScattPlotsCondsData.__init__(self, an_data)
 
+        self.dtype = 'uint32'
+
         #TODO
         self.type = 0
 
@@ -564,8 +631,8 @@
 
         scatts = {}
         for cat_id in self.cats.iterkeys():
-            scatts[cat_id] = self.cats[cat_id][scatt_id]['np_vals']
-
+            scatts[cat_id] = {'np_vals' : self.cats[cat_id][scatt_id]['np_vals'],
+                              'bands_info' : self.GetBandsInfo(scatt_id)}
         return scatts
 
     def CleanUp(self):
@@ -604,7 +671,7 @@
         return cats_rasts_out
 
 #TODO move to utils?
-def idScattToBands(scatt_id, n_bands):
+def idScattToidBands(scatt_id, n_bands):
  
     n_b1 = n_bands - 1
 
@@ -615,17 +682,16 @@
     return band_1, band_2
 
 
-def BandsToidScatt(band_1, band_2, n_bands):
+def idBandsToidScatt(band_1_id, band_2_id, n_bands):
 
-    if band_2 <  band_1:
+    if band_2_id <  band_1_id:
         tmp = band_1
-        band_1 = band_2
-        band_2 = tmp
+        band_1_id = band_2_id
+        band_2_id = tmp
 
-
     n_b1 = n_bands - 1
 
-    scatt_id = (band_1 * (2 * n_b1 + 1) - band_1 * band_1) / 2 + band_2 - band_1 - 1
+    scatt_id = (band_1_id * (2 * n_b1 + 1) - band_1_id * band_1_id) / 2 + band_2_id - band_1_id - 1
 
     return scatt_id
 

Modified: sandbox/turek/scatter_plot/include/defs/imagery.h
===================================================================
--- sandbox/turek/scatter_plot/include/defs/imagery.h	2013-08-01 08:33:31 UTC (rev 57336)
+++ sandbox/turek/scatter_plot/include/defs/imagery.h	2013-08-01 10:37:20 UTC (rev 57337)
@@ -120,9 +120,9 @@
 int I_sc_remove_scatt_data(struct scCats *, struct scdScattData *, int, int);
 int I_sc_set_value(struct scCats *, int, int, int, int);
 
-void I_scd_init_scatt_data(struct scdScattData *, int, int);
+void I_scd_init_scatt_data(struct scdScattData *, int, int, void *, struct Range, struct Range);
 void I_scd_free_scatt_data(struct scdScattData *);
-int I_scd_get_data_size(struct scdScattData *);
+void I_scd_get_range_min_max(struct scdScattData *, CELL *, CELL *, CELL *, CELL *);
 void * I_scd_get_data_ptr(struct scdScattData *);
 int I_scd_set_value(struct scdScattData *, unsigned int, unsigned int);
 

Modified: sandbox/turek/scatter_plot/include/imagery.h
===================================================================
--- sandbox/turek/scatter_plot/include/imagery.h	2013-08-01 08:33:31 UTC (rev 57336)
+++ sandbox/turek/scatter_plot/include/imagery.h	2013-08-01 10:37:20 UTC (rev 57337)
@@ -155,18 +155,25 @@
 struct scScatts
 {
     int n_a_scatts;
-
+    
     int * scatts_bands;
     int * scatt_idxs;
 
     struct scdScattData ** scatts_arr;
 };
 
+#define SC_SCATT_DATA          0 
+#define SC_SCATT_CONDITIONS    1
+
 struct scdScattData
 {
-    int n_vals;
-    //TODO void pointer???
-    unsigned int  * b_conds_arr;
+    int n_vals; //TODO delete???
+    
+    struct Range band_1_range;
+    struct Range band_2_range;
+
+
+    unsigned char  * b_conds_arr;
     unsigned int  * scatt_vals_arr;
 };
 

Modified: sandbox/turek/scatter_plot/lib/imagery/scatt.c
===================================================================
--- sandbox/turek/scatter_plot/lib/imagery/scatt.c	2013-08-01 08:33:31 UTC (rev 57336)
+++ sandbox/turek/scatter_plot/lib/imagery/scatt.c	2013-08-01 10:37:20 UTC (rev 57337)
@@ -231,22 +231,31 @@
 
 static inline void update_cat_scatt_plt(CELL ** chunks, char ** null_chunks, int chunk_size, unsigned short * belongs_pix, struct scScatts * scatts)
 {
-    int band_axis_1, band_axis_2, i_scatt, array_idx, cat_idx, i_chunks_pix;
-    int r_bits = 256;
+    int band_axis_1, band_axis_2, i_scatt, array_idx, cat_idx, i_chunks_pix, max_arr_idx;
 
-    CELL * band_1_chunks;
-    CELL * band_2_chunks;
+    CELL * b_1_chunks;
+    CELL * b_2_chunks;
     char * band_1_null_chunks,* band_2_null_chunks;
 
+    struct Range b_1_range, b_2_range;
+    int b_1_range_size;
+
     int * scatts_bands = scatts->scatts_bands;
+
     for(i_scatt = 0; i_scatt < scatts->n_a_scatts; i_scatt++)
     {   
-        band_1_chunks = chunks[scatts_bands[i_scatt * 2]];
-        band_2_chunks = chunks[scatts_bands[i_scatt * 2 + 1]];
+        b_1_chunks = chunks[scatts_bands[i_scatt * 2]];
+        b_2_chunks = chunks[scatts_bands[i_scatt * 2 + 1]];
 
         band_1_null_chunks =  null_chunks[scatts_bands[i_scatt * 2]];
         band_2_null_chunks =  null_chunks[scatts_bands[i_scatt * 2 + 1]];
 
+        b_1_range = scatts->scatts_arr[i_scatt]->band_1_range;
+        b_2_range = scatts->scatts_arr[i_scatt]->band_2_range;
+
+        b_1_range_size = b_1_range.max - b_1_range.min + 1;
+        max_arr_idx = (b_1_range.max -  b_1_range.min + 1) * (b_2_range.max -  b_2_range.min + 1);
+
         for(i_chunks_pix = 0; i_chunks_pix < chunk_size; i_chunks_pix++)
         {
             if(!belongs_pix[i_chunks_pix] || 
@@ -254,8 +263,12 @@
                 band_2_null_chunks[i_chunks_pix] == 1)                
                 continue;
 
-            array_idx = band_1_chunks[i_chunks_pix] + band_2_chunks[i_chunks_pix] * r_bits;
+            array_idx = b_1_chunks[i_chunks_pix] - b_1_range.min + (b_2_chunks[i_chunks_pix] - b_2_range.min) * b_1_range_size;
 
+            if(array_idx < 0 || array_idx >= max_arr_idx) {
+                G_warning ("pixel out of range");
+                continue;
+            }
             ++scatts->scatts_arr[i_scatt]->scatt_vals_arr[array_idx];
         }
     }
@@ -267,21 +280,22 @@
 {
 
     int i_chunks_pix, i_cat, i_scatt, n_a_scatts, i_cond;
-    int cat_id, scatt_plts_cat_idx, array_idx;
+    int cat_id, scatt_plts_cat_idx, array_idx, max_arr_idx;
     char * band_1_null_chunks,* band_2_null_chunks;
     
-    int r_bits = 256;
-
     struct scScatts * scatts_conds;
     struct scScatts * scatt_plts_scatts;
     struct scdScattData * conds;
 
+    struct Range b_1_range, b_2_range;
+    int b_1_range_size;
+
     int * scatts_bands;
     struct scdScattData ** scatts_arr;
 
-    CELL * band_1_chunks;
-    CELL * band_2_chunks;
-    unsigned int * i_scatt_conds;
+    CELL * b_1_chunks;
+    CELL * b_2_chunks;
+    unsigned char * i_scatt_conds;
 
     unsigned short * belongs_pix = (unsigned short *) G_malloc(chunk_size * sizeof(unsigned short)); 
     unsigned char * rast_pixs = (unsigned char *) G_malloc(chunk_size * sizeof(unsigned char));
@@ -330,14 +344,22 @@
             // test every defined conditions in scatter plots
             for(i_scatt = 0; i_scatt < scatts_conds->n_a_scatts; i_scatt++)
             {   
-                band_1_chunks =  chunks[scatts_bands[i_scatt * 2]];
-                band_2_chunks =  chunks[scatts_bands[i_scatt * 2 + 1]];
+                b_1_chunks =  chunks[scatts_bands[i_scatt * 2]];
+                b_2_chunks =  chunks[scatts_bands[i_scatt * 2 + 1]];
 
                 band_1_null_chunks =  null_chunks[scatts_bands[i_scatt * 2]];
                 band_2_null_chunks =  null_chunks[scatts_bands[i_scatt * 2 + 1]];
 
                 i_scatt_conds = scatts_conds->scatts_arr[i_scatt]->b_conds_arr;
 
+                b_1_range = scatts_conds->scatts_arr[i_scatt]->band_1_range;
+                b_2_range = scatts_conds->scatts_arr[i_scatt]->band_2_range;
+
+                b_1_range_size = b_1_range.max - b_1_range.min + 1;
+
+                max_arr_idx = (b_1_range.max -  b_1_range.min + 1) * (b_2_range.max -  b_2_range.min + 1);
+                //G_message("max_arr_idx scatt_conds: %d", max_arr_idx);
+
                 for(i_chunks_pix = 0; i_chunks_pix < chunk_size; i_chunks_pix++)
                 {
                     if(belongs_pix[i_chunks_pix] || 
@@ -345,7 +367,13 @@
                        band_2_null_chunks[i_chunks_pix] == 1)
                         continue;
 
-                    if(i_scatt_conds[band_1_chunks[i_chunks_pix] + band_2_chunks[i_chunks_pix] * r_bits])
+                    array_idx = b_1_chunks[i_chunks_pix] - b_1_range.min + (b_2_chunks[i_chunks_pix] - b_2_range.min) * b_1_range_size;
+                    /*TODO test value */
+                    if(array_idx < 0 || array_idx >= max_arr_idx) {
+                        G_warning ("pixel out of range");
+                        continue;
+                    }
+                    if(i_scatt_conds[array_idx])
                         belongs_pix[i_chunks_pix] = 1;
                 }                
             }

Modified: sandbox/turek/scatter_plot/lib/imagery/scatt_sccats.c
===================================================================
--- sandbox/turek/scatter_plot/lib/imagery/scatt_sccats.c	2013-08-01 08:33:31 UTC (rev 57336)
+++ sandbox/turek/scatter_plot/lib/imagery/scatt_sccats.c	2013-08-01 10:37:20 UTC (rev 57337)
@@ -162,7 +162,7 @@
 }
     
 
-int I_sc_insert_scatt_data(struct scCats * cats, struct scdScattData * scatt_vals, int cat_id, int scatt_id)
+int I_sc_insert_scatt_data(struct scCats * cats, struct scdScattData * scatt_data, int cat_id, int scatt_id)
 {
     int band_1, band_2, cat_idx, n_a_scatts;
     struct scScatts * scatts;
@@ -181,10 +181,10 @@
     if(scatts->scatt_idxs[scatt_id] >= 0)
         return -1;
 
-    if(!scatt_vals->b_conds_arr && cats->type == 1)
+    if(!scatt_data->b_conds_arr && cats->type == SC_SCATT_CONDITIONS)
         return -1;
 
-    if(!scatt_vals->scatt_vals_arr && cats->type == 0)
+    if(!scatt_data->scatt_vals_arr && cats->type == SC_SCATT_DATA)
         return -1;
 
     n_a_scatts = scatts->n_a_scatts;
@@ -196,13 +196,13 @@
     scatts->scatts_bands[n_a_scatts * 2] = band_1;
     scatts->scatts_bands[n_a_scatts * 2 + 1] = band_2;
 
-    scatts->scatts_arr[n_a_scatts] = scatt_vals;
+    scatts->scatts_arr[n_a_scatts] = scatt_data;
     ++scatts->n_a_scatts;
 
     return 0;
 }
 
-int I_sc_remove_scatt_data(struct scCats * cats, struct scdScattData * scatt_vals, int cat_id, int scatt_id)
+int I_sc_remove_scatt_data(struct scCats * cats, struct scdScattData * scatt_data, int cat_id, int scatt_id)
 {
     int cat_idx, scatt_idx, n_init_scatts, i_scatt;
     struct scScatts * scatts;
@@ -221,7 +221,7 @@
     if(scatts->scatt_idxs[scatt_id] < 0)
         return -1;
 
-    scatt_vals = scatts->scatts_arr[scatt_idx];
+    scatt_data = scatts->scatts_arr[scatt_idx];
 
     for(i_scatt = scatt_idx; i_scatt < scatts->n_a_scatts - 1; i_scatt++)
     {
@@ -233,7 +233,7 @@
 
     scatts->scatt_idxs[scatt_id] = -1;
 
-    scatt_vals = scatts->scatts_arr[scatt_id];
+    scatt_data = scatts->scatts_arr[scatt_id];
     scatts->n_a_scatts--;
 
     return 0;
@@ -259,61 +259,82 @@
     return 0;
 }
 
-void I_scd_init_scatt_data(struct scdScattData * scatt_vals, int n_vals, int type)
+void I_scd_init_scatt_data(struct scdScattData * scatt_data, int type, int n_vals, void * data, 
+                           struct Range band_1_range, struct Range band_2_range)
 {
-    scatt_vals->n_vals = n_vals;
+    scatt_data->n_vals = n_vals;
 
-    if(type == 0)
+    scatt_data->band_1_range.min = band_1_range.min;
+    scatt_data->band_1_range.max = band_1_range.max;
+    scatt_data->band_1_range.first_time = 0;
+
+    scatt_data->band_2_range.min = band_2_range.min;
+    scatt_data->band_2_range.max = band_2_range.max;
+    scatt_data->band_2_range.first_time = 0;
+
+    if(type == SC_SCATT_DATA)
     {   
-        scatt_vals->scatt_vals_arr = (unsigned int *) malloc(n_vals * sizeof(unsigned int));
-        memset(scatt_vals->scatt_vals_arr, 0, n_vals * sizeof(unsigned int));
-        scatt_vals->b_conds_arr = NULL;
+        if(data)
+            scatt_data->scatt_vals_arr = (unsigned int *) data;
+        else {
+            scatt_data->scatt_vals_arr = (unsigned int *) malloc(n_vals * sizeof(unsigned int));
+            memset(scatt_data->scatt_vals_arr, 0, n_vals * sizeof(unsigned int)); 
+        }
+        scatt_data->b_conds_arr = NULL;
     }
-    else if(type == 1)
-    {   
-        scatt_vals->b_conds_arr = (unsigned short *) malloc(n_vals * sizeof(unsigned short));
-        memset(scatt_vals->b_conds_arr, 0, n_vals * sizeof(unsigned short));
-        scatt_vals->scatt_vals_arr = NULL;
+    else if(type == SC_SCATT_CONDITIONS)
+    {
+        if(data)
+            scatt_data->b_conds_arr = (unsigned char *) data;
+        else {
+            scatt_data->b_conds_arr = (unsigned char *) malloc(n_vals * sizeof(unsigned char));
+            memset(scatt_data->b_conds_arr, 0, n_vals * sizeof(unsigned char));
+        }
+        scatt_data->scatt_vals_arr = NULL;
     }
 
     return;
 }
 
-void I_scd_free_scatt_data(struct scdScattData * scatt_vals)
+void I_scd_free_scatt_data(struct scdScattData * scatt_data)
 {
 
-    free(scatt_vals->b_conds_arr);
-    free(scatt_vals->scatt_vals_arr);
+    free(scatt_data->b_conds_arr);
+    free(scatt_data->scatt_vals_arr);
 
-    scatt_vals = NULL;
+    scatt_data = NULL;
 
     return;
 }
 
-int I_scd_get_data_size(struct scdScattData * scatt_vals)
+void I_scd_get_range_min_max(struct scdScattData * scatt_data, CELL * band_1_min, CELL * band_1_max, CELL * band_2_min, CELL * band_2_max)
 {
-    return scatt_vals->n_vals;
+
+    Rast_get_range_min_max(&(scatt_data->band_1_range), band_1_min, band_2_min);
+    Rast_get_range_min_max(&(scatt_data->band_2_range), band_2_min, band_2_max);
+
+    return;
 }
 
-void * I_scd_get_data_ptr(struct scdScattData * scatt_vals)
+void * I_scd_get_data_ptr(struct scdScattData * scatt_data)
 {
-    if(!scatt_vals->b_conds_arr)
-        return scatt_vals->b_conds_arr;
-    else if(!scatt_vals->scatt_vals_arr)
-        return scatt_vals->scatt_vals_arr;
+    if(!scatt_data->b_conds_arr)
+        return scatt_data->b_conds_arr;
+    else if(!scatt_data->scatt_vals_arr)
+        return scatt_data->scatt_vals_arr;
 
     return NULL;
 }
 
-int I_scd_set_value(struct scdScattData * scatt_vals, unsigned int val_idx, unsigned int val)
+int I_scd_set_value(struct scdScattData * scatt_data, unsigned int val_idx, unsigned int val)
 {
-    if(val_idx < 0 && val_idx >  scatt_vals->n_vals)
+    if(val_idx < 0 && val_idx >  scatt_data->n_vals)
         return -1;
 
-    if(scatt_vals->b_conds_arr)
-        scatt_vals->b_conds_arr[val_idx] = val;
-    else if(scatt_vals->scatt_vals_arr)
-        scatt_vals->scatt_vals_arr[val_idx] = val;
+    if(scatt_data->b_conds_arr)
+        scatt_data->b_conds_arr[val_idx] = val;
+    else if(scatt_data->scatt_vals_arr)
+        scatt_data->scatt_vals_arr[val_idx] = val;
     else
         return -1;
 

Modified: sandbox/turek/scatter_plot/testing_patch.diff
===================================================================
--- sandbox/turek/scatter_plot/testing_patch.diff	2013-08-01 08:33:31 UTC (rev 57336)
+++ sandbox/turek/scatter_plot/testing_patch.diff	2013-08-01 10:37:20 UTC (rev 57337)
@@ -1,6 +1,6 @@
 Index: vector/v.edit/main.c
 ===================================================================
---- vector/v.edit/main.c	(revision 57285)
+--- vector/v.edit/main.c	(revision 57336)
 +++ vector/v.edit/main.c	(working copy)
 @@ -299,7 +299,7 @@
  	move_z = atof(params.move->answers[2]);
@@ -32,9 +32,9 @@
      case MODE_BREAK:
 Index: include/imagery.h
 ===================================================================
---- include/imagery.h	(revision 57285)
+--- include/imagery.h	(revision 57336)
 +++ include/imagery.h	(working copy)
-@@ -135,6 +135,41 @@
+@@ -135,6 +135,48 @@
      
  } IClass_statistics;
  
@@ -58,27 +58,68 @@
 +struct scScatts
 +{
 +    int n_a_scatts;
-+
++    
 +    int * scatts_bands;
 +    int * scatt_idxs;
 +
 +    struct scdScattData ** scatts_arr;
 +};
 +
++#define SC_SCATT_DATA          0 
++#define SC_SCATT_CONDITIONS    1
++
 +struct scdScattData
 +{
-+    int n_vals;
-+    //TODO void pointer???
-+    unsigned int  * b_conds_arr;
++    int n_vals; //TODO delete???
++    
++    struct Range band_1_range;
++    struct Range band_2_range;
++
++
++    unsigned char  * b_conds_arr;
 +    unsigned int  * scatt_vals_arr;
 +};
 +
  #define SIGNATURE_TYPE_MIXED 1
  
  #define GROUPFILE "CURGROUP"
+Index: include/defs/imagery.h
+===================================================================
+--- include/defs/imagery.h	(revision 57336)
++++ include/defs/imagery.h	(working copy)
+@@ -110,6 +110,29 @@
+ FILE *I_fopen_subgroup_ref_new(const char *, const char *);
+ FILE *I_fopen_subgroup_ref_old(const char *, const char *);
+ 
++/* scatt_plt.c */
++void I_sc_init_cats(struct scCats *, int, int);
++void I_sc_free_cats(struct scCats *);
++void I_sc_get_active_categories(int *, int *, struct scCats *);
++int I_sc_add_cat(struct scCats *, int);
++int I_sc_delete_cat(struct scCats *, int);
++int I_sc_insert_scatt_data(struct scCats *, struct scdScattData *, int, int);
++int I_sc_remove_scatt_data(struct scCats *, struct scdScattData *, int, int);
++int I_sc_set_value(struct scCats *, int, int, int, int);
++
++void I_scd_init_scatt_data(struct scdScattData *, int, int, void *, struct Range, struct Range);
++void I_scd_free_scatt_data(struct scdScattData *);
++void I_scd_get_range_min_max(struct scdScattData *, CELL *, CELL *, CELL *, CELL *);
++void * I_scd_get_data_ptr(struct scdScattData *);
++int I_scd_set_value(struct scdScattData *, unsigned int, unsigned int);
++
++int I_compute_scatts(struct Cell_head *, struct scCats *, const char **, 
++                     int, struct scCats *, const char **,  const char **);
++
++int I_create_cat_rast(struct Cell_head *, const char *);
++int I_insert_patch_to_cat_rast(const char *, struct Cell_head *,  const char *);
++
++
+ /* sig.c */
+ int I_init_signatures(struct Signature *, int);
+ int I_new_signature(struct Signature *);
 Index: include/defs/vedit.h
 ===================================================================
---- include/defs/vedit.h	(revision 57285)
+--- include/defs/vedit.h	(revision 57336)
 +++ include/defs/vedit.h	(working copy)
 @@ -34,7 +34,7 @@
  
@@ -104,45 +145,534 @@
  
  /* zbulk.c */
  int Vedit_bulk_labeling(struct Map_info *, struct ilist *,
-Index: include/defs/imagery.h
+Index: gui/wxpython/scatt_plot/controllers.py
 ===================================================================
---- include/defs/imagery.h	(revision 57285)
-+++ include/defs/imagery.h	(working copy)
-@@ -110,6 +110,29 @@
- FILE *I_fopen_subgroup_ref_new(const char *, const char *);
- FILE *I_fopen_subgroup_ref_old(const char *, const char *);
- 
-+/* scatt_plt.c */
-+void I_sc_init_cats(struct scCats *, int, int);
-+void I_sc_free_cats(struct scCats *);
-+void I_sc_get_active_categories(int *, int *, struct scCats *);
-+int I_sc_add_cat(struct scCats *, int);
-+int I_sc_delete_cat(struct scCats *, int);
-+int I_sc_insert_scatt_data(struct scCats *, struct scdScattData *, int, int);
-+int I_sc_remove_scatt_data(struct scCats *, struct scdScattData *, int, int);
-+int I_sc_set_value(struct scCats *, int, int, int, int);
+--- gui/wxpython/scatt_plot/controllers.py	(revision 0)
++++ gui/wxpython/scatt_plot/controllers.py	(working copy)
+@@ -0,0 +1,518 @@
++"""!
++ at package scatt_plot.controllers
 +
-+void I_scd_init_scatt_data(struct scdScattData *, int, int);
-+void I_scd_free_scatt_data(struct scdScattData *);
-+int I_scd_get_data_size(struct scdScattData *);
-+void * I_scd_get_data_ptr(struct scdScattData *);
-+int I_scd_set_value(struct scdScattData *, unsigned int, unsigned int);
++ at brief Controller layer for scatter plot tool.
 +
-+int I_compute_scatts(struct Cell_head *, struct scCats *, const char **, 
-+                     int, struct scCats *, const char **,  const char **);
++Classes:
 +
-+int I_create_cat_rast(struct Cell_head *, const char *);
-+int I_insert_patch_to_cat_rast(const char *, struct Cell_head *,  const char *);
++(C) 2013 by the GRASS Development Team
 +
++This program is free software under the GNU General Public License
++(>=v2). Read the file COPYING that comes with GRASS for details.
 +
- /* sig.c */
- int I_init_signatures(struct Signature *, int);
- int I_new_signature(struct Signature *);
++ at author Stepan Turek <stepan.turek seznam.cz> (mentor: Martin Landa)
++"""
++import os
++import sys
++
++#TODO
++import wx
++
++from core.gcmd     import GException, GError, RunCommand
++
++from scatt_plot.sc_pl_core import Core, idBandsToidScatt
++
++from scatt_plot.gthreading import gThread
++from core.gconsole         import EVT_CMD_DONE
++
++from grass.pydispatch.signal import Signal
++
++class ScattsManager(wx.EvtHandler):
++    def __init__(self, guiparent, giface, iclass_mapwin):
++        #TODO remove iclass parameter
++
++        wx.EvtHandler.__init__(self)
++        self.giface = giface
++        self.mapDisp  = giface.GetMapDisplay()
++        self.mapWin = giface.GetMapWindow()
++
++        if iclass_mapwin:
++            self.mapWin = iclass_mapwin
++
++        self.guiparent = guiparent
++
++        self.core = Core()
++        self.scatts_dt = self.core.GetScattsData()
++
++        self.cats_mgr = CategoriesManager(self, self.core)
++
++        self.thread = gThread(self);
++        
++        self.scatt_plts = {}
++        self.added_cats_rasts = {}
++
++        self.cats_to_update = []
++
++        self.edit_cat_type =  None
++
++        self.data_set = False
++
++        if iclass_mapwin: 
++            self.mapWin_conn = MapWinConnection(self, self.mapWin, self.core.CatRastUpdater())
++            self.iclass_conn = IClassConnection(self, iclass_mapwin.parent, self.cats_mgr)
++        else:
++            self.mapWin_conn = None
++            self.iclass_conn = None
++
++        self.tasks_pids = {
++                            'add_scatt' : [],
++                            'set_data' : -1,
++                            'set_edit_cat_data' : -1,
++                            'mapwin_conn' : [],
++                            'render_plots' : -1
++                           }
++
++        self.Bind(EVT_CMD_DONE, self.OnThreadDone)
++
++    def SetData(self, bands):
++        self.data_set = False
++        self.tasks_pids['set_data'] = self.thread.GetId()
++        self.thread.Run(callable = self.core.SetData, bands = bands)
++
++        #for i in range(1):
++        #    self.AddScattPlot(i)
++
++    def SetDataDone(self, event):
++        self.data_set = True
++        self.cats_mgr.InitCoreCats()
++
++    def OnOutput(self, event):
++        """!Print thread output according to debug level.
++        """
++        print event.text
++
++    def GetBands(self):
++        return self.core.GetBands()
++
++    def AddScattPlot(self, scatt_id):
++
++        self.tasks_pids['add_scatt'].append(self.thread.GetId())
++        self.thread.Run(callable = self.core.AddScattPlot, scatt_id = scatt_id)
++
++    def RenderScattPlts(self):
++
++        cats_attrs = self.cats_mgr.GetCategoriesAttrs()
++        for scatt_id, scatt in self.scatt_plts.iteritems():
++            scatt_dt = self.scatts_dt.GetScatt(scatt_id)
++            scatt.Plot(scatt_dt, cats_attrs)
++
++
++    def AddScattPlotDone(self, event):
++        
++        scatt_id = event.kwds['scatt_id']
++
++        #TODO guiparent - not very good
++        self.scatt_plts[scatt_id] = self.guiparent.NewScatterPlot(scatt_id = scatt_id)
++
++        if self.edit_cat_type:
++            self.scatt_plts[scatt_id].StartCategoryEdit()
++
++        scatt_dt = self.scatts_dt.GetScatt(scatt_id)
++        
++        cats_attrs = self.cats_mgr.GetCategoriesAttrs()
++
++        self.scatt_plts[scatt_id].Plot(scatt_dt, cats_attrs)
++        #for scatt in scatt_dt.itervalues():
++        #    del scatt 
++        self.scatt_plts[scatt_id].GetParent().Show()
++        print "ok %d" % scatt_id
++
++    def CleanUp(self):
++        self.core.CleanUp()
++
++        for scatt_id, scatt in self.scatt_plts.items():
++            scatt.CleanUp()
++            del self.scatt_plts[scatt_id]
++
++    def OnThreadDone(self, event):
++        
++        if event.exception:
++            GError(str(event.exception))
++            return
++
++        if event.pid in self.tasks_pids['mapwin_conn']:
++            self.tasks_pids['mapwin_conn'].remove(event.pid)
++            updated_cats = event.ret
++
++            for cat in updated_cats:
++                if cat not in  self.cats_to_update:
++                    self.cats_to_update.append(cat)
++
++            if not self.tasks_pids['mapwin_conn']:
++                self.tasks_pids['render_plots'] = self.thread.GetId()
++                self.thread.Run(callable = self.core.ComputeCatScatts, 
++                                cats_ids = self.cats_to_update[:])
++                del self.cats_to_update[:]
++ 
++            return
++
++        if self.tasks_pids['render_plots'] == event.pid:
++            #TODO how to put it to the thread - kils gui
++            self.RenderScattPlts()
++            return
++            
++        if event.pid in self.tasks_pids['add_scatt']:
++            self.AddScattPlotDone(event)
++            return
++
++        if self.tasks_pids['set_data'] == event.pid:
++            self.SetDataDone(event)
++            return
++        
++        if self.tasks_pids['set_edit_cat_data'] == event.pid:
++            self.SetEditCatDataDone(event)
++            return
++
++    def EditCat(self, edit_type):
++
++        self.edit_cat_type = edit_type
++
++        if self.edit_cat_type:
++            for scatt in self.scatt_plts.itervalues():
++                scatt.StopCategoryEdit()
++                scatt.StartCategoryEdit()
++
++        else:
++            for scatt in self.scatt_plts.itervalues():
++                scatt.StopCategoryEdit()
++
++    def SetEditCatData(self, scatt_id, bbox):
++        
++        value = 1
++        if self.edit_cat_type == 'remove':
++            value = 0
++
++        self.tasks_pids['set_edit_cat_data'] = self.thread.GetId()
++
++        sel_cat_id = self.cats_mgr.GetSelectedCat()
++        
++        self.thread.Run(callable = self.core.SetEditCatData, 
++                        scatt_id = scatt_id,
++                        cat_id = sel_cat_id,
++                        bbox = bbox,
++                        value = value)
++    
++    def SetEditCatDataDone(self, event):
++
++        self.RenderScattPlts()
++
++        cat_id = event.kwds["cat_id"]
++
++        cat_rast = self.core.GetCatRastOut(cat_id)
++
++
++        if cat_rast not in self.added_cats_rasts.values():
++
++            cats_attrs = self.cats_mgr.GetCategoryAttrs(cat_id)
++
++            #TODO use standard raster lib
++            name = "cat_%d" % cat_id
++            ret, err_msg = RunCommand('r.external',
++                                      output = name,
++                                      getErrorMsg = True,
++                                      input = cat_rast,
++                                      flags = "o",
++                                      overwrite = True)
++
++            if ret != 0:
++                GError(_("r.external failed\n%s" % err_msg))
++
++            region = self.core.GetRegion()
++            ret, err_msg = RunCommand('r.region',
++                                      map = name,
++                                      getErrorMsg = True,
++                                      n = "%f" % region['n'],
++                                      s = "%f" % region['s'],
++                                      e = "%f" % region['e'],
++                                      w = "%f" % region['w'],
++                                      )
++
++            region = self.core.GetRegion()
++            ret, err_msg = RunCommand('r.colors',
++                                      map = name,
++                                      rules = "-",
++                                      stdin = "1 %s" % cats_attrs["color"],
++                                      getErrorMsg = True)
++
++            if ret != 0:
++                GError(_("r.region failed\n%s" % err_msg))
++
++            self.mapWin.Map.AddLayer(ltype = "raster", name =  "cat_%d" % cat_id, render = True,
++                                     command = ["d.rast", "map=%s" % name, "values=1"])                
++
++            #elif self.giface.GetLayerTree():
++            #    self.giface.GetLayerTree().AddLayer("raster", lname =  "cat_%d" % cat_id, lchecked = True,
++            #                    lcmd = ["d.rast", "map=%s" % name, "values=1"])
++
++            if ret != 0:
++                GError(_("r.region failed\n%s" % err_msg))
++
++            self.added_cats_rasts[cat_id] = cat_rast
++
++        self.giface.updateMap.emit()
++
++    def DigitDataChanged(self, vectMap, digit):
++        
++        if self.mapWin_conn:
++            self.mapWin_conn.DigitDataChanged(vectMap, digit)
++            return 1
++        else:
++            return 0
++
++    def GetCategoriesManager(self):
++        return self.cats_mgr
++
++class CategoriesManager:
++
++    def __init__(self, scatt_mgr, core):
++
++        self.core = core
++        self.scatt_mgr = scatt_mgr
++
++        self.cats = {}
++        self.cats_ids = []
++
++        self.sel_cat_id = -1
++
++        self.initialized = Signal('CategoriesManager.initialized')
++        self.setCategoryAttrs = Signal('CategoriesManager.setCategoryAttrs')
++        self.deletedCategory = Signal('CategoriesManager.deletedCategory')
++        self.addedCategory = Signal('CategoriesManager.addedCategory')
++
++    def Clear(self):
++
++        self.cats.clear()
++        del self.cats_ids[:]
++
++        self.sel_cat_id = -1   
++
++    def InitCoreCats(self):
++        if self.scatt_mgr.data_set:
++            for cat_id in self.cats_ids:
++                self.core.AddCategory(cat_id)
++
++    def AddCategory(self, cat_id = None, name = None, color = None):
++
++        if cat_id is None:
++            if self.cats_ids:
++                cat_id = max(self.cats_ids) + 1
++            else:
++                cat_id = 1
++
++        if self.scatt_mgr.data_set:
++            ret = self.core.AddCategory(cat_id)
++            if ret < 0: #TODO
++                return -1;
++
++        self.cats[cat_id] = {
++                                'name' : _('Category %s' % cat_id ),
++                                'color' : "0:0:0"
++                            }
++        self.cats_ids.append(cat_id)
++
++        if name is not None:
++            self.cats[cat_id]["name"] = name
++   
++        if color is not None:
++            self.cats[cat_id]["color"] = color
++
++        self.addedCategory.emit(cat_id = cat_id,
++                                name = self.cats[cat_id]["name"], 
++                                color = self.cats[cat_id]["color"] )
++        return cat_id
++
++    def SetCategoryAttrs(self, cat_id, attrs_dict):
++        for k, v in attrs_dict.iteritems():
++            self.cats[cat_id][k] = v
++
++        self.setCategoryAttrs.emit(cat_id = cat_id, attrs_dict = attrs_dict)
++
++    def DeleteCategory(self, cat_id):
++
++        if self.scatt_mgr.data_set:
++            self.core.DeleteCategory(cat_id)
++        del self.cats[cat_id]
++        self.cats_ids.remove(cat_id)
++
++        self.deletedCategory.emit(cat_id = cat_id)
++
++    #TODO emit event?
++    def SetSelectedCat(self, cat_id):
++        self.sel_cat_id = cat_id
++
++    def GetSelectedCat(self):
++        return self.sel_cat_id
++
++    def GetCategoryAttrs(self, cat_id):
++        #TODO is mutable
++        return self.cats[cat_id]
++
++    def GetCategoriesAttrs(self):
++        #TODO is mutable
++        return self.cats
++     
++    def GetCategories(self):
++        return self.cats_ids[:]
++
++class MapWinConnection:
++    def __init__(self, scatt_mgr, mapWin, scatt_rast_updater):
++        self.mapWin = mapWin
++        self.vectMap = None
++        self.scatt_rast_updater = scatt_rast_updater
++        self.scatt_mgr = scatt_mgr
++        self.cats_mgr = scatt_mgr.cats_mgr
++
++        self.thread = self.scatt_mgr.thread
++
++        #TODO
++        self.mapWin.parent.toolbars["vdigit"].editingStarted.connect(self.DigitDataChanged)
++
++        #def ChangeMap(self, vectMap, layers_cats):
++        #     self.vectMap = vectMap
++        #     self.layers_cats = layers_cats
++
++        #ret, region, msg = RunCommand("v.to.rast",
++        #                              flags = "gp",
++        #                              getErrorMsg = True,
++        #                              read = True)
++
++    def _connectSignals(self):
++        self.digit.featureAdded.connect(self.AddFeature)
++        self.digit.areasDeleted.connect(self.DeleteAreas)
++        self.digit.featuresDeleted.connect(self.DeleteAreas)
++        self.digit.vertexMoved.connect(self.ChangeVertex)
++        self.digit.vertexRemoved.connect(self.ChangeVertex)
++        self.digit.lineEdited.connect(self.ChangeVertex)
++        self.digit.featuresMoved.connect(self.MoveFeatures)
++
++    def AddFeature(self, new_geom, cat):
++        if not self.scatt_mgr.data_set:
++            return
++
++        self.scatt_mgr.tasks_pids['mapwin_conn'].append(self.thread.GetId())
++        self.thread.Run(callable = self.scatt_rast_updater.AddedFeature, 
++                        new_geom = new_geom, 
++                        cat = cat)
++
++    def DeleteAreas(self, old_geoms, old_areas_cats):
++        if not self.scatt_mgr.data_set:
++            return
++
++        self.scatt_mgr.tasks_pids['mapwin_conn'].append(self.thread.GetId())
++        self.thread.Run(callable = self.scatt_rast_updater.DeletedAreas, 
++                        old_geoms = old_geoms, 
++                        old_areas_cats = old_areas_cats)
++
++    def ChangeVertex(self, new_geom, new_areas_cats, old_geom, old_areas_cats):
++        if not self.scatt_mgr.data_set:
++            return
++
++        self.scatt_mgr.tasks_pids['mapwin_conn'].append(self.thread.GetId())
++        self.thread.Run(callable = self.scatt_rast_updater.ChangedVertex, 
++                        new_geom = new_geom, 
++                        old_geom = old_geom, 
++                        old_areas_cats = old_areas_cats,
++                        new_areas_cats = new_areas_cats)
++
++    def MoveFeatures(self, old_geoms, old_areas_cats, new_areas_cats, move):
++        if not self.scatt_mgr.data_set:
++            return
++
++        self.scatt_mgr.tasks_pids['mapwin_conn'].append(self.thread.GetId())
++        self.thread.Run(callable = self.scatt_rast_updater.MovedFeatures, 
++                        move = move, 
++                        old_geoms = old_geoms, 
++                        old_areas_cats = old_areas_cats,
++                        new_areas_cats = new_areas_cats)
++
++    def DigitDataChanged(self, vectMap, digit):
++
++        self.digit = digit
++        self.vectMap = vectMap
++
++        self.scatt_rast_updater.SetVectMap(vectMap)
++
++        self._connectSignals()
++
++class IClassConnection:
++    def __init__(self, scatt_mgr, iclass_frame, cats_mgr):
++        self.iclass_frame = iclass_frame
++        self.stats_data   = self.iclass_frame.stats_data
++        self.cats_mgr     = cats_mgr
++        self.scatt_mgr    = scatt_mgr
++
++        self.stats_data.statisticsAdded.connect(self.AddCategory)
++        self.stats_data.statisticsDeleted.connect(self.DeleteCategory)
++        self.stats_data.allStatisticsDeleted.connect(self.DeletAllCategories)
++        self.stats_data.statisticsSet.connect(self.SetCategory)
++
++        self.cats_mgr.setCategoryAttrs.connect(self.SetStatistics)
++        self.cats_mgr.deletedCategory.connect(self.DeleteStatistics)
++        self.cats_mgr.addedCategory.connect(self.AddStatistics)
++
++        self.SyncCats()
++
++    def SyncCats(self):
++        self.cats_mgr.addedCategory.disconnect(self.AddStatistics)
++        cats = self.stats_data.GetCategories()
++        for c in cats:
++            stats = self.stats_data.GetStatistics(c)
++            self.cats_mgr.AddCategory(c, stats.name, stats.color)
++        self.cats_mgr.addedCategory.connect(self.AddStatistics)
++
++    def AddCategory(self, cat, name, color):
++        self.cats_mgr.addedCategory.disconnect(self.AddStatistics)
++        self.cats_mgr.AddCategory(cat_id = cat, name = name, color = color)
++        self.cats_mgr.addedCategory.connect(self.AddStatistics)
++
++    def DeleteCategory(self, cat):
++        self.cats_mgr.deletedCategory.disconnect(self.DeleteStatistics)
++        self.cats_mgr.DeleteCategory(cat)
++        self.cats_mgr.deletedCategory.connect(self.DeleteStatistics)
++
++
++    def DeletAllCategories(self):
++
++        self.cats_mgr.deletedCategory.disconnect(self.DeleteStatistics)
++        cats = self.stats_data.GetCategories()
++        for c in cats:
++            self.cats_mgr.DeleteCategory(c)
++        self.cats_mgr.deletedCategory.connect(self.DeleteStatistics)
++
++    def SetCategory(self, cat, stats):
++
++        self.cats_mgr.setCategoryAttrs.disconnect(self.SetStatistics)
++        cats_attr = {}
++        for attr in ['name', 'color']:
++            if stats.has_key(attr):
++                cats_attr[attr] = stats[attr]
++
++        if cats_attr:
++            self.cats_mgr.SetCategoryAttrs(cat, cats_attr)
++        self.cats_mgr.setCategoryAttrs.connect(self.SetStatistics)
++
++
++    def SetStatistics(self, cat_id, attrs_dict):
++        self.stats_data.statisticsSet.disconnect(self.SetCategory)
++        self.stats_data.GetStatistics(cat_id).SetStatistics(attrs_dict)
++        self.stats_data.statisticsSet.connect(self.SetCategory)
++
++    def AddStatistics(self, cat_id, name, color):
++        self.stats_data.statisticsAdded.disconnect(self.AddCategory)
++        self.stats_data.AddStatistics(cat_id, name, color)
++        self.stats_data.statisticsAdded.connect(self.AddCategory)
++
++    def DeleteStatistics(self, cat_id):
++        self.stats_data.statisticsDeleted.disconnect(self.DeleteCategory)
++        self.stats_data.DeleteStatistics(cat_id)
++        self.stats_data.statisticsDeleted.connect(self.DeleteCategory)
 Index: gui/wxpython/scatt_plot/sc_pl_core.py
 ===================================================================
 --- gui/wxpython/scatt_plot/sc_pl_core.py	(revision 0)
 +++ gui/wxpython/scatt_plot/sc_pl_core.py	(working copy)
-@@ -0,0 +1,631 @@
+@@ -0,0 +1,697 @@
 +"""!
 + at package scatt_plot.scatt_plot
 +
@@ -160,6 +690,9 @@
 +import os
 +import sys
 +
++#TODO
++import time
++
 +import numpy as np
 +
 +from math import sqrt, ceil, floor
@@ -170,7 +703,8 @@
 +
 +import grass.script as grass
 +
-+from core_c import CreateCatRast, ComputeScatts, UpdateCatRast
++from core_c import CreateCatRast, ComputeScatts, UpdateCatRast, \
++                   SC_SCATT_DATA, SC_SCATT_CONDITIONS
 +
 +class Core:
 +    def __init__(self):
@@ -188,7 +722,7 @@
 +        n_bands = len(self.GetBands())
 +
 +        self.scatts_dt.Create(n_bands)
-+        self.scatt_conds_dt.Create(n_bands)        
++        self.scatt_conds_dt.Create(n_bands)
 +
 +    def AddCategory(self, cat_id):
 +        self.scatts_dt.AddCategory(cat_id)
@@ -225,9 +759,16 @@
 +        cats_rasts_out = self.scatts_dt.GetCatsRastsOut()
 +        cats_rasts_in = self.scatts_dt.GetCatsRastsIn()
 +
++
++        #for cat in scatts.itervalues():
++        #    for scatt_id in cat.itervalues():
++        #        print cat
++        #        scatt_id.values()[0].flush()
++        #        del scatt_id
++
 +        returncode, scatts = ComputeScatts(self.an_data.GetRegion(), scatt_conds, bands, 
 +                                           len(self.GetBands()), scatts, cats_rasts_in, cats_rasts_out)
-+        self.scatts_dt.SetData(scatts)
++        #self.scatts_dt.SetData(scatts)
 +
 +    def SetEditCatData(self, cat_id, scatt_id, bbox, value):
 +
@@ -240,9 +781,13 @@
 +            bbox[k] = self._validExtend(v)
 +
 +        arr[bbox['btm_y'] : bbox['up_y'], bbox['btm_x'] : bbox['up_x']] = value
++        arr.flush()
++        #del arr
 +
++        start_time = time.clock()
 +        self.ComputeCatScatts([cat_id])
-+
++        print "time"
++        print time.clock() - start_time
 +        return True
 +
 +    def ComputeCatScatts(self, cats_ids):
@@ -265,7 +810,7 @@
 +        returncode, scatts = ComputeScatts(self.an_data.GetRegion(), scatt_conds, bands,
 +                                           len(self.GetBands()), scatts, cats_rasts_in, cats_rasts_out)
 +        
-+        self.scatts_dt.SetData(scatts)
++        #self.scatts_dt.SetData(scatts)
 +
 +    def CatRastUpdater(self):
 +        return self.cat_rast_updater
@@ -338,8 +883,8 @@
 +    def DeletedAreas(self, old_geoms, old_areas_cats):
 +
 +        updated_cats = []
-+        for i in range(len(old_geoms)):
-+            self._updateCatRast(old_geoms[i], old_areas_cats[i], updated_cats)
++        #for i in range(len(old_geoms)):
++        #    self._updateCatRast(old_geoms[i], old_areas_cats[i], updated_cats)
 +
 +        return updated_cats
 +
@@ -468,17 +1013,16 @@
 +
 +    def __init__(self):
 +        
-+        self.bands = None
-+        self.bin_bands_f = []      
++        self.bands = []
++        self.bands_info = {}
 +
-+        self.region = {}
++        self.region = None
 +
 +    def GetRegion(self):
 +        return self.region
 +
 +    def Create(self, bands):
 +
-+        self.bands = None
 +        self.bands = bands
 +        self.region = None
 +
@@ -490,11 +1034,53 @@
 +        if  ret != 0:
 +            raise GException("g.region failed:\n%s" % msg)
 +
++
++        self.bands_info = {}
++        for b in bands:
++            self.bands_info[b] = self._getRasterInfo(b)
++            if self.bands_info[b]["datatype"] != "CELL":
++                raise GException(_("Raster <%s> is not <CELL> type.") % (b))
++            #TODO size of raster check
++
 +        self.region = self._parseRegion(region)
 +
++    def _getRasterInfo(self, rast):
++        """
++        """
++        ret, out, msg = RunCommand("r.info",
++                                    map = rast,
++                                    flags = "rg",
++                                    getErrorMsg = True,
++                                    read = True)
++
++        if  ret != 0:
++            raise GException("r.info failed:\n%s" % msg)
++
++        out = out.split("\n")
++        raster_info = {} 
++
++        for b in out:
++            if not b.strip():
++                continue
++            k, v = b.split("=")
++            if k == "datatype":
++                pass
++            elif k in ['rows', 'cols', 'cells', 'min', 'max']:
++                v = int(v)
++            else:
++                v = float(v)
++
++            raster_info[k] = v
++
++        return raster_info
++
 +    def GetBands(self):
 +        return self.bands
 +
++    def GetBandInfo(self, band_id):
++        band = self.bands[band_id]
++        return self.bands_info[band]
++
 +    def _parseRegion(self, region_str):
 +
 +        region = {}
@@ -516,10 +1102,10 @@
 +
 +        self.an_data = an_data
 +
++        #TODO
 +        self.max_n_cats = 10
 +    
-+        self.vals = 256 * 256
-+
++        self.dtype = 'uint8'
 +        self.type = 1;
 +        self.CleanUp()
 +
@@ -577,22 +1163,30 @@
 +        if self.cats[cat_id].has_key(scatt_id):
 +            return 0
 +
-+        if self.type == 0:
-+            np_vals = np.zeros(self.vals, dtype = 'uint32')
-+        elif self.type == 1:
-+            #TODO solve proble with short
-+            np_vals = np.zeros(self.vals, dtype = 'uint32')
-+        else:
-+            return -1
++        b_i = self.GetBandsInfo(scatt_id)
 +
-+        np_vals.shape = (256, 256)#TODO hack do it general
++        shape = (b_i['b2']['max'] - b_i['b2']['min'] + 1, b_i['b1']['max'] - b_i['b1']['min'] + 1)
 +
++        np_vals = np.memmap(grass.tempfile(), dtype=self.dtype, mode='w+', shape = shape)
++        np_vals.flush()
++
 +        self.cats[cat_id][scatt_id] = {
 +                                        'np_vals' : np_vals
 +                                      }
 +
 +        return 1
 +
++    def GetBandsInfo(self, scatt_id):
++        b1, b2 = idScattToidBands(scatt_id, len(self.an_data.GetBands()))
++
++        b1_info = self.an_data.GetBandInfo(b1)
++        b2_info = self.an_data.GetBandInfo(b2)
++
++        bands_info = {'b1' : b1_info,
++                      'b2' : b2_info}
++
++        return bands_info
++
 +    def DeleScattPlot(self, cat_id, scatt_id):
 +
 +        if not self.cats.has_key(cat_id):
@@ -623,7 +1217,8 @@
 +            for scatt_id in scatt_ids:
 +                # if key is missing condition is always True (full scatter plor is computed)
 +                if self.cats[cat_id].has_key(scatt_id):
-+                    cats[cat_id][scatt_id] = {'np_vals' : self.cats[cat_id][scatt_id]['np_vals']}
++                    cats[cat_id][scatt_id] = {'np_vals' : self.cats[cat_id][scatt_id]['np_vals'],
++                                              'bands_info' : self.GetBandsInfo(scatt_id)}
 +                        
 +        return cats
 +
@@ -645,6 +1240,8 @@
 +
 +        ScattPlotsCondsData.__init__(self, an_data)
 +
++        self.dtype = 'uint32'
++
 +        #TODO
 +        self.type = 0
 +
@@ -709,8 +1306,8 @@
 +
 +        scatts = {}
 +        for cat_id in self.cats.iterkeys():
-+            scatts[cat_id] = self.cats[cat_id][scatt_id]['np_vals']
-+
++            scatts[cat_id] = {'np_vals' : self.cats[cat_id][scatt_id]['np_vals'],
++                              'bands_info' : self.GetBandsInfo(scatt_id)}
 +        return scatts
 +
 +    def CleanUp(self):
@@ -749,7 +1346,7 @@
 +        return cats_rasts_out
 +
 +#TODO move to utils?
-+def idScattToBands(scatt_id, n_bands):
++def idScattToidBands(scatt_id, n_bands):
 + 
 +    n_b1 = n_bands - 1
 +
@@ -760,17 +1357,16 @@
 +    return band_1, band_2
 +
 +
-+def BandsToidScatt(band_1, band_2, n_bands):
++def idBandsToidScatt(band_1_id, band_2_id, n_bands):
 +
-+    if band_2 <  band_1:
++    if band_2_id <  band_1_id:
 +        tmp = band_1
-+        band_1 = band_2
-+        band_2 = tmp
++        band_1_id = band_2_id
++        band_2_id = tmp
 +
-+
 +    n_b1 = n_bands - 1
 +
-+    scatt_id = (band_1 * (2 * n_b1 + 1) - band_1 * band_1) / 2 + band_2 - band_1 - 1
++    scatt_id = (band_1_id * (2 * n_b1 + 1) - band_1_id * band_1_id) / 2 + band_2_id - band_1_id - 1
 +
 +    return scatt_id
 +
@@ -948,7 +1544,7 @@
 +
 +from scatt_plot.controllers import ScattsManager
 +from scatt_plot.toolbars    import MainToolbar, CategoriesToolbar
-+from scatt_plot.sc_pl_core  import Core, BandsToidScatt
++from scatt_plot.sc_pl_core  import Core, idBandsToidScatt
 +from scatt_plot.plots       import ScatterPlotWidget
 +
 +
@@ -1133,7 +1729,7 @@
 +
 +
 +        self._createWidgets()
-+        self.group.SetValue("testovaci_1")
++        self.group.SetValue("B_sk")
 +
 +    def _createWidgets(self):
 +
@@ -1359,7 +1955,7 @@
 +            band_2 = band_1
 +            band_1 = band_2
 +
-+        self.scatt_id = BandsToidScatt(band_1, band_2, len(self.bands))
++        self.scatt_id = idBandsToidScatt(band_1, band_2, len(self.bands))
 +
 +        event.Skip()
 +
@@ -1646,7 +2242,7 @@
 ===================================================================
 --- gui/wxpython/scatt_plot/core_c.py	(revision 0)
 +++ gui/wxpython/scatt_plot/core_c.py	(working copy)
-@@ -0,0 +1,211 @@
+@@ -0,0 +1,227 @@
 +"""!
 + at package scatt_plot.scatt_plot
 +
@@ -1668,13 +2264,15 @@
 +try:
 +    from grass.lib.imagery import *
 +    from grass.lib.gis import Cell_head, G_get_window
++    #from grass.lib.raster import struct_Range
 +
++
 +except ImportError, e:
 +    sys.stderr.write(_("Loading imagery lib failed"))
 +
 +def ComputeScatts(region, scatt_conds, bands, n_bands, scatts, cats_rasts_in, cats_rasts_out):
 +
-+    #return _computeScattsProcess(region, scatt_conds, bands, n_bands, scatts, cats_rasts_in, cats_rasts_out)
++    return _computeScattsProcess(region, scatt_conds, bands, n_bands, scatts, cats_rasts_in, cats_rasts_out, None)
 +
 +    # Queue object for interprocess communication
 +    q = Queue()
@@ -1690,7 +2288,7 @@
 +
 +def UpdateCatRast(patch_rast, region, cat_rast):
 +
-+    #return ComputeScattsProcess(region, scatt_conds, bands, n_bands, scatts, cats_rasts)
++    #return _computeScattsProcess(region, scatt_conds, bands, n_bands, scatts, cats_rasts, None)
 +    # Queue object for interprocess communication
 +
 +    #_updateCatRastProcess(patch_rast, region, cat_rast, None)
@@ -1722,19 +2320,28 @@
 +    cell_head = _regionToCellHead(region)
 +
 +    ret = I_compute_scatts(pointer(cell_head),
-+                          pointer(scatt_conds_c),
-+                          pointer(char_bands),
-+                          n_bands,
-+                          pointer(sccats_c),
-+                          pointer(char_cats_rasts_in),
-+                          pointer(char_cats_rasts_out))
++                           pointer(scatt_conds_c),
++                           pointer(char_bands),
++                           n_bands,
++                           pointer(sccats_c),
++                           pointer(char_cats_rasts_in),
++                           pointer(char_cats_rasts_out))
 +
 +    I_sc_free_cats(pointer(sccats_c))
 +    I_sc_free_cats(pointer(scatt_conds_c))
 +
-+    output_queue.put((ret, scatts))
-+    #return (ret, scatts)
++    #output_queue.put((ret, scatts))
++    return (ret, scatts)
 +
++def _getBandcRange( band_info):
++    band_c_range = struct_Range()
++
++    band_c_range.max = band_info['max']
++    band_c_range.min = band_info['min']
++
++    return band_c_range
++
++
 +def _regionToCellHead(region):
 +    cell_head = struct_Cell_head()
 +    G_get_window(pointer(cell_head))
@@ -1787,24 +2394,29 @@
 +            # if key is missing condition is always True (full scatter plor is computed)
 +            if cats[cat_id].has_key(scatt_id):
 +
-+                vals = dt["np_vals"]
-+                #TODO hack
-+                vals.shape = (256 * 256)
++                vals = dt['np_vals']
++                b1_info = dt['bands_info']['b1']
++                b2_info = dt['bands_info']['b2']
 +
-+                c_uint_p = ctypes.POINTER(ctypes.c_uint)
 +                scatt_vals = scdScattData()
-+                if cats_type == 0:
++
++                c_void_p = ctypes.POINTER(ctypes.c_void_p)
++
++                if cats_type == SC_SCATT_DATA:
 +                    vals[:] = 0
-+                    scatt_vals.scatt_vals_arr = vals.ctypes.data_as(c_uint_p)
-+
++                elif cats_type == SC_SCATT_CONDITIONS:
++                    pass
 +                else:
-+                    #TODO solve proble with short integer
-+                    scatt_vals.b_conds_arr = vals.ctypes.data_as(c_uint_p)
++                    return None
 +
++                b1_c_info = _getBandcRange(b1_info)
++                b2_c_info =_getBandcRange(b2_info)
++                data_p = vals.ctypes.data_as(c_void_p)
++                I_scd_init_scatt_data(pointer(scatt_vals), cats_type, len(vals), data_p, 
++                                      b1_c_info, b2_c_info)
++
 +                vals_dt.append(scatt_vals)
 +
-+                #vals_dt.append(data_p)
-+                vals.shape = (256, 256)
 +                I_sc_insert_scatt_data(pointer(sccats),  
 +                                       pointer(scatt_vals),
 +                                       cat_id, scatt_id)
@@ -1875,7 +2487,7 @@
 ===================================================================
 --- gui/wxpython/scatt_plot/plots.py	(revision 0)
 +++ gui/wxpython/scatt_plot/plots.py	(working copy)
-@@ -0,0 +1,185 @@
+@@ -0,0 +1,199 @@
 +"""!
 + at package scatt_plot.dialogs
 +
@@ -2009,7 +2621,7 @@
 +        """
 +      
 +        self.axes.clear()
-+        for cat_id, cat in scatts.iteritems():
++        for cat_id, scatt in scatts.iteritems():
 +            if cat_id == 0:
 +                cmap = matplotlib.cm.jet
 +                cmap.set_bad('w',1.)
@@ -2026,11 +2638,25 @@
 +                cmap._lut[:, 1] = int(colors[1])/255.0
 +                cmap._lut[:, 2] = int(colors[2])/255.0
 +
-+            masked_cat = np.ma.masked_less_equal(cat, 0)
++            masked_cat = np.ma.masked_less_equal(scatt['np_vals'], 0)
 +
-+            self.axes.imshow(masked_cat, cmap = cmap,  interpolation='nearest')
 +
++            b1_i = scatt['bands_info']['b1']
++            b2_i = scatt['bands_info']['b2']
++            
++            #self.axes.set_xlim((0, 270))
++            #self.axes.set_ylim((0, 270))
++            np.savetxt("/home/ostepok/Desktop/data.txt", scatt['np_vals'], fmt = '%d') 
++
++
++            #TODO needs optimization
++            img = self.axes.imshow(masked_cat, cmap = cmap,
++                                               origin = 'lower',
++                                               extent = (b1_i['min'] - 0.5, b1_i['max'] + 0.5, b2_i['min'] - 0.5, b2_i['max'] + 0.5), 
++                                               interpolation='nearest')
++            
 +            self.canvas.draw()
++
 +    
 +    def on_pick(self, event):
 +        pass
@@ -2062,527 +2688,55 @@
 +        self.parent.OnPlotClosed(self.scatt_id)
 +        self.Destroy()
 \ No newline at end of file
-Index: gui/wxpython/scatt_plot/controllers.py
+Index: gui/wxpython/mapdisp/toolbars.py
 ===================================================================
---- gui/wxpython/scatt_plot/controllers.py	(revision 0)
-+++ gui/wxpython/scatt_plot/controllers.py	(working copy)
-@@ -0,0 +1,513 @@
-+"""!
-+ at package scatt_plot.controllers
-+
-+ at brief Controller layer for scatter plot tool.
-+
-+Classes:
-+
-+(C) 2013 by the GRASS Development Team
-+
-+This program is free software under the GNU General Public License
-+(>=v2). Read the file COPYING that comes with GRASS for details.
-+
-+ at author Stepan Turek <stepan.turek seznam.cz> (mentor: Martin Landa)
-+"""
-+import os
-+import sys
-+
-+#TODO
-+import wx
-+
-+from core.gcmd     import GException, GError, RunCommand
-+
-+from scatt_plot.sc_pl_core import Core, BandsToidScatt
-+
-+from scatt_plot.gthreading import gThread
-+from core.gconsole         import EVT_CMD_DONE
-+
-+from grass.pydispatch.signal import Signal
-+
-+class ScattsManager(wx.EvtHandler):
-+    def __init__(self, guiparent, giface, iclass_mapwin):
-+        #TODO remove iclass parameter
-+
-+        wx.EvtHandler.__init__(self)
-+        self.giface = giface
-+        self.mapDisp  = giface.GetMapDisplay()
-+        self.mapWin = giface.GetMapWindow()
-+
-+        if iclass_mapwin:
-+            self.mapWin = iclass_mapwin
-+
-+        self.guiparent = guiparent
-+
-+        self.core = Core()
-+        self.scatts_dt = self.core.GetScattsData()
-+
-+        self.cats_mgr = CategoriesManager(self, self.core)
-+
-+        self.thread = gThread(self);
-+        
-+        self.scatt_plts = {}
-+        self.added_cats_rasts = {}
-+
-+        self.cats_to_update = []
-+
-+        self.edit_cat_type =  None
-+
-+        self.data_set = False
-+
-+        if iclass_mapwin: 
-+            self.mapWin_conn = MapWinConnection(self, self.mapWin, self.core.CatRastUpdater())
-+            self.iclass_conn = IClassConnection(self, iclass_mapwin.parent, self.cats_mgr)
-+        else:
-+            self.mapWin_conn = None
-+            self.iclass_conn = None
-+
-+        self.tasks_pids = {
-+                            'add_scatt' : -1,
-+                            'set_data' : -1,
-+                            'set_edit_cat_data' : -1,
-+                            'mapwin_conn' : [],
-+                            'render_plots' : -1
-+                           }
-+
-+        self.Bind(EVT_CMD_DONE, self.OnThreadDone)
-+
-+    def SetData(self, bands):
-+        self.data_set = False
-+        self.tasks_pids['set_data'] = self.thread.GetId()
-+        self.thread.Run(callable = self.core.SetData, bands = bands)
-+
-+    def SetDataDone(self, event):
-+        self.data_set = True
-+        self.cats_mgr.InitCoreCats()
-+
-+    def OnOutput(self, event):
-+        """!Print thread output according to debug level.
+--- gui/wxpython/mapdisp/toolbars.py	(revision 57336)
++++ gui/wxpython/mapdisp/toolbars.py	(working copy)
+@@ -243,7 +243,8 @@
+                       (MapIcons["scatter"],     self.parent.OnScatterplot),
+                       (MapIcons["histogram"],   self.parent.OnHistogramPyPlot),
+                       (BaseIcons["histogramD"], self.parent.OnHistogram),
+-                      (MapIcons["vnet"],        self.parent.OnVNet)))
++                      (MapIcons["vnet"],        self.parent.OnVNet),
++                      (MapIcons["scatter"],     self.parent.OnScatterplot2)))
+         
+     def OnDecoration(self, event):
+         """!Decorations overlay menu
+Index: gui/wxpython/mapdisp/frame.py
+===================================================================
+--- gui/wxpython/mapdisp/frame.py	(revision 57336)
++++ gui/wxpython/mapdisp/frame.py	(working copy)
+@@ -207,6 +207,7 @@
+         #
+         self.dialogs = {}
+         self.dialogs['attributes'] = None
++        self.dialogs['scatt_plot'] = None
+         self.dialogs['category'] = None
+         self.dialogs['barscale'] = None
+         self.dialogs['legend'] = None
+@@ -1301,6 +1302,19 @@
+         """!Returns toolbar with zooming tools"""
+         return self.toolbars['map']
+ 
++    def OnScatterplot2(self, event):
++        """!Init interactive scatterplot tools
 +        """
-+        print event.text
-+
-+    def GetBands(self):
-+        return self.core.GetBands()
-+
-+    def AddScattPlot(self, scatt_id):
-+
-+        self.tasks_pids['add_scatt'] = self.thread.GetId()
-+        self.thread.Run(callable = self.core.AddScattPlot, scatt_id = scatt_id)
-+
-+    def RenderScattPlts(self):
-+
-+        cats_attrs = self.cats_mgr.GetCategoriesAttrs()
-+        for scatt_id, scatt in self.scatt_plts.iteritems():
-+            scatt_dt = self.scatts_dt.GetScatt(scatt_id)
-+            scatt.Plot(scatt_dt, cats_attrs)
-+
-+
-+    def AddScattPlotDone(self, event):
-+        
-+        scatt_id = event.kwds['scatt_id']
-+
-+        #TODO guiparent - not very good
-+        self.scatt_plts[scatt_id] = self.guiparent.NewScatterPlot(scatt_id = scatt_id)
-+
-+        if self.edit_cat_type:
-+            self.scatt_plts[scatt_id].StartCategoryEdit()
-+
-+        scatt_dt = self.scatts_dt.GetScatt(scatt_id)
-+        
-+        cats_attrs = self.cats_mgr.GetCategoriesAttrs()
-+        self.scatt_plts[scatt_id].Plot(scatt_dt, cats_attrs)
-+
-+        self.scatt_plts[scatt_id].GetParent().Show()
-+
-+
-+    def CleanUp(self):
-+        self.core.CleanUp()
-+
-+        for scatt_id, scatt in self.scatt_plts.items():
-+            scatt.CleanUp()
-+            del self.scatt_plts[scatt_id]
-+
-+    def OnThreadDone(self, event):
-+        
-+        if event.exception:
-+            GError(str(event.exception))
++        if self.dialogs['scatt_plot']:
++            self.dialogs['scatt_plot'].Raise()
 +            return
 +
-+        if event.pid in self.tasks_pids['mapwin_conn']:
-+            self.tasks_pids['mapwin_conn'].remove(event.pid)
-+            updated_cats = event.ret
-+
-+            for cat in updated_cats:
-+                if cat not in  self.cats_to_update:
-+                    self.cats_to_update.append(cat)
-+
-+            if not self.tasks_pids['mapwin_conn']:
-+                self.tasks_pids['render_plots'] = self.thread.GetId()
-+                self.thread.Run(callable = self.core.ComputeCatScatts, 
-+                                cats_ids = self.cats_to_update[:])
-+                del self.cats_to_update[:]
-+ 
-+            return
-+
-+        if self.tasks_pids['render_plots'] == event.pid:
-+            #TODO how to put it to the thread - kils gui
-+            self.RenderScattPlts()
-+            return
-+            
-+        if self.tasks_pids['add_scatt'] == event.pid:
-+            self.AddScattPlotDone(event)
-+            return
-+
-+        if self.tasks_pids['set_data'] == event.pid:
-+            self.SetDataDone(event)
-+            return
++        from scatt_plot.dialogs import ScattPlotMainDialog
++        self.dialogs['scatt_plot'] = ScattPlotMainDialog(parent=self, giface=self._giface)
 +        
-+        if self.tasks_pids['set_edit_cat_data'] == event.pid:
-+            self.SetEditCatDataDone(event)
-+            return
++        self.dialogs['scatt_plot'].CenterOnScreen()
++        self.dialogs['scatt_plot'].Show()
 +
-+    def EditCat(self, edit_type):
-+
-+        self.edit_cat_type = edit_type
-+
-+        if self.edit_cat_type:
-+            for scatt in self.scatt_plts.itervalues():
-+                scatt.StopCategoryEdit()
-+                scatt.StartCategoryEdit()
-+
-+        else:
-+            for scatt in self.scatt_plts.itervalues():
-+                scatt.StopCategoryEdit()
-+
-+    def SetEditCatData(self, scatt_id, bbox):
-+        
-+        value = 1
-+        if self.edit_cat_type == 'remove':
-+            value = 0
-+
-+        self.tasks_pids['set_edit_cat_data'] = self.thread.GetId()
-+
-+        sel_cat_id = self.cats_mgr.GetSelectedCat()
-+        
-+        self.thread.Run(callable = self.core.SetEditCatData, 
-+                        scatt_id = scatt_id,
-+                        cat_id = sel_cat_id,
-+                        bbox = bbox,
-+                        value = value)
-+    
-+    def SetEditCatDataDone(self, event):
-+
-+        self.RenderScattPlts()
-+
-+        cat_id = event.kwds["cat_id"]
-+
-+        cat_rast = self.core.GetCatRastOut(cat_id)
-+
-+
-+        if cat_rast not in self.added_cats_rasts.values():
-+
-+            cats_attrs = self.cats_mgr.GetCategoryAttrs(cat_id)
-+
-+            #TODO use standard raster lib
-+            name = "cat_%d" % cat_id
-+            ret, err_msg = RunCommand('r.external',
-+                                      output = name,
-+                                      getErrorMsg = True,
-+                                      input = cat_rast,
-+                                      flags = "o",
-+                                      overwrite = True)
-+
-+            if ret != 0:
-+                GError(_("r.external failed\n%s" % err_msg))
-+
-+            region = self.core.GetRegion()
-+            ret, err_msg = RunCommand('r.region',
-+                                      map = name,
-+                                      getErrorMsg = True,
-+                                      n = "%f" % region['n'],
-+                                      s = "%f" % region['s'],
-+                                      e = "%f" % region['e'],
-+                                      w = "%f" % region['w'],
-+                                      )
-+
-+            region = self.core.GetRegion()
-+            ret, err_msg = RunCommand('r.colors',
-+                                      map = name,
-+                                      rules = "-",
-+                                      stdin = "1 %s" % cats_attrs["color"],
-+                                      getErrorMsg = True)
-+
-+            if ret != 0:
-+                GError(_("r.region failed\n%s" % err_msg))
-+
-+            self.mapWin.Map.AddLayer(ltype = "raster", name =  "cat_%d" % cat_id, render = True,
-+                                     command = ["d.rast", "map=%s" % name, "values=1"])                
-+
-+            #elif self.giface.GetLayerTree():
-+            #    self.giface.GetLayerTree().AddLayer("raster", lname =  "cat_%d" % cat_id, lchecked = True,
-+            #                    lcmd = ["d.rast", "map=%s" % name, "values=1"])
-+
-+            if ret != 0:
-+                GError(_("r.region failed\n%s" % err_msg))
-+
-+            self.added_cats_rasts[cat_id] = cat_rast
-+
-+        self.giface.updateMap.emit()
-+
-+    def DigitDataChanged(self, vectMap, digit):
-+        
-+        if self.mapWin_conn:
-+            self.mapWin_conn.DigitDataChanged(vectMap, digit)
-+            return 1
-+        else:
-+            return 0
-+
-+    def GetCategoriesManager(self):
-+        return self.cats_mgr
-+
-+class CategoriesManager:
-+
-+    def __init__(self, scatt_mgr, core):
-+
-+        self.core = core
-+        self.scatt_mgr = scatt_mgr
-+
-+        self.cats = {}
-+        self.cats_ids = []
-+
-+        self.sel_cat_id = -1
-+
-+        self.initialized = Signal('CategoriesManager.initialized')
-+        self.setCategoryAttrs = Signal('CategoriesManager.setCategoryAttrs')
-+        self.deletedCategory = Signal('CategoriesManager.deletedCategory')
-+        self.addedCategory = Signal('CategoriesManager.addedCategory')
-+
-+    def Clear(self):
-+
-+        self.cats.clear()
-+        del self.cats_ids[:]
-+
-+        self.sel_cat_id = -1   
-+
-+    def InitCoreCats(self):
-+        if self.scatt_mgr.data_set:
-+            for cat_id in self.cats_ids:
-+                self.core.AddCategory(cat_id)
-+
-+    def AddCategory(self, cat_id = None, name = None, color = None):
-+
-+        if cat_id is None:
-+            if self.cats_ids:
-+                cat_id = max(self.cats_ids) + 1
-+            else:
-+                cat_id = 1
-+
-+        if self.scatt_mgr.data_set:
-+            ret = self.core.AddCategory(cat_id)
-+            if ret < 0: #TODO
-+                return -1;
-+
-+        self.cats[cat_id] = {
-+                                'name' : _('Category %s' % cat_id ),
-+                                'color' : "0:0:0"
-+                            }
-+        self.cats_ids.append(cat_id)
-+
-+        if name is not None:
-+            self.cats[cat_id]["name"] = name
-+   
-+        if color is not None:
-+            self.cats[cat_id]["color"] = color
-+
-+        self.addedCategory.emit(cat_id = cat_id,
-+                                name = self.cats[cat_id]["name"], 
-+                                color = self.cats[cat_id]["color"] )
-+        return cat_id
-+
-+    def SetCategoryAttrs(self, cat_id, attrs_dict):
-+        for k, v in attrs_dict.iteritems():
-+            self.cats[cat_id][k] = v
-+
-+        self.setCategoryAttrs.emit(cat_id = cat_id, attrs_dict = attrs_dict)
-+
-+    def DeleteCategory(self, cat_id):
-+
-+        if self.scatt_mgr.data_set:
-+            self.core.DeleteCategory(cat_id)
-+        del self.cats[cat_id]
-+        self.cats_ids.remove(cat_id)
-+
-+        self.deletedCategory.emit(cat_id = cat_id)
-+
-+    #TODO emit event?
-+    def SetSelectedCat(self, cat_id):
-+        self.sel_cat_id = cat_id
-+
-+    def GetSelectedCat(self):
-+        return self.sel_cat_id
-+
-+    def GetCategoryAttrs(self, cat_id):
-+        #TODO is mutable
-+        return self.cats[cat_id]
-+
-+    def GetCategoriesAttrs(self):
-+        #TODO is mutable
-+        return self.cats
-+     
-+    def GetCategories(self):
-+        return self.cats_ids[:]
-+
-+class MapWinConnection:
-+    def __init__(self, scatt_mgr, mapWin, scatt_rast_updater):
-+        self.mapWin = mapWin
-+        self.vectMap = None
-+        self.scatt_rast_updater = scatt_rast_updater
-+        self.scatt_mgr = scatt_mgr
-+        self.cats_mgr = scatt_mgr.cats_mgr
-+
-+        self.thread = self.scatt_mgr.thread
-+
-+        #TODO
-+        self.mapWin.parent.toolbars["vdigit"].editingStarted.connect(self.DigitDataChanged)
-+
-+        #def ChangeMap(self, vectMap, layers_cats):
-+        #     self.vectMap = vectMap
-+        #     self.layers_cats = layers_cats
-+
-+        #ret, region, msg = RunCommand("v.to.rast",
-+        #                              flags = "gp",
-+        #                              getErrorMsg = True,
-+        #                              read = True)
-+
-+    def _connectSignals(self):
-+        self.digit.featureAdded.connect(self.AddFeature)
-+        self.digit.areasDeleted.connect(self.DeleteAreas)
-+        self.digit.featuresDeleted.connect(self.DeleteAreas)
-+        self.digit.vertexMoved.connect(self.ChangeVertex)
-+        self.digit.vertexRemoved.connect(self.ChangeVertex)
-+        self.digit.lineEdited.connect(self.ChangeVertex)
-+        self.digit.featuresMoved.connect(self.MoveFeatures)
-+
-+    def AddFeature(self, new_geom, cat):
-+        if not self.scatt_mgr.data_set:
-+            return
-+
-+        self.scatt_mgr.tasks_pids['mapwin_conn'].append(self.thread.GetId())
-+        self.thread.Run(callable = self.scatt_rast_updater.AddedFeature, 
-+                        new_geom = new_geom, 
-+                        cat = cat)
-+
-+    def DeleteAreas(self, old_geoms, old_areas_cats):
-+        if not self.scatt_mgr.data_set:
-+            return
-+
-+        self.scatt_mgr.tasks_pids['mapwin_conn'].append(self.thread.GetId())
-+        self.thread.Run(callable = self.scatt_rast_updater.DeletedAreas, 
-+                        old_geoms = old_geoms, 
-+                        old_areas_cats = old_areas_cats)
-+
-+    def ChangeVertex(self, new_geom, new_areas_cats, old_geom, old_areas_cats):
-+        if not self.scatt_mgr.data_set:
-+            return
-+
-+        self.scatt_mgr.tasks_pids['mapwin_conn'].append(self.thread.GetId())
-+        self.thread.Run(callable = self.scatt_rast_updater.ChangedVertex, 
-+                        new_geom = new_geom, 
-+                        old_geom = old_geom, 
-+                        old_areas_cats = old_areas_cats,
-+                        new_areas_cats = new_areas_cats)
-+
-+    def MoveFeatures(self, old_geoms, old_areas_cats, new_areas_cats, move):
-+        if not self.scatt_mgr.data_set:
-+            return
-+
-+        self.scatt_mgr.tasks_pids['mapwin_conn'].append(self.thread.GetId())
-+        self.thread.Run(callable = self.scatt_rast_updater.MovedFeatures, 
-+                        move = move, 
-+                        old_geoms = old_geoms, 
-+                        old_areas_cats = old_areas_cats,
-+                        new_areas_cats = new_areas_cats)
-+
-+    def DigitDataChanged(self, vectMap, digit):
-+
-+        self.digit = digit
-+        self.vectMap = vectMap
-+
-+        self.scatt_rast_updater.SetVectMap(vectMap)
-+
-+        self._connectSignals()
-+
-+class IClassConnection:
-+    def __init__(self, scatt_mgr, iclass_frame, cats_mgr):
-+        self.iclass_frame = iclass_frame
-+        self.stats_data   = self.iclass_frame.stats_data
-+        self.cats_mgr     = cats_mgr
-+        self.scatt_mgr    = scatt_mgr
-+
-+        self.stats_data.statisticsAdded.connect(self.AddCategory)
-+        self.stats_data.statisticsDeleted.connect(self.DeleteCategory)
-+        self.stats_data.allStatisticsDeleted.connect(self.DeletAllCategories)
-+        self.stats_data.statisticsSet.connect(self.SetCategory)
-+
-+        self.cats_mgr.setCategoryAttrs.connect(self.SetStatistics)
-+        self.cats_mgr.deletedCategory.connect(self.DeleteStatistics)
-+        self.cats_mgr.addedCategory.connect(self.AddStatistics)
-+
-+        self.SyncCats()
-+
-+    def SyncCats(self):
-+        self.cats_mgr.addedCategory.disconnect(self.AddStatistics)
-+        cats = self.stats_data.GetCategories()
-+        for c in cats:
-+            stats = self.stats_data.GetStatistics(c)
-+            self.cats_mgr.AddCategory(c, stats.name, stats.color)
-+        self.cats_mgr.addedCategory.connect(self.AddStatistics)
-+
-+    def AddCategory(self, cat, name, color):
-+        self.cats_mgr.addedCategory.disconnect(self.AddStatistics)
-+        self.cats_mgr.AddCategory(cat_id = cat, name = name, color = color)
-+        self.cats_mgr.addedCategory.connect(self.AddStatistics)
-+
-+    def DeleteCategory(self, cat):
-+        self.cats_mgr.deletedCategory.disconnect(self.DeleteStatistics)
-+        self.cats_mgr.DeleteCategory(cat)
-+        self.cats_mgr.deletedCategory.connect(self.DeleteStatistics)
-+
-+
-+    def DeletAllCategories(self):
-+
-+        self.cats_mgr.deletedCategory.disconnect(self.DeleteStatistics)
-+        cats = self.stats_data.GetCategories()
-+        for c in cats:
-+            self.cats_mgr.DeleteCategory(c)
-+        self.cats_mgr.deletedCategory.connect(self.DeleteStatistics)
-+
-+    def SetCategory(self, cat, stats):
-+
-+        self.cats_mgr.setCategoryAttrs.disconnect(self.SetStatistics)
-+        cats_attr = {}
-+        for attr in ['name', 'color']:
-+            if stats.has_key(attr):
-+                cats_attr[attr] = stats[attr]
-+
-+        if cats_attr:
-+            self.cats_mgr.SetCategoryAttrs(cat, cats_attr)
-+        self.cats_mgr.setCategoryAttrs.connect(self.SetStatistics)
-+
-+
-+    def SetStatistics(self, cat_id, attrs_dict):
-+        self.stats_data.statisticsSet.disconnect(self.SetCategory)
-+        self.stats_data.GetStatistics(cat_id).SetStatistics(attrs_dict)
-+        self.stats_data.statisticsSet.connect(self.SetCategory)
-+
-+    def AddStatistics(self, cat_id, name, color):
-+        self.stats_data.statisticsAdded.disconnect(self.AddCategory)
-+        self.stats_data.AddStatistics(cat_id, name, color)
-+        self.stats_data.statisticsAdded.connect(self.AddCategory)
-+
-+    def DeleteStatistics(self, cat_id):
-+        self.stats_data.statisticsDeleted.disconnect(self.DeleteCategory)
-+        self.stats_data.DeleteStatistics(cat_id)
-+        self.stats_data.statisticsDeleted.connect(self.DeleteCategory)
+     def OnVNet(self, event):
+         """!Dialog for v.net* modules 
+         """
 Index: gui/wxpython/vdigit/wxdigit.py
 ===================================================================
---- gui/wxpython/vdigit/wxdigit.py	(revision 57285)
+--- gui/wxpython/vdigit/wxdigit.py	(revision 57336)
 +++ gui/wxpython/vdigit/wxdigit.py	(working copy)
 @@ -17,7 +17,7 @@
  (and NumPy would be an excellent candidate for acceleration via
@@ -3006,7 +3160,7 @@
      def GetLineCats(self, line):
 Index: gui/wxpython/vdigit/toolbars.py
 ===================================================================
---- gui/wxpython/vdigit/toolbars.py	(revision 57285)
+--- gui/wxpython/vdigit/toolbars.py	(revision 57336)
 +++ gui/wxpython/vdigit/toolbars.py	(working copy)
 @@ -17,6 +17,7 @@
  import wx
@@ -3035,7 +3189,7 @@
      def StopEditing(self):
 Index: gui/wxpython/Makefile
 ===================================================================
---- gui/wxpython/Makefile	(revision 57285)
+--- gui/wxpython/Makefile	(revision 57336)
 +++ gui/wxpython/Makefile	(working copy)
 @@ -13,7 +13,7 @@
  	$(wildcard animation/* core/*.py dbmgr/* gcp/*.py gmodeler/* \
@@ -3055,555 +3209,11 @@
  
  DSTDIRS := $(patsubst %,$(ETCDIR)/%,icons scripts xml)
  
-Index: gui/wxpython/mapdisp/toolbars.py
-===================================================================
---- gui/wxpython/mapdisp/toolbars.py	(revision 57285)
-+++ gui/wxpython/mapdisp/toolbars.py	(working copy)
-@@ -243,7 +243,8 @@
-                       (MapIcons["scatter"],     self.parent.OnScatterplot),
-                       (MapIcons["histogram"],   self.parent.OnHistogramPyPlot),
-                       (BaseIcons["histogramD"], self.parent.OnHistogram),
--                      (MapIcons["vnet"],        self.parent.OnVNet)))
-+                      (MapIcons["vnet"],        self.parent.OnVNet),
-+                      (MapIcons["scatter"],     self.parent.OnScatterplot2)))
-         
-     def OnDecoration(self, event):
-         """!Decorations overlay menu
-Index: gui/wxpython/mapdisp/frame.py
-===================================================================
---- gui/wxpython/mapdisp/frame.py	(revision 57285)
-+++ gui/wxpython/mapdisp/frame.py	(working copy)
-@@ -207,6 +207,7 @@
-         #
-         self.dialogs = {}
-         self.dialogs['attributes'] = None
-+        self.dialogs['scatt_plot'] = None
-         self.dialogs['category'] = None
-         self.dialogs['barscale'] = None
-         self.dialogs['legend'] = None
-@@ -1301,6 +1302,19 @@
-         """!Returns toolbar with zooming tools"""
-         return self.toolbars['map']
- 
-+    def OnScatterplot2(self, event):
-+        """!Init interactive scatterplot tools
-+        """
-+        if self.dialogs['scatt_plot']:
-+            self.dialogs['scatt_plot'].Raise()
-+            return
-+
-+        from scatt_plot.dialogs import ScattPlotMainDialog
-+        self.dialogs['scatt_plot'] = ScattPlotMainDialog(parent=self, giface=self._giface)
-+        
-+        self.dialogs['scatt_plot'].CenterOnScreen()
-+        self.dialogs['scatt_plot'].Show()
-+
-     def OnVNet(self, event):
-         """!Dialog for v.net* modules 
-         """
-Index: lib/vector/vedit/move.c
-===================================================================
---- lib/vector/vedit/move.c	(revision 57285)
-+++ lib/vector/vedit/move.c	(working copy)
-@@ -22,13 +22,16 @@
-   \param List list of primitives to be moved
-   \param move_x,move_y,move_z direction (move_z used only if map is 3D)
-   \param snap enable snapping (see globals.h)
--  
-+  \param new_ids list of newly assigned ids for features, which vertexes were moved,
-+  		 new_id corresponds to same position of id in List
-+  		 null pointer can be passed
-+
-   \return number of modified primitives
-   \return -1 on error
- */
- int Vedit_move_lines(struct Map_info *Map, struct Map_info **BgMap,
- 		     int nbgmaps, struct ilist *List, double move_x,
--		     double move_y, double move_z, int snap, double thresh)
-+		     double move_y, double move_z, int snap, double thresh, struct ilist *new_ids)
- {
-     struct line_pnts *Points;
-     struct line_cats *Cats;
-@@ -84,6 +87,8 @@
- 	if (newline < 0) {
- 	    return -1;
- 	}
-+	if(new_ids)
-+	    Vect_list_append(new_ids, newline);
- 
- 	nlines_moved++;
-     }
-Index: lib/vector/vedit/vertex.c
-===================================================================
---- lib/vector/vedit/vertex.c	(revision 57285)
-+++ lib/vector/vedit/vertex.c	(working copy)
-@@ -26,7 +26,10 @@
-   \param move_x,move_y,move_z direction (move_z is used when map is 3D)
-   \param move_first move only first vertex found in the bounding box
-   \param snap snapping mode (see vedit.h)
--  
-+  \param new_ids list of newly assigned ids for features, which vertexes were moved,
-+  		 new_id corresponds to same position of id in List
-+  		 if feature was not rewritten new id is -1
-+  		 null pointer can be passed
-   \return number of moved verteces
-   \return -1 on error
- */
-@@ -34,11 +37,11 @@
- 		      int nbgmaps, struct ilist *List,
- 		      struct line_pnts *coord, double thresh_coords,
- 		      double thresh_snap, double move_x, double move_y,
--		      double move_z, int move_first, int snap)
-+		      double move_z, int move_first, int snap, struct ilist *new_ids)
- {
-     int nvertices_moved, nlines_modified, nvertices_snapped;
- 
--    int i, j, k;
-+    int i, j, k, newline;
-     int line, type, rewrite;
-     int npoints;
-     double east, north, dist;
-@@ -159,12 +162,17 @@
- 	}			/* for each coord */
- 
- 	if (rewrite) {
--	    if (Vect_rewrite_line(Map, line, type, Points, Cats) < 0) {
-+	    newline = Vect_rewrite_line(Map, line, type, Points, Cats);
-+	    if (newline < 0) {
- 		return -1;
- 	    }
-+	    if(new_ids)
-+		Vect_list_append(new_ids, newline);
- 
- 	    nlines_modified++;
- 	}
-+	else if(new_ids)
-+	    Vect_list_append(new_ids, -1);
-     }				/* for each selected line */
- 
-     /* destroy structures */
-@@ -187,12 +195,15 @@
-   \param List list of lines
-   \param coord points location
-   \param thresh find line in given threshold
--  
-+  \param new_ids list of newly assigned ids for features, which vertexes were moved,
-+  		 new_id corresponds to same position of id in List
-+  		 if feature was not rewritten new id is -1
-+  		 null pointer can be passed
-   \return number of add verteces
-   \return -1 on error
- */
- int Vedit_add_vertex(struct Map_info *Map, struct ilist *List,
--		     struct line_pnts *coord, double thresh)
-+		     struct line_pnts *coord, double thresh, struct ilist *new_ids)
- {
-     int i, j;
-     int type, line, seg;
-@@ -200,6 +211,7 @@
-     double east, north, dist;
-     double *x, *y, *z;
-     double px, py;
-+    int newline;
- 
-     struct line_pnts *Points;
-     struct line_cats *Cats;
-@@ -253,12 +265,17 @@
- 	/* rewrite the line */
- 	if (rewrite) {
- 	    Vect_line_prune(Points);
--	    if (Vect_rewrite_line(Map, line, type, Points, Cats) < 0) {
-+	    newline = Vect_rewrite_line(Map, line, type, Points, Cats);
-+	    if (newline < 0) {
- 		return -1;
- 	    }
-+	    if(new_ids)
-+		Vect_list_append(new_ids, newline);
- 
- 	    nlines_modified++;
- 	}
-+	else if(new_ids)
-+	    Vect_list_append(new_ids, -1);
-     }				/* for each line */
- 
-     /* destroy structures */
-@@ -277,12 +294,15 @@
-   \param List list of selected lines
-   \param coord points location
-   \param thresh threshold value to find a line
--  
-+  \param new_ids list of newly assigned ids for features, which vertexes were moved,
-+  		new_id corresponds to same position of id in List
-+  		if feature was not rewritten new id is -1
-+  		null pointer can be passed
-   \return number of removed vertices
-   \return -1 on error
- */
- int Vedit_remove_vertex(struct Map_info *Map, struct ilist *List,
--			struct line_pnts *coord, double thresh)
-+			struct line_pnts *coord, double thresh, struct ilist *new_ids)
- {
-     int i, j, k;
-     int type, line;
-@@ -290,6 +310,7 @@
-     double east, north;
-     double dist;
-     double *x, *y, *z;
-+    int newline;
- 
-     struct line_pnts *Points;
-     struct line_cats *Cats;
-@@ -336,12 +357,18 @@
- 
- 	if (rewrite) {
- 	    /* rewrite the line */
--	    if (Vect_rewrite_line(Map, line, type, Points, Cats) < 0) {
-+	    newline = Vect_rewrite_line(Map, line, type, Points, Cats); 
-+	    if (newline < 0) {
- 		return -1;
- 	    }
-+	    if(new_ids)
-+		Vect_list_append(new_ids, newline);
- 
- 	    nlines_modified++;
- 	}
-+	else if(new_ids)
-+	    Vect_list_append(new_ids, -1);
-+
-     }				/* for each line */
- 
-     /* destroy structures */
-Index: lib/imagery/scatt_sccats.c
-===================================================================
---- lib/imagery/scatt_sccats.c	(revision 0)
-+++ lib/imagery/scatt_sccats.c	(working copy)
-@@ -0,0 +1,321 @@
-+/*!
-+   \file lib/imagery/scatt_cat_rast.c
-+
-+   \brief Imagery library - functions for wx Scatter Plot Tool.
-+
-+   Low level functions used by wx Scatter Plot Tool.
-+
-+   Copyright (C) 2013 by the GRASS Development Team
-+
-+   This program is free software under the GNU General Public License
-+   (>=v2).  Read the file COPYING that comes with GRASS for details.
-+
-+   \author Stepan Turek <stepan.turek at seznam.cz> (Mentor: Martin Landa)
-+ */
-+
-+#include <grass/raster.h>
-+#include <grass/imagery.h>
-+#include <grass/gis.h>
-+
-+#include <stdio.h>
-+#include <stdlib.h>
-+#include <math.h>
-+#include <string.h>
-+
-+//TODO split formulas to be more understandable
-+static void id_scatt_to_bands(const int scatt_id, const int n_bands, int * band_1, int * band_2)
-+{   
-+    int n_b1 = n_bands - 1;
-+
-+    * band_1 = (int) ((2 * n_b1 + 1 - sqrt((double)((2 * n_b1 + 1) * (2 * n_b1 + 1) - 8 * scatt_id))) / 2);
-+
-+    * band_2 = scatt_id - ((* band_1) * (2 * n_b1 + 1) - (* band_1) * (* band_1)) / 2 + (* band_1) + 1;
-+
-+    return;
-+}
-+
-+static void bands_to_id_scatt(const int band_1, const int band_2, const int n_bands, int * scatt_id)
-+{   
-+    int n_b1 = n_bands - 1;
-+
-+    * scatt_id = (band_1 * (2 * n_b1 + 1) - band_1 * band_1) / 2 + band_2 - band_1 - 1;
-+
-+    return;
-+}
-+
-+void I_sc_init_cats(struct scCats * cats, int n_bands, int type)
-+{
-+    int i_cat;
-+
-+    cats->type = type;
-+
-+    cats->n_cats = 10;
-+    cats->n_a_cats = 0;
-+
-+    cats->n_bands = n_bands;
-+    cats->n_scatts = (n_bands - 1) * n_bands / 2;
-+
-+    cats->cats_arr = (struct scScatts **) malloc(cats->n_cats * sizeof(struct scScatts *));
-+    memset(cats->cats_arr, 0, cats-> n_cats * sizeof(struct scScatts *));
-+
-+    cats->cats_ids = (int *)  malloc(cats->n_cats * sizeof(int));
-+    cats->cats_idxs =(int *)  malloc(cats->n_cats * sizeof(int));
-+
-+    for(i_cat = 0; i_cat < cats->n_cats; i_cat++)
-+        cats->cats_idxs[i_cat] = -1;
-+
-+    return;
-+}
-+
-+void I_sc_free_cats(struct scCats * cats)
-+{
-+    int i_cat;
-+
-+    for(i_cat = 0; i_cat < cats->n_a_cats; i_cat++)
-+    {        
-+        if(cats->cats_arr[i_cat])
-+        {   
-+            free(cats->cats_arr[i_cat]->scatt_idxs);
-+            free(cats->cats_arr[i_cat]->scatts_bands);
-+            free(cats->cats_arr[i_cat]->scatts_arr);
-+            free(cats->cats_arr[i_cat]);
-+        }
-+    }
-+
-+    free(cats->cats_ids);
-+    free(cats->cats_idxs);
-+    free(cats->cats_arr);
-+
-+    cats->n_cats = 0;
-+    cats->n_a_cats = 0;
-+    cats->n_bands = 0;
-+    cats->n_scatts = 0;
-+    cats->type = -1;
-+
-+    return;
-+}
-+
-+void I_sc_get_active_categories(int * a_cats_ids, int * n_a_cats, struct scCats * cats)
-+{
-+    a_cats_ids = cats->cats_ids;
-+    * n_a_cats = cats->n_a_cats;
-+}
-+
-+int I_sc_add_cat(struct scCats * cats, int cat_id)
-+{
-+    int i_scatt;
-+    int n_a_cats = cats->n_a_cats;
-+
-+    if(cat_id < 0 || cat_id >= cats->n_cats)
-+        return -1;
-+
-+    if(cats->cats_idxs[cat_id] >= 0) 
-+        return -1;
-+
-+    cats->cats_ids[n_a_cats] = cat_id;
-+    cats->cats_idxs[cat_id] = n_a_cats;
-+    
-+    cats->cats_arr[n_a_cats] = (struct scScatts *) malloc(sizeof(struct scScatts));
-+
-+    cats->cats_arr[n_a_cats]->scatts_arr = (struct scdScattData **) malloc(cats->n_scatts * sizeof(struct scdScattData *));
-+    memset((cats->cats_arr[n_a_cats]->scatts_arr), 0, cats->n_scatts * sizeof(struct scdScattData *));
-+    
-+    cats->cats_arr[n_a_cats]->n_a_scatts = 0;
-+
-+    cats->cats_arr[n_a_cats]->scatts_bands = (int *) malloc(cats->n_scatts * 2 * sizeof(int));
-+     
-+    cats->cats_arr[n_a_cats]->scatt_idxs = (int *) malloc(cats->n_scatts * sizeof(int));
-+    for(i_scatt = 0; i_scatt < cats->n_scatts; i_scatt++)
-+        cats->cats_arr[n_a_cats]->scatt_idxs[i_scatt] = -1;
-+    
-+    ++cats->n_a_cats;
-+
-+    return 0;
-+}
-+
-+int I_sc_delete_cat(struct scCats * cats, int cat_id)
-+{
-+    int cat_idx, i_cat;
-+
-+    if(cat_id < 0 || cat_id >= cats->n_cats)
-+        return -1;
-+
-+    cat_idx = cats->cats_idxs[cat_id];
-+    if(cat_idx < 0)
-+        return -1;
-+
-+    free(cats->cats_arr[cat_idx]->scatt_idxs);
-+    free(cats->cats_arr[cat_idx]->scatts_bands);
-+    free(cats->cats_arr[cat_idx]->scatts_arr);
-+    free(cats->cats_arr[cat_idx]);
-+
-+    for(i_cat = cat_idx; i_cat < cats->n_a_cats - 1; i_cat++)
-+    {
-+        cats->cats_arr[i_cat] = cats->cats_arr[i_cat + 1];
-+        cats->cats_ids[i_cat] = cats->cats_ids[i_cat + 1];
-+    }
-+    cats->cats_idxs[cat_id] = -1; 
-+
-+    --cats->n_a_cats;
-+    
-+    return 0;
-+}
-+    
-+
-+int I_sc_insert_scatt_data(struct scCats * cats, struct scdScattData * scatt_vals, int cat_id, int scatt_id)
-+{
-+    int band_1, band_2, cat_idx, n_a_scatts;
-+    struct scScatts * scatts;
-+
-+    if(cat_id < 0 || cat_id >= cats->n_cats)
-+        return -1;
-+
-+    cat_idx = cats->cats_idxs[cat_id];
-+    if(cat_idx < 0)
-+        return -1;
-+
-+    if(scatt_id < 0 && scatt_id >= cats->n_scatts)
-+        return -1;
-+
-+    scatts = cats->cats_arr[cat_idx];
-+    if(scatts->scatt_idxs[scatt_id] >= 0)
-+        return -1;
-+
-+    if(!scatt_vals->b_conds_arr && cats->type == 1)
-+        return -1;
-+
-+    if(!scatt_vals->scatt_vals_arr && cats->type == 0)
-+        return -1;
-+
-+    n_a_scatts = scatts->n_a_scatts;
-+
-+    scatts->scatt_idxs[scatt_id] = n_a_scatts;
-+
-+    id_scatt_to_bands(scatt_id, cats->n_bands, &band_1, &band_2);
-+
-+    scatts->scatts_bands[n_a_scatts * 2] = band_1;
-+    scatts->scatts_bands[n_a_scatts * 2 + 1] = band_2;
-+
-+    scatts->scatts_arr[n_a_scatts] = scatt_vals;
-+    ++scatts->n_a_scatts;
-+
-+    return 0;
-+}
-+
-+int I_sc_remove_scatt_data(struct scCats * cats, struct scdScattData * scatt_vals, int cat_id, int scatt_id)
-+{
-+    int cat_idx, scatt_idx, n_init_scatts, i_scatt;
-+    struct scScatts * scatts;
-+
-+    if(cat_id < 0 && cat_id >= cats->n_cats)
-+        return -1;
-+
-+    cat_idx = cats->cats_idxs[cat_id];
-+    if(cat_idx < 0)
-+        return -1;
-+
-+    if(scatt_id < 0 || scatt_id >= cats->n_scatts)
-+        return -1;
-+
-+    scatts = cats->cats_arr[cat_idx];
-+    if(scatts->scatt_idxs[scatt_id] < 0)
-+        return -1;
-+
-+    scatt_vals = scatts->scatts_arr[scatt_idx];
-+
-+    for(i_scatt = scatt_idx; i_scatt < scatts->n_a_scatts - 1; i_scatt++)
-+    {
-+        scatts->scatts_arr[i_scatt] = scatts->scatts_arr[i_scatt + 1];
-+        scatts->scatts_bands[i_scatt * 2] = scatts->scatts_bands[(i_scatt + 1)* 2];
-+        scatts->scatts_bands[i_scatt * 2 + 1] = scatts->scatts_bands[(i_scatt + 1) * 2 + 1];
-+    }
-+    scatts->scatts_arr[scatts->n_a_scatts] = NULL;
-+
-+    scatts->scatt_idxs[scatt_id] = -1;
-+
-+    scatt_vals = scatts->scatts_arr[scatt_id];
-+    scatts->n_a_scatts--;
-+
-+    return 0;
-+}
-+
-+int I_sc_set_value(struct scCats * cats, int cat_id, int scatt_id, int value_idx, int value)
-+{
-+    int n_a_scatts = cats->cats_arr[cat_id]->n_a_scatts;
-+    int cat_idx, scatt_idx, ret;
-+
-+    cat_idx = cats->cats_idxs[cat_id];
-+    if(cat_idx < 0)
-+        return -1;
-+    
-+    if(cats->cats_arr[cat_idx]->scatt_idxs[scatt_id] < 0)
-+        return -1;
-+
-+    cat_idx = cats->cats_idxs[cat_id];
-+    scatt_idx = cats->cats_arr[cat_idx]->scatt_idxs[scatt_id];
-+
-+    I_scd_set_value(cats->cats_arr[cat_idx]->scatts_arr[scatt_idx], value_idx, value);
-+
-+    return 0;
-+}
-+
-+void I_scd_init_scatt_data(struct scdScattData * scatt_vals, int n_vals, int type)
-+{
-+    scatt_vals->n_vals = n_vals;
-+
-+    if(type == 0)
-+    {   
-+        scatt_vals->scatt_vals_arr = (unsigned int *) malloc(n_vals * sizeof(unsigned int));
-+        memset(scatt_vals->scatt_vals_arr, 0, n_vals * sizeof(unsigned int));
-+        scatt_vals->b_conds_arr = NULL;
-+    }
-+    else if(type == 1)
-+    {   
-+        scatt_vals->b_conds_arr = (unsigned short *) malloc(n_vals * sizeof(unsigned short));
-+        memset(scatt_vals->b_conds_arr, 0, n_vals * sizeof(unsigned short));
-+        scatt_vals->scatt_vals_arr = NULL;
-+    }
-+
-+    return;
-+}
-+
-+void I_scd_free_scatt_data(struct scdScattData * scatt_vals)
-+{
-+
-+    free(scatt_vals->b_conds_arr);
-+    free(scatt_vals->scatt_vals_arr);
-+
-+    scatt_vals = NULL;
-+
-+    return;
-+}
-+
-+int I_scd_get_data_size(struct scdScattData * scatt_vals)
-+{
-+    return scatt_vals->n_vals;
-+}
-+
-+void * I_scd_get_data_ptr(struct scdScattData * scatt_vals)
-+{
-+    if(!scatt_vals->b_conds_arr)
-+        return scatt_vals->b_conds_arr;
-+    else if(!scatt_vals->scatt_vals_arr)
-+        return scatt_vals->scatt_vals_arr;
-+
-+    return NULL;
-+}
-+
-+int I_scd_set_value(struct scdScattData * scatt_vals, unsigned int val_idx, unsigned int val)
-+{
-+    if(val_idx < 0 && val_idx >  scatt_vals->n_vals)
-+        return -1;
-+
-+    if(scatt_vals->b_conds_arr)
-+        scatt_vals->b_conds_arr[val_idx] = val;
-+    else if(scatt_vals->scatt_vals_arr)
-+        scatt_vals->scatt_vals_arr[val_idx] = val;
-+    else
-+        return -1;
-+
-+    return 0;
-+}
 Index: lib/imagery/scatt.c
 ===================================================================
 --- lib/imagery/scatt.c	(revision 0)
 +++ lib/imagery/scatt.c	(working copy)
-@@ -0,0 +1,582 @@
+@@ -0,0 +1,610 @@
 +/*!
 +   \file lib/imagery/scatt.c
 +
@@ -3837,22 +3447,31 @@
 +
 +static inline void update_cat_scatt_plt(CELL ** chunks, char ** null_chunks, int chunk_size, unsigned short * belongs_pix, struct scScatts * scatts)
 +{
-+    int band_axis_1, band_axis_2, i_scatt, array_idx, cat_idx, i_chunks_pix;
-+    int r_bits = 256;
++    int band_axis_1, band_axis_2, i_scatt, array_idx, cat_idx, i_chunks_pix, max_arr_idx;
 +
-+    CELL * band_1_chunks;
-+    CELL * band_2_chunks;
++    CELL * b_1_chunks;
++    CELL * b_2_chunks;
 +    char * band_1_null_chunks,* band_2_null_chunks;
 +
++    struct Range b_1_range, b_2_range;
++    int b_1_range_size;
++
 +    int * scatts_bands = scatts->scatts_bands;
++
 +    for(i_scatt = 0; i_scatt < scatts->n_a_scatts; i_scatt++)
 +    {   
-+        band_1_chunks = chunks[scatts_bands[i_scatt * 2]];
-+        band_2_chunks = chunks[scatts_bands[i_scatt * 2 + 1]];
++        b_1_chunks = chunks[scatts_bands[i_scatt * 2]];
++        b_2_chunks = chunks[scatts_bands[i_scatt * 2 + 1]];
 +
 +        band_1_null_chunks =  null_chunks[scatts_bands[i_scatt * 2]];
 +        band_2_null_chunks =  null_chunks[scatts_bands[i_scatt * 2 + 1]];
 +
++        b_1_range = scatts->scatts_arr[i_scatt]->band_1_range;
++        b_2_range = scatts->scatts_arr[i_scatt]->band_2_range;
++
++        b_1_range_size = b_1_range.max - b_1_range.min + 1;
++        max_arr_idx = (b_1_range.max -  b_1_range.min + 1) * (b_2_range.max -  b_2_range.min + 1);
++
 +        for(i_chunks_pix = 0; i_chunks_pix < chunk_size; i_chunks_pix++)
 +        {
 +            if(!belongs_pix[i_chunks_pix] || 
@@ -3860,8 +3479,12 @@
 +                band_2_null_chunks[i_chunks_pix] == 1)                
 +                continue;
 +
-+            array_idx = band_1_chunks[i_chunks_pix] + band_2_chunks[i_chunks_pix] * r_bits;
++            array_idx = b_1_chunks[i_chunks_pix] - b_1_range.min + (b_2_chunks[i_chunks_pix] - b_2_range.min) * b_1_range_size;
 +
++            if(array_idx < 0 || array_idx >= max_arr_idx) {
++                G_warning ("pixel out of range");
++                continue;
++            }
 +            ++scatts->scatts_arr[i_scatt]->scatt_vals_arr[array_idx];
 +        }
 +    }
@@ -3873,21 +3496,22 @@
 +{
 +
 +    int i_chunks_pix, i_cat, i_scatt, n_a_scatts, i_cond;
-+    int cat_id, scatt_plts_cat_idx, array_idx;
++    int cat_id, scatt_plts_cat_idx, array_idx, max_arr_idx;
 +    char * band_1_null_chunks,* band_2_null_chunks;
 +    
-+    int r_bits = 256;
-+
 +    struct scScatts * scatts_conds;
 +    struct scScatts * scatt_plts_scatts;
 +    struct scdScattData * conds;
 +
++    struct Range b_1_range, b_2_range;
++    int b_1_range_size;
++
 +    int * scatts_bands;
 +    struct scdScattData ** scatts_arr;
 +
-+    CELL * band_1_chunks;
-+    CELL * band_2_chunks;
-+    unsigned int * i_scatt_conds;
++    CELL * b_1_chunks;
++    CELL * b_2_chunks;
++    unsigned char * i_scatt_conds;
 +
 +    unsigned short * belongs_pix = (unsigned short *) G_malloc(chunk_size * sizeof(unsigned short)); 
 +    unsigned char * rast_pixs = (unsigned char *) G_malloc(chunk_size * sizeof(unsigned char));
@@ -3936,14 +3560,22 @@
 +            // test every defined conditions in scatter plots
 +            for(i_scatt = 0; i_scatt < scatts_conds->n_a_scatts; i_scatt++)
 +            {   
-+                band_1_chunks =  chunks[scatts_bands[i_scatt * 2]];
-+                band_2_chunks =  chunks[scatts_bands[i_scatt * 2 + 1]];
++                b_1_chunks =  chunks[scatts_bands[i_scatt * 2]];
++                b_2_chunks =  chunks[scatts_bands[i_scatt * 2 + 1]];
 +
 +                band_1_null_chunks =  null_chunks[scatts_bands[i_scatt * 2]];
 +                band_2_null_chunks =  null_chunks[scatts_bands[i_scatt * 2 + 1]];
 +
 +                i_scatt_conds = scatts_conds->scatts_arr[i_scatt]->b_conds_arr;
 +
++                b_1_range = scatts_conds->scatts_arr[i_scatt]->band_1_range;
++                b_2_range = scatts_conds->scatts_arr[i_scatt]->band_2_range;
++
++                b_1_range_size = b_1_range.max - b_1_range.min + 1;
++
++                max_arr_idx = (b_1_range.max -  b_1_range.min + 1) * (b_2_range.max -  b_2_range.min + 1);
++                //G_message("max_arr_idx scatt_conds: %d", max_arr_idx);
++
 +                for(i_chunks_pix = 0; i_chunks_pix < chunk_size; i_chunks_pix++)
 +                {
 +                    if(belongs_pix[i_chunks_pix] || 
@@ -3951,7 +3583,13 @@
 +                       band_2_null_chunks[i_chunks_pix] == 1)
 +                        continue;
 +
-+                    if(i_scatt_conds[band_1_chunks[i_chunks_pix] + band_2_chunks[i_chunks_pix] * r_bits])
++                    array_idx = b_1_chunks[i_chunks_pix] - b_1_range.min + (b_2_chunks[i_chunks_pix] - b_2_range.min) * b_1_range_size;
++                    /*TODO test value */
++                    if(array_idx < 0 || array_idx >= max_arr_idx) {
++                        G_warning ("pixel out of range");
++                        continue;
++                    }
++                    if(i_scatt_conds[array_idx])
 +                        belongs_pix[i_chunks_pix] = 1;
 +                }                
 +            }
@@ -4187,3 +3825,522 @@
 +    return 0;    
 +}
 \ No newline at end of file
+Index: lib/imagery/scatt_sccats.c
+===================================================================
+--- lib/imagery/scatt_sccats.c	(revision 0)
++++ lib/imagery/scatt_sccats.c	(working copy)
+@@ -0,0 +1,342 @@
++/*!
++   \file lib/imagery/scatt_cat_rast.c
++
++   \brief Imagery library - functions for wx Scatter Plot Tool.
++
++   Low level functions used by wx Scatter Plot Tool.
++
++   Copyright (C) 2013 by the GRASS Development Team
++
++   This program is free software under the GNU General Public License
++   (>=v2).  Read the file COPYING that comes with GRASS for details.
++
++   \author Stepan Turek <stepan.turek at seznam.cz> (Mentor: Martin Landa)
++ */
++
++#include <grass/raster.h>
++#include <grass/imagery.h>
++#include <grass/gis.h>
++
++#include <stdio.h>
++#include <stdlib.h>
++#include <math.h>
++#include <string.h>
++
++//TODO split formulas to be more understandable
++static void id_scatt_to_bands(const int scatt_id, const int n_bands, int * band_1, int * band_2)
++{   
++    int n_b1 = n_bands - 1;
++
++    * band_1 = (int) ((2 * n_b1 + 1 - sqrt((double)((2 * n_b1 + 1) * (2 * n_b1 + 1) - 8 * scatt_id))) / 2);
++
++    * band_2 = scatt_id - ((* band_1) * (2 * n_b1 + 1) - (* band_1) * (* band_1)) / 2 + (* band_1) + 1;
++
++    return;
++}
++
++static void bands_to_id_scatt(const int band_1, const int band_2, const int n_bands, int * scatt_id)
++{   
++    int n_b1 = n_bands - 1;
++
++    * scatt_id = (band_1 * (2 * n_b1 + 1) - band_1 * band_1) / 2 + band_2 - band_1 - 1;
++
++    return;
++}
++
++void I_sc_init_cats(struct scCats * cats, int n_bands, int type)
++{
++    int i_cat;
++
++    cats->type = type;
++
++    cats->n_cats = 10;
++    cats->n_a_cats = 0;
++
++    cats->n_bands = n_bands;
++    cats->n_scatts = (n_bands - 1) * n_bands / 2;
++
++    cats->cats_arr = (struct scScatts **) malloc(cats->n_cats * sizeof(struct scScatts *));
++    memset(cats->cats_arr, 0, cats-> n_cats * sizeof(struct scScatts *));
++
++    cats->cats_ids = (int *)  malloc(cats->n_cats * sizeof(int));
++    cats->cats_idxs =(int *)  malloc(cats->n_cats * sizeof(int));
++
++    for(i_cat = 0; i_cat < cats->n_cats; i_cat++)
++        cats->cats_idxs[i_cat] = -1;
++
++    return;
++}
++
++void I_sc_free_cats(struct scCats * cats)
++{
++    int i_cat;
++
++    for(i_cat = 0; i_cat < cats->n_a_cats; i_cat++)
++    {        
++        if(cats->cats_arr[i_cat])
++        {   
++            free(cats->cats_arr[i_cat]->scatt_idxs);
++            free(cats->cats_arr[i_cat]->scatts_bands);
++            free(cats->cats_arr[i_cat]->scatts_arr);
++            free(cats->cats_arr[i_cat]);
++        }
++    }
++
++    free(cats->cats_ids);
++    free(cats->cats_idxs);
++    free(cats->cats_arr);
++
++    cats->n_cats = 0;
++    cats->n_a_cats = 0;
++    cats->n_bands = 0;
++    cats->n_scatts = 0;
++    cats->type = -1;
++
++    return;
++}
++
++void I_sc_get_active_categories(int * a_cats_ids, int * n_a_cats, struct scCats * cats)
++{
++    a_cats_ids = cats->cats_ids;
++    * n_a_cats = cats->n_a_cats;
++}
++
++int I_sc_add_cat(struct scCats * cats, int cat_id)
++{
++    int i_scatt;
++    int n_a_cats = cats->n_a_cats;
++
++    if(cat_id < 0 || cat_id >= cats->n_cats)
++        return -1;
++
++    if(cats->cats_idxs[cat_id] >= 0) 
++        return -1;
++
++    cats->cats_ids[n_a_cats] = cat_id;
++    cats->cats_idxs[cat_id] = n_a_cats;
++    
++    cats->cats_arr[n_a_cats] = (struct scScatts *) malloc(sizeof(struct scScatts));
++
++    cats->cats_arr[n_a_cats]->scatts_arr = (struct scdScattData **) malloc(cats->n_scatts * sizeof(struct scdScattData *));
++    memset((cats->cats_arr[n_a_cats]->scatts_arr), 0, cats->n_scatts * sizeof(struct scdScattData *));
++    
++    cats->cats_arr[n_a_cats]->n_a_scatts = 0;
++
++    cats->cats_arr[n_a_cats]->scatts_bands = (int *) malloc(cats->n_scatts * 2 * sizeof(int));
++     
++    cats->cats_arr[n_a_cats]->scatt_idxs = (int *) malloc(cats->n_scatts * sizeof(int));
++    for(i_scatt = 0; i_scatt < cats->n_scatts; i_scatt++)
++        cats->cats_arr[n_a_cats]->scatt_idxs[i_scatt] = -1;
++    
++    ++cats->n_a_cats;
++
++    return 0;
++}
++
++int I_sc_delete_cat(struct scCats * cats, int cat_id)
++{
++    int cat_idx, i_cat;
++
++    if(cat_id < 0 || cat_id >= cats->n_cats)
++        return -1;
++
++    cat_idx = cats->cats_idxs[cat_id];
++    if(cat_idx < 0)
++        return -1;
++
++    free(cats->cats_arr[cat_idx]->scatt_idxs);
++    free(cats->cats_arr[cat_idx]->scatts_bands);
++    free(cats->cats_arr[cat_idx]->scatts_arr);
++    free(cats->cats_arr[cat_idx]);
++
++    for(i_cat = cat_idx; i_cat < cats->n_a_cats - 1; i_cat++)
++    {
++        cats->cats_arr[i_cat] = cats->cats_arr[i_cat + 1];
++        cats->cats_ids[i_cat] = cats->cats_ids[i_cat + 1];
++    }
++    cats->cats_idxs[cat_id] = -1; 
++
++    --cats->n_a_cats;
++    
++    return 0;
++}
++    
++
++int I_sc_insert_scatt_data(struct scCats * cats, struct scdScattData * scatt_data, int cat_id, int scatt_id)
++{
++    int band_1, band_2, cat_idx, n_a_scatts;
++    struct scScatts * scatts;
++
++    if(cat_id < 0 || cat_id >= cats->n_cats)
++        return -1;
++
++    cat_idx = cats->cats_idxs[cat_id];
++    if(cat_idx < 0)
++        return -1;
++
++    if(scatt_id < 0 && scatt_id >= cats->n_scatts)
++        return -1;
++
++    scatts = cats->cats_arr[cat_idx];
++    if(scatts->scatt_idxs[scatt_id] >= 0)
++        return -1;
++
++    if(!scatt_data->b_conds_arr && cats->type == SC_SCATT_CONDITIONS)
++        return -1;
++
++    if(!scatt_data->scatt_vals_arr && cats->type == SC_SCATT_DATA)
++        return -1;
++
++    n_a_scatts = scatts->n_a_scatts;
++
++    scatts->scatt_idxs[scatt_id] = n_a_scatts;
++
++    id_scatt_to_bands(scatt_id, cats->n_bands, &band_1, &band_2);
++
++    scatts->scatts_bands[n_a_scatts * 2] = band_1;
++    scatts->scatts_bands[n_a_scatts * 2 + 1] = band_2;
++
++    scatts->scatts_arr[n_a_scatts] = scatt_data;
++    ++scatts->n_a_scatts;
++
++    return 0;
++}
++
++int I_sc_remove_scatt_data(struct scCats * cats, struct scdScattData * scatt_data, int cat_id, int scatt_id)
++{
++    int cat_idx, scatt_idx, n_init_scatts, i_scatt;
++    struct scScatts * scatts;
++
++    if(cat_id < 0 && cat_id >= cats->n_cats)
++        return -1;
++
++    cat_idx = cats->cats_idxs[cat_id];
++    if(cat_idx < 0)
++        return -1;
++
++    if(scatt_id < 0 || scatt_id >= cats->n_scatts)
++        return -1;
++
++    scatts = cats->cats_arr[cat_idx];
++    if(scatts->scatt_idxs[scatt_id] < 0)
++        return -1;
++
++    scatt_data = scatts->scatts_arr[scatt_idx];
++
++    for(i_scatt = scatt_idx; i_scatt < scatts->n_a_scatts - 1; i_scatt++)
++    {
++        scatts->scatts_arr[i_scatt] = scatts->scatts_arr[i_scatt + 1];
++        scatts->scatts_bands[i_scatt * 2] = scatts->scatts_bands[(i_scatt + 1)* 2];
++        scatts->scatts_bands[i_scatt * 2 + 1] = scatts->scatts_bands[(i_scatt + 1) * 2 + 1];
++    }
++    scatts->scatts_arr[scatts->n_a_scatts] = NULL;
++
++    scatts->scatt_idxs[scatt_id] = -1;
++
++    scatt_data = scatts->scatts_arr[scatt_id];
++    scatts->n_a_scatts--;
++
++    return 0;
++}
++
++int I_sc_set_value(struct scCats * cats, int cat_id, int scatt_id, int value_idx, int value)
++{
++    int n_a_scatts = cats->cats_arr[cat_id]->n_a_scatts;
++    int cat_idx, scatt_idx, ret;
++
++    cat_idx = cats->cats_idxs[cat_id];
++    if(cat_idx < 0)
++        return -1;
++    
++    if(cats->cats_arr[cat_idx]->scatt_idxs[scatt_id] < 0)
++        return -1;
++
++    cat_idx = cats->cats_idxs[cat_id];
++    scatt_idx = cats->cats_arr[cat_idx]->scatt_idxs[scatt_id];
++
++    I_scd_set_value(cats->cats_arr[cat_idx]->scatts_arr[scatt_idx], value_idx, value);
++
++    return 0;
++}
++
++void I_scd_init_scatt_data(struct scdScattData * scatt_data, int type, int n_vals, void * data, 
++                           struct Range band_1_range, struct Range band_2_range)
++{
++    scatt_data->n_vals = n_vals;
++
++    scatt_data->band_1_range.min = band_1_range.min;
++    scatt_data->band_1_range.max = band_1_range.max;
++    scatt_data->band_1_range.first_time = 0;
++
++    scatt_data->band_2_range.min = band_2_range.min;
++    scatt_data->band_2_range.max = band_2_range.max;
++    scatt_data->band_2_range.first_time = 0;
++
++    if(type == SC_SCATT_DATA)
++    {   
++        if(data)
++            scatt_data->scatt_vals_arr = (unsigned int *) data;
++        else {
++            scatt_data->scatt_vals_arr = (unsigned int *) malloc(n_vals * sizeof(unsigned int));
++            memset(scatt_data->scatt_vals_arr, 0, n_vals * sizeof(unsigned int)); 
++        }
++        scatt_data->b_conds_arr = NULL;
++    }
++    else if(type == SC_SCATT_CONDITIONS)
++    {
++        if(data)
++            scatt_data->b_conds_arr = (unsigned char *) data;
++        else {
++            scatt_data->b_conds_arr = (unsigned char *) malloc(n_vals * sizeof(unsigned char));
++            memset(scatt_data->b_conds_arr, 0, n_vals * sizeof(unsigned char));
++        }
++        scatt_data->scatt_vals_arr = NULL;
++    }
++
++    return;
++}
++
++void I_scd_free_scatt_data(struct scdScattData * scatt_data)
++{
++
++    free(scatt_data->b_conds_arr);
++    free(scatt_data->scatt_vals_arr);
++
++    scatt_data = NULL;
++
++    return;
++}
++
++void I_scd_get_range_min_max(struct scdScattData * scatt_data, CELL * band_1_min, CELL * band_1_max, CELL * band_2_min, CELL * band_2_max)
++{
++
++    Rast_get_range_min_max(&(scatt_data->band_1_range), band_1_min, band_2_min);
++    Rast_get_range_min_max(&(scatt_data->band_2_range), band_2_min, band_2_max);
++
++    return;
++}
++
++void * I_scd_get_data_ptr(struct scdScattData * scatt_data)
++{
++    if(!scatt_data->b_conds_arr)
++        return scatt_data->b_conds_arr;
++    else if(!scatt_data->scatt_vals_arr)
++        return scatt_data->scatt_vals_arr;
++
++    return NULL;
++}
++
++int I_scd_set_value(struct scdScattData * scatt_data, unsigned int val_idx, unsigned int val)
++{
++    if(val_idx < 0 && val_idx >  scatt_data->n_vals)
++        return -1;
++
++    if(scatt_data->b_conds_arr)
++        scatt_data->b_conds_arr[val_idx] = val;
++    else if(scatt_data->scatt_vals_arr)
++        scatt_data->scatt_vals_arr[val_idx] = val;
++    else
++        return -1;
++
++    return 0;
++}
+Index: lib/vector/vedit/move.c
+===================================================================
+--- lib/vector/vedit/move.c	(revision 57336)
++++ lib/vector/vedit/move.c	(working copy)
+@@ -22,13 +22,16 @@
+   \param List list of primitives to be moved
+   \param move_x,move_y,move_z direction (move_z used only if map is 3D)
+   \param snap enable snapping (see globals.h)
+-  
++  \param new_ids list of newly assigned ids for features, which vertexes were moved,
++  		 new_id corresponds to same position of id in List
++  		 null pointer can be passed
++
+   \return number of modified primitives
+   \return -1 on error
+ */
+ int Vedit_move_lines(struct Map_info *Map, struct Map_info **BgMap,
+ 		     int nbgmaps, struct ilist *List, double move_x,
+-		     double move_y, double move_z, int snap, double thresh)
++		     double move_y, double move_z, int snap, double thresh, struct ilist *new_ids)
+ {
+     struct line_pnts *Points;
+     struct line_cats *Cats;
+@@ -84,6 +87,8 @@
+ 	if (newline < 0) {
+ 	    return -1;
+ 	}
++	if(new_ids)
++	    Vect_list_append(new_ids, newline);
+ 
+ 	nlines_moved++;
+     }
+Index: lib/vector/vedit/vertex.c
+===================================================================
+--- lib/vector/vedit/vertex.c	(revision 57336)
++++ lib/vector/vedit/vertex.c	(working copy)
+@@ -26,7 +26,10 @@
+   \param move_x,move_y,move_z direction (move_z is used when map is 3D)
+   \param move_first move only first vertex found in the bounding box
+   \param snap snapping mode (see vedit.h)
+-  
++  \param new_ids list of newly assigned ids for features, which vertexes were moved,
++  		 new_id corresponds to same position of id in List
++  		 if feature was not rewritten new id is -1
++  		 null pointer can be passed
+   \return number of moved verteces
+   \return -1 on error
+ */
+@@ -34,11 +37,11 @@
+ 		      int nbgmaps, struct ilist *List,
+ 		      struct line_pnts *coord, double thresh_coords,
+ 		      double thresh_snap, double move_x, double move_y,
+-		      double move_z, int move_first, int snap)
++		      double move_z, int move_first, int snap, struct ilist *new_ids)
+ {
+     int nvertices_moved, nlines_modified, nvertices_snapped;
+ 
+-    int i, j, k;
++    int i, j, k, newline;
+     int line, type, rewrite;
+     int npoints;
+     double east, north, dist;
+@@ -159,12 +162,17 @@
+ 	}			/* for each coord */
+ 
+ 	if (rewrite) {
+-	    if (Vect_rewrite_line(Map, line, type, Points, Cats) < 0) {
++	    newline = Vect_rewrite_line(Map, line, type, Points, Cats);
++	    if (newline < 0) {
+ 		return -1;
+ 	    }
++	    if(new_ids)
++		Vect_list_append(new_ids, newline);
+ 
+ 	    nlines_modified++;
+ 	}
++	else if(new_ids)
++	    Vect_list_append(new_ids, -1);
+     }				/* for each selected line */
+ 
+     /* destroy structures */
+@@ -187,12 +195,15 @@
+   \param List list of lines
+   \param coord points location
+   \param thresh find line in given threshold
+-  
++  \param new_ids list of newly assigned ids for features, which vertexes were moved,
++  		 new_id corresponds to same position of id in List
++  		 if feature was not rewritten new id is -1
++  		 null pointer can be passed
+   \return number of add verteces
+   \return -1 on error
+ */
+ int Vedit_add_vertex(struct Map_info *Map, struct ilist *List,
+-		     struct line_pnts *coord, double thresh)
++		     struct line_pnts *coord, double thresh, struct ilist *new_ids)
+ {
+     int i, j;
+     int type, line, seg;
+@@ -200,6 +211,7 @@
+     double east, north, dist;
+     double *x, *y, *z;
+     double px, py;
++    int newline;
+ 
+     struct line_pnts *Points;
+     struct line_cats *Cats;
+@@ -253,12 +265,17 @@
+ 	/* rewrite the line */
+ 	if (rewrite) {
+ 	    Vect_line_prune(Points);
+-	    if (Vect_rewrite_line(Map, line, type, Points, Cats) < 0) {
++	    newline = Vect_rewrite_line(Map, line, type, Points, Cats);
++	    if (newline < 0) {
+ 		return -1;
+ 	    }
++	    if(new_ids)
++		Vect_list_append(new_ids, newline);
+ 
+ 	    nlines_modified++;
+ 	}
++	else if(new_ids)
++	    Vect_list_append(new_ids, -1);
+     }				/* for each line */
+ 
+     /* destroy structures */
+@@ -277,12 +294,15 @@
+   \param List list of selected lines
+   \param coord points location
+   \param thresh threshold value to find a line
+-  
++  \param new_ids list of newly assigned ids for features, which vertexes were moved,
++  		new_id corresponds to same position of id in List
++  		if feature was not rewritten new id is -1
++  		null pointer can be passed
+   \return number of removed vertices
+   \return -1 on error
+ */
+ int Vedit_remove_vertex(struct Map_info *Map, struct ilist *List,
+-			struct line_pnts *coord, double thresh)
++			struct line_pnts *coord, double thresh, struct ilist *new_ids)
+ {
+     int i, j, k;
+     int type, line;
+@@ -290,6 +310,7 @@
+     double east, north;
+     double dist;
+     double *x, *y, *z;
++    int newline;
+ 
+     struct line_pnts *Points;
+     struct line_cats *Cats;
+@@ -336,12 +357,18 @@
+ 
+ 	if (rewrite) {
+ 	    /* rewrite the line */
+-	    if (Vect_rewrite_line(Map, line, type, Points, Cats) < 0) {
++	    newline = Vect_rewrite_line(Map, line, type, Points, Cats); 
++	    if (newline < 0) {
+ 		return -1;
+ 	    }
++	    if(new_ids)
++		Vect_list_append(new_ids, newline);
+ 
+ 	    nlines_modified++;
+ 	}
++	else if(new_ids)
++	    Vect_list_append(new_ids, -1);
++
+     }				/* for each line */
+ 
+     /* destroy structures */



More information about the grass-commit mailing list