def multiple_solver(self, G, sources, grounds, finitegrounds): """Solver used for advanced mode.""" Gsolve = G if finitegrounds[0] != -9999: Gsolve = G + sparse.spdiags(finitegrounds.T, 0, G.shape[0], G.shape[0]) ##remove infinite grounds from graph infgroundlist = np.where(grounds==np.Inf) infgroundlist = infgroundlist[0] numinfgrounds = infgroundlist.shape[0] dst_to_delete = [] for ground in range(1, numinfgrounds+1): dst = infgroundlist[numinfgrounds-ground] dst_to_delete.append(dst) #Gsolve = deleterowcol(Gsolve, delrow = dst, delcol = dst) keep = np.delete(np.arange(0, sources.shape[0]), dst) sources = sources[keep] Gsolve = ComputeBase.deleterowcol(Gsolve, delrow = dst_to_delete, delcol = dst_to_delete) self.state.create_amg_hierarchy(Gsolve, self.options.solver) voltages = ComputeBase.solve_linear_system(Gsolve, sources, self.options.solver, self.state.amg_hierarchy) del Gsolve self.state.del_amg_hierarchy() numinfgrounds = infgroundlist.shape[0] if numinfgrounds>0: #replace infinite grounds in voltage vector for ground in range(numinfgrounds,0, -1): node = infgroundlist[numinfgrounds - ground] voltages = np.asmatrix(np.insert(voltages,node,0)).T return np.asarray(voltages).reshape(voltages.size)
def emit(self, record): try: msg = self.format(record) msg = msg.strip('\r') status_msg = None if ('\n' not in msg and 'elapsed' not in msg): # dispay simple info messages in the status bar plain_msg = logging._defaultFormatter.format(record) if (record.levelname == 'INFO'): status_msg = (plain_msg, 1) elif (record.levelname == 'DEBUG'): status_msg = (plain_msg, 2) evt = wxLogEvent(message=msg, levelname=record.levelname, status_msg=status_msg) wx.PostEvent(self.dest, evt) # @UndefinedVariable (hours,mins,secs) = ComputeBase.elapsed_time(self.last_gui_yield_time) if (secs > 0) or (mins > 0) or (hours > 0): self.last_gui_yield_time = time.time() wx.SafeYield(None, True) # @UndefinedVariable wx.GetApp().Yield(True) # @UndefinedVariable except (KeyboardInterrupt, SystemExit): raise except: self.handleError(record)
def on_menuFileRunBatch_select(self, event): wildcard = "Options Files (*.ini)|*.ini" result = dialog.fileDialog(self, 'Select any number of Circuitscape Options Files within one directory', '', '', wildcard ) if result.accepted==True: wx.BeginBusyCursor() # @UndefinedVariable GUI.logger.debug('Running Circuitscape in batch mode') startTime = time.time() startTimeHMS = time.strftime('%H:%M:%S') self.statusBar.SetStatusText('Batch start ' + str(startTimeHMS), 0) job = 0 numjobs = len(result.paths) for selection in result.paths: job += 1 _configDir, configFile = os.path.split(selection) GUI.logger.debug('Processing ' + configFile) self.statusBar.SetStatusText('Batch start ' + str(startTimeHMS) + '. Running job ' + str(job) +'/' + str(numjobs), 0) try: cs = Compute(selection, GUI.log_handler) except RuntimeError as error: wx.EndBusyCursor() # @UndefinedVariable message = str(error) dial = wx.MessageDialog(None, message, 'Error', wx.OK | wx.ICON_ERROR) # @UndefinedVariable dial.ShowModal() return except MemoryError: wx.EndBusyCursor() # @UndefinedVariable self.memory_error_feedback() return except: wx.EndBusyCursor() # @UndefinedVariable self.unknown_exception() return try: self.statusBar.SetStatusText('',1) self.statusBar.SetStatusText('',2) result, _solver_failed = cs.compute() GUI.logger.debug('Finished processing ' + configFile) except RuntimeError as error: message = str(error) dial = wx.MessageDialog(None, message, 'Error', wx.OK | wx.ICON_ERROR) # @UndefinedVariable dial.ShowModal() except MemoryError: self.memory_error_feedback() return except: self.unknown_exception() GUI.logger.debug('Done with batch operations.') wx.EndBusyCursor() # @UndefinedVariable self.components.calcButton.SetFocus() self.reset_status_bar() (hours,mins,secs) = ComputeBase.elapsed_time(startTime) if hours > 0: self.statusBar.SetStatusText('Batch job took ' + str(hours) +' hours ' + str(mins) + ' minutes to complete.',2) else: self.statusBar.SetStatusText('Batch job took ' + str(mins) +' minutes ' + str(secs) + ' seconds to complete.',2)
def read_graph(self, filename): """Reads arbitrary graph from disk. Returns sparse adjacency matrix and node names .""" graph_list = CSIO.load_graph(filename) try: zeros_in_resistance_graph = False nodes = ComputeBase.deletecol(graph_list,2) node_names = np.unique(np.asarray(nodes, dtype='int32')) nodes[np.where(nodes>= 0)] = ComputeBase.relabel(nodes[np.where(nodes>= 0)], 0) node1 = nodes[:,0] node2 = nodes[:,1] data = graph_list[:,2] ######################## Reclassification code if self.options.use_reclass_table == True: try: reclass_table = CSIO.read_point_strengths(self.options.reclass_file) except: raise RuntimeError('Error reading reclass table. Please check file format.') for i in range (0,reclass_table.shape[0]): data = np.where(data==reclass_table[i,0], reclass_table[i,1],data) Compute.logger.info('Reclassified landscape graph using %s'%(self.options.reclass_file,)) ######################## if self.options.habitat_map_is_resistances == True: zeros_in_resistance_graph = (np.where(data==0, 1, 0)).sum() > 0 conductances = 1/data else: conductances = data numnodes = node_names.shape[0] G = sparse.csr_matrix((conductances, (node1, node2)), shape = (numnodes, numnodes)) Gdense=G.todense() g_graph = np.maximum(Gdense, Gdense.T) # To handle single or double entries for elements BHM 06/28/11 g_graph = sparse.csr_matrix(g_graph) except: raise RuntimeError('Error processing graph/network file. Please check file format') if zeros_in_resistance_graph == True: raise RuntimeError('Error: zero resistance values are not currently allowed in network/graph input file.') return g_graph, node_names
def read_focal_nodes(self, filename): """Loads list of focal nodes for arbitrary graph.""" focal_nodes = CSIO.load_graph(filename) try: if filename == self.options.habitat_file:#If graph was used as focal node file, then just want first two columns for focal_nodes. focal_nodes = ComputeBase.deletecol(focal_nodes, 2) focal_nodes = np.unique(np.asarray(focal_nodes)) except: raise RuntimeError('Error processing focal node file. Please check file format') return focal_nodes
def single_ground_solver(G, src, dst, solver_type, ml): """Solver used for pairwise mode.""" n = G.shape[0] rhs = np.zeros(n, dtype = 'float64') if src==dst: voltages = np.zeros(n, dtype = 'float64') else: rhs[dst] = -1 rhs[src] = 1 voltages = ComputeBase.solve_linear_system (G, rhs, solver_type, ml) return voltages
def on_initialize(self, event): self.state = {} self.state['version'] = __version__ #LOAD LAST self.options configFile = 'circuitscape.ini' self.options = self.LoadOptions(configFile) self.options.version = self.state['version'] self.options.log_level = 'INFO' ##Set all objects to reflect options if sys.platform.startswith('win'): _icon = wx.Icon('cs_logo.ico', wx.BITMAP_TYPE_ICO) # @UndefinedVariable self.SetIcon(_icon) self.components.Image1.file = get_packaged_resource('cs_logo.jpg') self.setWidgets() self.components.calcButton.SetFocus() self.statusBar = self.CreateStatusBar() self.statusBar.SetFieldsCount(3) self.reset_status_bar() GUI.log_handler = GUILogger(self) GUI.logger = ComputeBase._create_logger("circuitscape_gui", getattr(logging, self.options.log_level.upper()), None, False, GUI.log_handler) self.Bind(EVT_WX_LOG_EVENT, self.onLogEvent)
def advanced_module(self, g_habitat, out, source_map, ground_map, source_id=None, component_with_points=None): solver_called = False solver_failed = False node_map = None if component_with_points != None: G = g_habitat.get_graph() G = ComputeBase.laplacian(G) node_map = g_habitat.node_map vc_map_id = '' if source_id==None else str(source_id) out.alloc_v_map(vc_map_id) if self.options.write_cur_maps: out.alloc_c_map(vc_map_id) for comp in range(1, g_habitat.num_components+1): if (component_with_points != None) and (comp != component_with_points): continue if self.options.data_type == 'raster': c_map = np.where(g_habitat.component_map == comp, 1, 0) local_source_map = np.multiply(c_map, source_map) local_ground_map = np.where(c_map, ground_map, 0) del c_map have_sources = (np.where(local_source_map, 1, 0)).sum() > 0 have_grounds = (np.where(local_ground_map, 1, 0)).sum() > 0 else: c_map = np.where(g_habitat.components == comp, 1, 0) sources = np.zeros(g_habitat.num_nodes) for idx in range(0, source_map.shape[0]): sources = np.where(g_habitat.node_map == source_map[idx,0], source_map[idx,1], sources) grounds = -9999 * np.ones(g_habitat.num_nodes) for idx in range(0, ground_map.shape[0]): grounds = np.where(g_habitat.node_map == ground_map[idx,0], ground_map[idx,1], grounds) if self.options.ground_file_is_resistances: _grounds = 1 / grounds grounds = np.where(grounds == -9999, 0, _grounds) else: grounds = np.where(grounds == -9999, 0, grounds) have_sources = (np.where(sources, 1, 0)).sum() > 0 have_grounds = (np.where(grounds, 1, 0)).sum() > 0 if not (have_sources and have_grounds): continue if component_with_points == None: (G, node_map) = g_habitat.prune_nodes_for_component(comp) G = ComputeBase.laplacian(G) if self.options.data_type == 'raster': (rows, cols) = np.where(local_source_map) values = local_source_map[rows,cols] local_sources_rc = np.c_[values,rows,cols] (rows, cols) = np.where(local_ground_map) values = local_ground_map[rows,cols] local_grounds_rc = np.c_[values,rows,cols] del rows, cols, values, local_source_map, local_ground_map numnodes = node_map.max() sources = np.zeros(numnodes) grounds = np.zeros(numnodes) num_local_sources = local_sources_rc.shape[0] num_local_grounds = local_grounds_rc.shape[0] for source in range(0, num_local_sources): src = self.grid_to_graph(local_sources_rc[source,1], local_sources_rc[source,2], node_map) # Possible to have more than one source at a node when there are polygons sources[src] += local_sources_rc[source,0] for ground in range(0, num_local_grounds): gnd = self.grid_to_graph (local_grounds_rc[ground,1], local_grounds_rc[ground,2], node_map) # Possible to have more than one ground at a node when there are polygons grounds[gnd] += local_grounds_rc[ground,0] (sources, grounds, finitegrounds) = self.resolve_conflicts(sources, grounds) solver_called = True try: voltages = self.multiple_solver(G, sources, grounds, finitegrounds) del sources, grounds except MemoryError: raise MemoryError except: voltages = -777 solver_failed = True if solver_failed==False: ##Voltage and current mapping are cumulative, since there may be independent components. if self.options.write_volt_maps or (self.options.scenario=='one-to-all'): out.accumulate_v_map(vc_map_id, voltages, node_map) if self.options.write_cur_maps: out.accumulate_c_map(vc_map_id, voltages, G, node_map, finitegrounds, None, None) if solver_failed==False and self.options.write_volt_maps: out.write_v_map(vc_map_id) if (self.options.write_cur_maps) and ((source_id == None) or ((source_id != None) and (self.options.write_cum_cur_map_only==False))): out.write_c_map(vc_map_id, node_map=node_map) if self.options.scenario=='one-to-all': if solver_failed==False: (row, col) = np.where(source_map>0) vmap = out.get_v_map(vc_map_id) voltages = vmap[row,col]/source_map[row,col] #allows for variable source strength elif self.options.scenario=='all-to-one': if solver_failed==False: voltages = 0 #return 0 voltage/resistance for all-to-one mode out.rm_v_map(vc_map_id) # Advanced mode will return voltages of the last component solved only for verification purposes. if solver_called==False: voltages = -1 return voltages, out.get_c_map(vc_map_id, True), solver_failed
def single_ground_all_pair_resistances(self, g_habitat, fp, cs, report_status): """Handles pairwise resistance/current/voltage calculations. Called once when focal points are used, called multiple times when focal regions are used. """ options = self.options last_write_time = time.time() numpoints = fp.num_points() parallelize = options.parallelize # TODO: revisit to see if restriction can be removed if options.low_memory_mode==True or self.state.point_file_contains_polygons==True: parallelize = False if (self.state.point_file_contains_polygons == True) or (options.write_cur_maps == True) or (options.write_volt_maps == True) or (options.use_included_pairs==True) or (options.data_type=='network'): use_resistance_calc_shortcut = False else: use_resistance_calc_shortcut = True # We use this when there are no focal regions. It saves time when we are also not creating maps shortcut_resistances = -1 * np.ones((numpoints, numpoints), dtype='float64') solver_failed_somewhere = [False] Compute.logger.info('Graph has ' + str(g_habitat.num_nodes) + ' nodes, ' + str(numpoints) + ' focal nodes and '+ str(g_habitat.num_components)+ ' components.') resistances = -1 * np.ones((numpoints, numpoints), dtype = 'float64') #Inf creates trouble in python 2.5 on Windows. Use -1 instead. # if use_resistance_calc_shortcut==True: # num_points_to_solve = numpoints # else: # num_points_to_solve = numpoints*(numpoints-1)/2 num_points_to_solve = 0 max_parallel = 0 for c in range(1, int(g_habitat.num_components+1)): if not fp.exists_points_in_component(c, g_habitat): continue num_parallel = 0 for (pt1_idx, pt2_idx) in fp.point_pair_idxs_in_component(c, g_habitat): if pt2_idx == -1: if (use_resistance_calc_shortcut==True): max_parallel = max(max_parallel, num_parallel) num_parallel = 0 break else: max_parallel = max(max_parallel, num_parallel) num_parallel = 0 continue num_parallel += 1 num_points_to_solve += 1 Compute.logger.debug('max parallel possible = ' + str(max_parallel) + ', will parallelize = ' + str(parallelize)) num_points_solved = 0 for c in range(1, int(g_habitat.num_components+1)): if not fp.exists_points_in_component(c, g_habitat): continue G_pruned, local_node_map = g_habitat.prune_nodes_for_component(c) G = ComputeBase.laplacian(G_pruned) del G_pruned if use_resistance_calc_shortcut: voltmatrix = np.zeros((numpoints,numpoints), dtype='float64') #For resistance calc shortcut G_dst_dst = local_dst = None for (pt1_idx, pt2_idx) in fp.point_pair_idxs_in_component(c, g_habitat): if pt2_idx == -1: if parallelize: self.state.worker_pool_wait() self.state.del_amg_hierarchy() if (local_dst != None) and (G_dst_dst != None): G[local_dst, local_dst] = G_dst_dst local_dst = G_dst_dst = None if (use_resistance_calc_shortcut==True): Compute.get_shortcut_resistances(pt1_idx, voltmatrix, numpoints, resistances, shortcut_resistances) break #No need to continue, we've got what we need to calculate resistances else: continue if parallelize: self.state.worker_pool_create(options.max_parallel, True) if report_status==True: num_points_solved += 1 if use_resistance_calc_shortcut==True: Compute.logger.info('solving focal node ' + str(num_points_solved) + ' of '+ str(num_points_to_solve)) else: Compute.logger.info('solving focal pair ' + str(num_points_solved) + ' of '+ str(num_points_to_solve)) local_src = fp.get_graph_node_idx(pt2_idx, local_node_map) if None == local_dst: local_dst = fp.get_graph_node_idx(pt1_idx, local_node_map) G_dst_dst = G[local_dst, local_dst] G[local_dst, local_dst] = 0 if self.state.amg_hierarchy == None: self.state.create_amg_hierarchy(G, self.options.solver) if use_resistance_calc_shortcut: post_solve = self._post_single_ground_solve(G, fp, cs, resistances, numpoints, pt1_idx, pt2_idx, local_src, local_dst, local_node_map, solver_failed_somewhere, use_resistance_calc_shortcut, voltmatrix) else: post_solve = self._post_single_ground_solve(G, fp, cs, resistances, numpoints, pt1_idx, pt2_idx, local_src, local_dst, local_node_map, solver_failed_somewhere) if parallelize: self.state.worker_pool.apply_async(Compute.parallel_single_ground_solver, args=(G, local_src, local_dst, options.solver, self.state.amg_hierarchy), callback=post_solve) #post_solve(self.state.worker_pool.apply(Compute.parallel_single_ground_solver, args=(G, local_src, local_dst, options.solver, self.state.amg_hierarchy))) else: try: voltages = Compute.single_ground_solver(G, local_src, local_dst, options.solver, self.state.amg_hierarchy) except: voltages = None post_solve(voltages) if options.low_memory_mode==True or self.state.point_file_contains_polygons==True: self.state.del_amg_hierarchy() (hours,mins,_secs) = ComputeBase.elapsed_time(last_write_time) if mins > 2 or hours > 0: last_write_time = time.time() CSIO.write_resistances(options.output_file, resistances, incomplete=True)# Save incomplete resistances self.state.del_amg_hierarchy() # Finally, resistance to self is 0. if use_resistance_calc_shortcut==True: resistances = shortcut_resistances for i in range(0, numpoints): resistances[i, i] = 0 return resistances, solver_failed_somewhere[0]
def one_to_all_module(self, g_map, poly_map, points_rc): """Overhead module for one-to-all AND all-to-one modes with raster data.""" last_write_time = time.time() out = Output(self.options, self.state, False) if self.options.write_cur_maps: out.alloc_c_map('') if self.options.write_max_cur_maps: out.alloc_c_map('max') fp = FocalPoints(points_rc, self.state.included_pairs, False) fp = FocalPoints(fp.get_unique_coordinates(), self.state.included_pairs, False) point_ids = fp.point_ids points_rc_unique = fp.points_rc included_pairs = self.state.included_pairs resistance_vector = np.zeros((point_ids.size,2), float) solver_failed_somewhere = False if self.options.use_included_pairs==False: #Will do this each time later if using included pairs point_map = np.zeros((self.state.nrows, self.state.ncols), int) point_map[points_rc[:,1], points_rc[:,2]] = points_rc[:,0] #combine point map and poly map poly_map_temp = self.get_poly_map_temp(poly_map, point_map, point_ids) unique_point_map = np.zeros((self.state.nrows, self.state.ncols), int) unique_point_map[points_rc_unique[:,1], points_rc_unique[:,2]] = points_rc_unique[:,0] (strength_map, strengths_rc) = self.get_strength_map(points_rc_unique, self.state.point_strengths) g_habitat = HabitatGraph(g_map=g_map, poly_map=poly_map_temp, connect_using_avg_resistances=self.options.connect_using_avg_resistances, connect_four_neighbors_only=self.options.connect_four_neighbors_only) Compute.logger.info('Graph has ' + str(g_habitat.num_nodes) + ' nodes and '+ str(g_habitat.num_components) + ' components.') component_with_points = g_habitat.unique_component_with_points(unique_point_map) else: if Compute.logger.isEnabledFor(logging.DEBUG): g_habitat = HabitatGraph(g_map=g_map, poly_map=poly_map, connect_using_avg_resistances=self.options.connect_using_avg_resistances, connect_four_neighbors_only=self.options.connect_four_neighbors_only) Compute.logger.info('Graph has ' + str(g_habitat.num_nodes) + ' nodes and '+ str(g_habitat.num_components) + ' components.') component_with_points = None for pt_idx in range(0, point_ids.size): # These are the 'src' nodes, pt_idx.e. the 'one' in all-to-one and one-to-all Compute.logger.info('solving focal node ' + str(pt_idx+1) + ' of ' + str(point_ids.size)) if self.options.use_included_pairs==True: # Done above otherwise ####################### points_rc_unique_temp = np.copy(points_rc_unique) point_map = np.zeros((self.state.nrows, self.state.ncols), int) point_map[points_rc[:,1], points_rc[:,2]] = points_rc[:,0] #loop thru exclude[point,:], delete included pairs of focal point from point_map and points_rc_unique_temp for pair in range(0, point_ids.size): if (pt_idx != pair) and not self.state.included_pairs.is_included_pair(point_ids[pt_idx], point_ids[pair]): pt_id = point_ids[pair] point_map = np.where(point_map==pt_id, 0, point_map) points_rc_unique_temp[pair, 0] = 0 #point will not be burned in to unique_point_map poly_map_temp = self.get_poly_map_temp2(poly_map, point_map, points_rc_unique_temp, included_pairs, pt_idx) g_habitat = HabitatGraph(g_map=g_map, poly_map=poly_map_temp, connect_using_avg_resistances=self.options.connect_using_avg_resistances, connect_four_neighbors_only=self.options.connect_four_neighbors_only) unique_point_map = np.zeros((self.state.nrows, self.state.ncols),int) unique_point_map[points_rc_unique_temp[:,1], points_rc_unique_temp[:,2]] = points_rc_unique_temp[:,0] (strength_map, strengths_rc) = self.get_strength_map(points_rc_unique_temp, self.state.point_strengths) ########################################### src = point_ids[pt_idx] if unique_point_map.sum() == src: # src is the only point resistance_vector[pt_idx,0] = src resistance_vector[pt_idx,1] = -1 else: # there are points to connect with src point if self.options.scenario == 'one-to-all': strength = strengths_rc[pt_idx,0] if self.options.use_variable_source_strengths else 1 source_map = np.where(unique_point_map == src, strength, 0) ground_map = np.where(unique_point_map == src, 0, unique_point_map) ground_map = np.where(ground_map, np.Inf, 0) self.options.remove_src_or_gnd = 'rmvgnd' else: # all-to-one if self.options.use_variable_source_strengths==True: source_map = np.where(unique_point_map == src, 0, strength_map) else: source_map = np.where(unique_point_map, 1, 0) source_map = np.where(unique_point_map == src, 0, source_map) ground_map = np.where(unique_point_map == src, np.Inf, 0) self.options.remove_src_or_gnd = 'rmvsrc' #FIXME: right now one-to-all *might* fail if there is just one node that is not grounded (I haven't encountered this problem lately BHM Nov 2009). resistance, current_map, solver_failed = self.advanced_module(g_habitat, out, source_map, ground_map, src, component_with_points) if not solver_failed: if self.options.write_cur_maps: out.accumulate_c_map_with_values('', current_map) if self.options.write_max_cur_maps: out.store_max_c_map_values('max', current_map) else: Compute.logger.warning('Solver failed for at least one focal node. Focal nodes with failed solves will be marked with value of -777 in output resistance list.') resistance_vector[pt_idx,0] = src resistance_vector[pt_idx,1] = resistance if solver_failed==True: solver_failed_somewhere = True (hours,mins,_secs) = ComputeBase.elapsed_time(last_write_time) if mins > 2 or hours > 0: last_write_time = time.time() CSIO.write_resistances(self.options.output_file, resistance_vector, incomplete=True) if not solver_failed_somewhere: if self.options.write_cur_maps: out.write_c_map('', True) if self.options.write_max_cur_maps: out.write_c_map('max', True) CSIO.write_resistances(self.options.output_file, resistance_vector) return resistance_vector, solver_failed_somewhere
def on_logLevelChoice_select(self, event): log_lvl = event.GetSelection() self.options.log_level = GUI.OPTIONS_LOG_LEVEL[log_lvl] GUI.logger = ComputeBase._create_logger("circuitscape_gui", getattr(logging, self.options.log_level), None, False, GUI.log_handler) GUI.logger.setLevel(getattr(logging, self.options.log_level.upper())) GUI.log_handler.setLevel(getattr(logging, self.options.log_level.upper()))