1""" 2@package iscatt.core_c 3 4@brief Wrappers for scatter plot C backend. 5 6(C) 2013 by the GRASS Development Team 7 8This program is free software under the GNU General Public License 9(>=v2). Read the file COPYING that comes with GRASS for details. 10 11@author Stepan Turek <stepan.turek seznam.cz> (mentor: Martin Landa) 12""" 13 14import sys 15import six 16import numpy as np 17from multiprocessing import Process, Queue 18 19from ctypes import * 20try: 21 from grass.lib.imagery import * 22 from grass.lib.gis import Cell_head, G_get_window 23except ImportError as e: 24 sys.stderr.write(_("Loading ctypes libs failed")) 25 26from core.gcmd import GException 27from grass.script import encode 28 29 30def Rasterize(polygon, rast, region, value): 31 rows, cols = rast.shape 32 33 # TODO creating of region is on many places 34 region['rows'] = rows 35 region['cols'] = cols 36 37 region['nsres'] = 1.0 38 region['ewres'] = 1.0 39 40 q = Queue() 41 p = Process(target=_rasterize, args=(polygon, rast, region, value, q)) 42 p.start() 43 rast = q.get() 44 p.join() 45 46 return rast 47 48 49def ApplyColormap(vals, vals_mask, colmap, out_vals): 50 51 c_uint8_p = POINTER(c_uint8) 52 53 vals_p = vals.ctypes.data_as(c_uint8_p) 54 55 if hasattr(vals_mask, "ctypes"): 56 vals_mask_p = vals_mask.ctypes.data_as(c_uint8_p) 57 else: # vals mask is empty (all data are selected) 58 vals_mask_p = None 59 colmap_p = colmap.ctypes.data_as(c_uint8_p) 60 out_vals_p = out_vals.ctypes.data_as(c_uint8_p) 61 62 vals_size = vals.reshape((-1)).shape[0] 63 I_apply_colormap(vals_p, vals_mask_p, vals_size, colmap_p, out_vals_p) 64 65 66def MergeArrays(merged_arr, overlay_arr, alpha): 67 if merged_arr.shape != overlay_arr.shape: 68 GException("MergeArrays: merged_arr.shape != overlay_arr.shape") 69 70 c_uint8_p = POINTER(c_uint8) 71 merged_p = merged_arr.ctypes.data_as(c_uint8_p) 72 overlay_p = overlay_arr.ctypes.data_as(c_uint8_p) 73 74 I_merge_arrays( 75 merged_p, 76 overlay_p, 77 merged_arr.shape[0], 78 merged_arr.shape[1], 79 alpha) 80 81 82def ComputeScatts(region, scatt_conds, bands, n_bands, 83 scatts, cats_rasts_conds, cats_rasts): 84 _memmapToFileNames(scatts) 85 _memmapToFileNames(scatt_conds) 86 87 q = Queue() 88 p = Process( 89 target=_computeScattsProcess, 90 args=( 91 region, 92 scatt_conds, 93 bands, 94 n_bands, 95 scatts, 96 cats_rasts_conds, 97 cats_rasts, 98 q)) 99 p.start() 100 ret = q.get() 101 p.join() 102 103 return ret[0], ret[1] 104 105#_memmapToFileNames and _fileNamesToMemmap are workaround for older numpy version, 106# where memmap objects are not pickable, 107# and therefore cannot be passed to process spawned by multiprocessing module 108 109 110def _memmapToFileNames(data): 111 112 for k, v in six.iteritems(data): 113 if 'np_vals' in v: 114 data[k]['np_vals'] = v['np_vals'].filename() 115 116 117def _fileNamesToMemmap(data): 118 for k, v in six.iteritems(data): 119 if 'np_vals' in v: 120 data[k]['np_vals'] = np.memmap(filename=v['np_vals']) 121 122 123def UpdateCatRast(patch_rast, region, cat_rast): 124 q = Queue() 125 p = Process( 126 target=_updateCatRastProcess, 127 args=( 128 patch_rast, 129 region, 130 cat_rast, 131 q)) 132 p.start() 133 ret = q.get() 134 p.join() 135 136 return ret 137 138 139def CreateCatRast(region, cat_rast): 140 cell_head = _regionToCellHead(region) 141 I_create_cat_rast(pointer(cell_head), cat_rast) 142 143 144def _computeScattsProcess(region, scatt_conds, bands, n_bands, scatts, 145 cats_rasts_conds, cats_rasts, output_queue): 146 147 _fileNamesToMemmap(scatts) 148 _fileNamesToMemmap(scatt_conds) 149 150 sccats_c, cats_rasts_c, refs = _getComputationStruct( 151 scatts, cats_rasts, SC_SCATT_DATA, n_bands) 152 scatt_conds_c, cats_rasts_conds_c, refs2 = _getComputationStruct( 153 scatt_conds, cats_rasts_conds, SC_SCATT_CONDITIONS, n_bands) 154 155 char_bands = _stringListToCharArr(bands) 156 157 cell_head = _regionToCellHead(region) 158 159 ret = I_compute_scatts(pointer(cell_head), 160 pointer(scatt_conds_c), 161 pointer(cats_rasts_conds_c), 162 pointer(char_bands), 163 n_bands, 164 pointer(sccats_c), 165 pointer(cats_rasts_c)) 166 167 I_sc_free_cats(pointer(sccats_c)) 168 I_sc_free_cats(pointer(scatt_conds_c)) 169 170 output_queue.put((ret, scatts)) 171 172 173def _getBandcRange(band_info): 174 band_c_range = struct_Range() 175 176 band_c_range.max = band_info['max'] 177 band_c_range.min = band_info['min'] 178 179 return band_c_range 180 181 182def _regionToCellHead(region): 183 cell_head = struct_Cell_head() 184 G_get_window(pointer(cell_head)) 185 186 convert_dict = {'n': 'north', 'e': 'east', 187 'w': 'west', 's': 'south', 188 'nsres': 'ns_res', 189 'ewres': 'ew_res'} 190 191 for k, v in six.iteritems(region): 192 if k in ["rows", "cols", "cells", "zone"]: # zone added in r65224 193 v = int(v) 194 else: 195 v = float(v) 196 197 if k in convert_dict: 198 k = convert_dict[k] 199 200 setattr(cell_head, k, v) 201 202 return cell_head 203 204 205def _stringListToCharArr(str_list): 206 207 arr = c_char_p * len(str_list) 208 char_arr = arr() 209 for i, st in enumerate(str_list): 210 if st: 211 char_arr[i] = encode(st) 212 else: 213 char_arr[i] = None 214 215 return char_arr 216 217 218def _getComputationStruct(cats, cats_rasts, cats_type, n_bands): 219 220 sccats = struct_scCats() 221 I_sc_init_cats(pointer(sccats), c_int(n_bands), c_int(cats_type)) 222 223 refs = [] 224 cats_rasts_core = [] 225 226 for cat_id, scatt_ids in six.iteritems(cats): 227 cat_c_id = I_sc_add_cat(pointer(sccats)) 228 cats_rasts_core.append(cats_rasts[cat_id]) 229 230 for scatt_id, dt in six.iteritems(scatt_ids): 231 # if key is missing condition is always True (full scatter plor is 232 # computed) 233 vals = dt['np_vals'] 234 235 scatt_vals = scdScattData() 236 237 c_void_p = ctypes.POINTER(ctypes.c_void_p) 238 239 if cats_type == SC_SCATT_DATA: 240 vals[:] = 0 241 elif cats_type == SC_SCATT_CONDITIONS: 242 pass 243 else: 244 return None 245 data_p = vals.ctypes.data_as(c_void_p) 246 I_scd_init_scatt_data( 247 pointer(scatt_vals), 248 cats_type, len(vals), 249 data_p) 250 251 refs.append(scatt_vals) 252 253 I_sc_insert_scatt_data(pointer(sccats), 254 pointer(scatt_vals), 255 cat_c_id, scatt_id) 256 257 cats_rasts_c = _stringListToCharArr(cats_rasts_core) 258 259 return sccats, cats_rasts_c, refs 260 261 262def _updateCatRastProcess(patch_rast, region, cat_rast, output_queue): 263 cell_head = _regionToCellHead(region) 264 265 ret = I_insert_patch_to_cat_rast(patch_rast, 266 pointer(cell_head), 267 cat_rast) 268 269 output_queue.put(ret) 270 271 272def _rasterize(polygon, rast, region, value, output_queue): 273 pol_size = len(polygon) * 2 274 pol = np.array(polygon, dtype=float) 275 276 c_uint8_p = POINTER(c_uint8) 277 c_double_p = POINTER(c_double) 278 279 pol_p = pol.ctypes.data_as(c_double_p) 280 rast_p = rast.ctypes.data_as(c_uint8_p) 281 282 cell_h = _regionToCellHead(region) 283 I_rasterize(pol_p, 284 len(polygon), 285 value, 286 pointer(cell_h), rast_p) 287 288 output_queue.put(rast) 289