def _run_finished(self, success): key = self.running_key self.running_key = None size = QSizePolicy(QSizePolicy.Expanding,QSizePolicy.Expanding) self.tabwidget_visualizations.setSizePolicy(size) name = '%s/%s/%s'%key new_tab = QTabWidget(self.tabwidget_visualizations) self.tabwidget_visualizations.addTab(new_tab, name) map_widget = None tab_widget = None for (visualization_type, visualizations) in self.batch_processor.get_visualizations(): if len(visualizations) > 0: if visualization_type == 'mapnik_map': viz = visualizations[0] map_widget = ViewImageForm(viz, new_tab) map_widget.setSizePolicy(size) elif visualization_type == 'mapnik_animated_map': viz = visualizations[0] map_widget = ViewAnimationForm(viz, new_tab) map_widget.setSizePolicy(size) elif visualization_type == 'table_per_year': viz = visualizations[0] tab_widget = ViewTableForm(viz, new_tab) tab_widget.setSizePolicy(size) # else: # map_widget = self.tabMap # tab_widget = self.tabTable # if not map_widget or not tab_widget: return # self.tabMap = map_widget # self.tabTable = tab_widget if tab_widget: new_tab.addTab(tab_widget, "Table") if map_widget: new_tab.addTab(map_widget, "Map") self.already_browsed[key] = (tab_widget, map_widget) # self.lblViewIndicator.setText(QString(key[1])) # self.lblViewRun.setText(QString(key[0])) # self.lblViewYear.setText(QString(repr(key[2]))) swap = self.queued_results is not None and self.queued_results[0] == 'swap' if self.queued_results is not None and not swap: self.running_key = self.queued_results[0] logger.log_note('Generating queued results for %s on run %s for year %i'%self.running_key) self.batch_processor = self.queued_results[1] self.queued_results = None runThread = OpusGuiThread( parentThread = get_mainwindow_instance(), parentGuiElement = self, thread_object = self.batch_processor) # Use this signal from the thread if it is capable of producing its own status signal QObject.connect(runThread, SIGNAL("runFinished(PyQt_PyObject)"), self._run_finished) QObject.connect(runThread, SIGNAL("runError(PyQt_PyObject)"), self._run_error) runThread.start() else: # if swap: # (map_widget, tab_widget) = self.queued_results[1] # ## self.swap_visualizations(map_widget, tab_widget) # name = '%s/%s/%s'%key # # self.swap_visualizations(map_widget, tab_widget) # self.add_visualization(map_widget = map_widget, tab_widget = tab_widget, name = name) self.queued_results = None self.generating_results = False self.pb_generate_results.setText('Results Generated')
class SimulationGuiElement(QWidget, Ui_SimulationGuiElement): def __init__(self, mainwindow, runManager, model, xml_config): QWidget.__init__(self, mainwindow) self.mainwindow = mainwindow self.setupUi(self) self.runManager = runManager self.project = runManager.project self.model = model self.model.guiElement = self self.inGui = False self.logFileKey = 0 self.running = False self.paused = False self.timer = None self.runThread = None self.config = None self.xml_config = xml_config self.config = xml_config.get_run_configuration( str(self.model.modeltorun)) insert_auto_generated_cache_directory_if_needed(self.config) (self.start_year, self.end_year) = self.config['years'] self.tabIcon = QIcon(":/Images/Images/cog.png") self.tabLabel = model.modeltorun self.setup_run_name_line_edit() self.setup_indicator_batch_combobox() # Simulation Progress Tab self.runProgressBarTotal.setProperty("value", QVariant(0)) self.runProgressBarTotal.reset() ### Year Progress Bar self.runProgressBarYear.setProperty("value", QVariant(0)) self.runProgressBarYear.reset() ### Model Progress Bar self.runProgressBarModel.setProperty("value", QVariant(0)) self.runProgressBarModel.reset() self.setupDiagnosticIndicatorTab() self.gb_model_progress.hide() self.spatial_datasets = get_available_spatial_dataset_names( project=self.project) self.diagnostic_go_button.setEnabled(False) def updateConfigAndGuiForRun(self): config = self.xml_config.get_run_configuration( str(self.model.modeltorun)) self.config = config insert_auto_generated_cache_directory_if_needed(config) (self.start_year, self.end_year) = config['years'] #self.summaryYearRangeLabel.setText(QString("Running model from "+str(self.start_year)+" to "+str(self.end_year))) def on_cbYear_stateChanged(self, state): if self.cbYear.isChecked(): self.gb_year_progress.show() self.cbModel.setChecked(False) else: self.gb_year_progress.hide() self.gb_model_progress.hide() def on_cbModel_stateChanged(self, state): if self.cbModel.isChecked(): self.gb_model_progress.show() else: self.setUpdatesEnabled(False) self.gb_model_progress.hide() self.adjustSize() self.setUpdatesEnabled(True) def setupDiagnosticIndicatorTab(self): years = range(self.config["years"][0], self.config["years"][1] + 1) # yearItems is a list of [int, boolean] pairs, where the integer is a year # and the boolean is true if the year has already been added to the drop self.yearItems = [] for year in years: #the second value in the list determines if it is already added to the drop down self.yearItems.append([year, False]) datasets = get_available_dataset_names(self.project) for dataset in datasets: self.diagnostic_dataset_name.addItem(QString(dataset)) self.setup_diagnostic_indicators() self.indicatorResultsTab.removeTab(0) QObject.connect(self.diagnostic_go_button, SIGNAL("released()"), self.on_indicatorBox) QObject.connect(self.diagnostic_dataset_name, SIGNAL("currentIndexChanged(QString)"), self.on_diagnostic_dataset_name_currentIndexChanged) def setup_diagnostic_indicators(self): dataset = str(self.diagnostic_dataset_name.currentText()) indicator_variable_nodes = get_indicator_nodes_per_dataset( self.project) if dataset in indicator_variable_nodes: indicators = indicator_variable_nodes[dataset] else: indicators = [] # indicators = self.xml_helper.get_available_indicator_names(attributes = ['dataset']) self.diagnostic_indicator_name.clear() for indicator in indicators: self.diagnostic_indicator_name.addItem(indicator.tag) # if add_baseyear: # self.diagnostic_year.addItem(str(self.config['base_year'])) def on_diagnostic_dataset_name_currentIndexChanged(self, param): if isinstance(param, int): return #qt sends two signals for the same event; only process one self.setup_diagnostic_indicators() def setup_indicator_batch_combobox(self): self.cboOptionalIndicatorBatch.addItem(QString('(None)')) # Get available batches batch_nodes = get_available_batch_nodes(self.project) for batch_node in batch_nodes: self.cboOptionalIndicatorBatch.addItem(batch_node.get('name')) def setup_run_name_line_edit(self): run_name = 'run_%s' % strftime('%Y_%m_%d_%H_%M', localtime()) self.leRunName.setText(QString(run_name)) def on_indicatorBox(self): indicator_name = str(self.diagnostic_indicator_name.currentText()) dataset_name = self.diagnostic_dataset_name.currentText() indicator_type = str(self.diagnostic_indicator_type.currentText()) year = str(self.diagnostic_year.currentText()) if year == '': return year = int(year) if dataset_name not in self.spatial_datasets and indicator_type == 'map': MessageBox.warning( mainwindow=self.mainwindow, text="That indicator cannot be visualized as a map.", detailed_text=( 'The dataset %s is either not spatial or cannot be ' 'rendered as a grid. If the latter, please try ' 'exporting to an external GIS tool.' % dataset_name)) return cache_directory = self.model.config['cache_directory'] params = {'indicators': [indicator_name]} if indicator_type == 'table': indicator_type = 'tab' params['output_type'] = 'tab' # JLM > commented this out for when implemented animations # else: # indicator_type = 'mapnik_map' visualizations = [(indicator_type, str(dataset_name), params)] self.batch_processor = BatchProcessor(self.project) self.batch_processor.guiElement = self self.batch_processor.set_data(visualizations=visualizations, source_data_name=self.model.run_name, years=[year, year], cache_directory=cache_directory) self.diagnosticThread = OpusGuiThread( parentThread=self.mainwindow, parentGuiElement=self, thread_object=self.batch_processor) # Use this signal from the thread if it is capable of producing its own status signal QObject.connect(self.diagnosticThread, SIGNAL("runFinished(PyQt_PyObject)"), self.visualizationsCreated) QObject.connect(self.diagnosticThread, SIGNAL("runError(PyQt_PyObject)"), self.runErrorFromThread) self.diagnosticThread.start() def visualizationsCreated(self): all_visualizations = self.batch_processor.get_visualizations() for indicator_type, visualizations in all_visualizations: for visualization in visualizations: if indicator_type == 'mapnik_map': form = ViewImageForm(visualization=visualization) elif indicator_type == 'animated_map': form = ViewAnimationForm(visualization=visualization) else: form = ViewTableForm(visualization=visualization) self.indicatorResultsTab.insertTab(0, form, form.tabIcon, form.tabLabel) def removeElement(self): return self.on_pbnRemoveModel_released() def on_pbnRemoveModel_released(self): # if(self.running == True): success = True if self.runThread: success = self.runThread.cancel() if success: if self.timer: self.timer.stop() self.running = False self.paused = False return success def on_pbnStartModel_released(self): duplicate = False self.diagnostic_go_button.setEnabled(True) if self.running and not self.paused: # Take care of pausing a run success = self.runThread.pause() if success: self.paused = True self.timer.stop() self.pbnStartModel.setText(QString("Resume simulation run...")) elif self.running and self.paused: # Need to resume a paused run success = self.runThread.resume() if success: self.paused = False self.timer.start(1000) self.pbnStartModel.setText(QString("Pause simulation run...")) elif not self.running: run_name = str(self.leRunName.text()) if run_name == '': run_name = None else: run_id = None run_nodes = get_available_run_nodes(self.project) for run_node in run_nodes: existing_run_name = run_node.tag if run_name == existing_run_name: duplicate = True r = run_node.get('run_id') if r is not None: run_id = int(r) break if duplicate: dlg_dup = OverwriteRunDialog(self) if dlg_dup.exec_() == QDialog.Rejected: return delete_simulation_run( self.project, run_node.tag) # todo change to run_node.get('name') # Update the XML self.project.update_xml_config() self.updateConfigAndGuiForRun() # Fire up a new thread and run the model self.pbnStartModel.setText(QString("Pause simulation run...")) # References to the GUI elements for status for this run... self.progressBarTotal = self.runProgressBarTotal self.progressBarYear = self.runProgressBarYear self.progressBarModel = self.runProgressBarModel #self.pbnRemoveModel.setEnabled(False) #self.pbnStartModel.setEnabled(False) # Initializing values self.progressBarTotal.setValue(0) self.progressBarYear.setValue(0) self.progressBarModel.setValue(0) self.progressBarTotal.setRange(0, 0) self.progressBarYear.setRange(0, 0) self.progressBarModel.setRange(0, 0) batch_name = str(self.cboOptionalIndicatorBatch.currentText()) if batch_name == '(None)': batch_name = None self.runThread = RunModelThread(get_mainwindow_instance(), self, batch_name, run_name) if duplicate and run_id is not None: from opus_core.services.run_server.run_manager import RunManager as ServicesRunManager run_manager = ServicesRunManager( ServicesDatabaseConfiguration()) run_manager.delete_everything_for_this_run(run_id=run_id) run_manager.close() # Use this signal from the thread if it is capable of producing its own status signal QObject.connect(self.runThread, SIGNAL("runFinished(PyQt_PyObject)"), self.runFinishedFromThread) QObject.connect(self.runThread, SIGNAL("runError(PyQt_PyObject)"), self.runErrorFromThread) # Use this timer to call a function in the thread to check status if the thread is unable # to produce its own signal above self.timer = QTimer() QObject.connect(self.timer, SIGNAL("timeout()"), self.runStatusFromThread) self.timer.start(1000) self.running = True self.paused = False self.runThread.start() else: print "Unexpected state in the model run..." # This is not used currently since the model can not return status... instead we use a timer to # check the status from a log file. def runPingFromThread(self, value): self.progressBar.setValue(value) #print "Ping from thread!" # Called when the model is finished... peg the percentage to 100% and stop the timer. def runFinishedFromThread(self, success): self.progressBarTotal.setValue(100) self.progressBarYear.setValue(100) self.progressBarModel.setValue(100) msg = 'Simulation ran successfully!' if success else 'Simulation failed.' self.summaryCurrentYearValue.setText(QString(msg)) self.summaryCurrentModelValue.setText(QString("Finished")) self.summaryCurrentPieceValue.setText(QString("Finished")) self.timer.stop() # Get the final logfile update after model finishes... self.logFileKey = self.runThread.modelguielement.model._get_current_log( self.logFileKey) self.running = False self.paused = False self.pbnStartModel.setText(QString("Start Simulation Run...")) #get the last year to show up in the diagnostics tab. self.yearItems[-1][1] = True self.diagnostic_year.addItem(QString(str(self.yearItems[-1][0]))) if self.runThread.batch_name is not None: all_visualizations = self.runThread.batch_processor.get_visualizations( ) for indicator_type, visualizations in all_visualizations: form_generator = None print indicator_type if indicator_type == 'mapnik_map' or \ indicator_type == 'matplotlib_chart': form_generator = self.mainwindow.managers[ 'results_manager'].addViewImageIndicator elif indicator_type == 'mapnik_animated_map': form_generator = self.mainwindow.managers[ 'results_manager'].addViewAnimationIndicator elif indicator_type == 'tab': form_generator = self.mainwindow.managers[ 'results_manager'].addViewTableIndicator if form_generator is not None: for visualization in visualizations: form_generator(visualization=visualization, indicator_type=indicator_type) # GUI elements that show progress go here. Note that they have to be set # up first in the constructor of this class, then optionally initialized in # on_pbnStartModel_released(), then calculated and updated here, and finally # when the simulation is done running, finalized values are optionally # defined in runFinishedFromThread (because status.txt doesn't refresh at # end of the simulation. def runStatusFromThread(self): totalProgress = 0 yearProgress = 0 modelProgress = 0 boxTitle = "Simulation run initializing..." # TODO: this is for the old prog bar if self.runThread.modelguielement.model.statusfile is None: boxTitle = "Simulation run initializing..." else: # Compute percent progress for the progress bar. # The statusfile is written by the _write_status_for_gui method # in class ModelSystem in urbansim.model_coordinators.model_system # The file is ascii, with the following format (1 item per line): # current year # total number of models # number of current model that is about to run (starting with 0) # name of current model # total number of pieces of current model (could be 1) # number of current piece # description of current piece (empty string if no description) statusfile = self.runThread.modelguielement.model.statusfile try: f = open(statusfile) lines = f.readlines() f.close() # use float for all numbers to help with percent computation if len(lines) > 0: current_year = float(lines[0]) total_models = float(lines[1]) current_model = float(lines[2]) current_model_names = lines[3] current_model_display_name = current_model_names #current_model_names[0] total_pieces = float(lines[4]) current_piece = float(lines[5]) current_piece_name = lines[6].strip() total_years = float(self.end_year - self.start_year + 1) # For each year, we need to run all of the models. # year_fraction_completed is the fraction completed (ignoring the currently running year) # model_fraction_completed is the additional fraction completed for the current year modelProgress = 100.0 * (current_piece / total_pieces) yearProgress = modelProgress / total_models + 100.0 * ( current_model / total_models) totalProgress = yearProgress / total_years + 100.0 * ( (current_year - self.start_year) / total_years) currentYearString = "(" + str( int((current_year - self.start_year)) + 1) + "/" + str( int(total_years)) + ") " + str(int(current_year)) self.summaryCurrentYearValue.setText( QString(currentYearString)) currentModelString = "(" + str( int(current_model) + 1) + "/" + str(int( total_models)) + ") " + current_model_display_name self.summaryCurrentModelValue.setText( QString(currentModelString)) currentPieceString = "(" + str( int(current_piece) + 1) + "/" + str( int(total_pieces)) + ") " + current_piece_name self.summaryCurrentPieceValue.setText( QString(currentPieceString)) boxTitle = current_model_display_name # detect if a year has been completed for item in self.yearItems: if item[0] < current_year and not item[1]: self.diagnostic_year.addItem(QString(str(item[0]))) item[1] = True #hook into indicator group computation here if (self.progressBarTotal.maximum() == 0): self.progressBarTotal.setRange(0, 100) self.progressBarYear.setRange(0, 100) self.progressBarModel.setRange(0, 100) except IOError: boxTitle = "Simulation run is initializing..." newString = QString(boxTitle) newString.leftJustified(60) # self.simprogressGroupBox.setTitle(newString) self.progressBarTotal.setValue(totalProgress) self.progressBarYear.setValue(yearProgress) self.progressBarModel.setValue(modelProgress) self.logFileKey = self.runThread.modelguielement.model._get_current_log( self.logFileKey) def runErrorFromThread(self, errorMessage): self.running = False self.paused = False self.pbnStartModel.setText(QString("Start Simulation Run...")) MessageBox.warning(mainwindow=self.mainwindow, text="There was a problem running the simulation.", detailed_text=errorMessage)
def on_pb_generate_results_released(self): run_name = self.current_run indicator_name = self.current_indicator indicator_dataset = self.current_indicator_dataset start_year = int(self.current_year) end_year = start_year if run_name is None or indicator_name is None or start_year is None: return key = (run_name, indicator_name, start_year) if key in self.already_browsed: if not self.generating_results: (tab_widget,map_widget) = self.already_browsed[key] # self.swap_visualizations(map_widget, tab_widget) self.pb_generate_results.setText('Results Generated') else: self.queued_results = ('swap', (map_widget, tab_widget)) return self.pb_generate_results.setEnabled(False) self.pb_generate_results.setText('Generating Results...') indicator_nodes = get_available_indicator_nodes(self.project) dataset = None for indicator_node in indicator_nodes: ind_dataset, name = get_variable_dataset_and_name(indicator_node) if name == indicator_name and ind_dataset == indicator_dataset: dataset = ind_dataset break if dataset is None: raise Exception('Could not find dataset for indicator %s' % indicator_name) table_params = { 'name': None, 'output_type' : 'tab', 'indicators' : [indicator_name], } map_params = {'name':None, 'indicators':[indicator_name]} visualizations = [ ('table_per_year', dataset, table_params), ('mapnik_map', dataset, map_params) ] batch_processor = BatchProcessor(self.project) batch_processor.guiElement = self batch_processor.set_data( visualizations = visualizations, source_data_name = run_name, years = range(start_year, end_year + 1)) if not self.generating_results: self.generating_results = True logger.log_note('Generating results for %s on run %s for year %indicator_node'%(run_name, indicator_name, start_year)) self.running_key = key self.batch_processor = batch_processor batch_processor_thread = OpusGuiThread( parentThread = get_mainwindow_instance(), parentGuiElement = self, thread_object = self.batch_processor) # Use this signal from the thread if it is capable of producing its own status signal self.connect(batch_processor_thread, SIGNAL("runFinished(PyQt_PyObject)"), self._run_finished) self.connect(batch_processor_thread, SIGNAL("runError(PyQt_PyObject)"), self._run_error) batch_processor_thread.start() else: self.queued_results = (key, batch_processor)
class SimulationGuiElement(QWidget, Ui_SimulationGuiElement): def __init__(self, mainwindow, runManager, model, xml_config): QWidget.__init__(self, mainwindow) self.mainwindow = mainwindow self.setupUi(self) self.runManager = runManager self.project = runManager.project self.model = model self.model.guiElement = self self.inGui = False self.logFileKey = 0 self.running = False self.paused = False self.timer = None self.runThread = None self.config = None self.xml_config = xml_config self.config = xml_config.get_run_configuration(str(self.model.modeltorun)) insert_auto_generated_cache_directory_if_needed(self.config) (self.start_year, self.end_year) = self.config['years'] self.tabIcon = QIcon(":/Images/Images/cog.png") self.tabLabel = model.modeltorun self.setup_run_name_line_edit() self.setup_indicator_batch_combobox() # Simulation Progress Tab self.runProgressBarTotal.setProperty("value",QVariant(0)) self.runProgressBarTotal.reset() ### Year Progress Bar self.runProgressBarYear.setProperty("value",QVariant(0)) self.runProgressBarYear.reset() ### Model Progress Bar self.runProgressBarModel.setProperty("value",QVariant(0)) self.runProgressBarModel.reset() self.setupDiagnosticIndicatorTab() self.gb_model_progress.hide() self.spatial_datasets = get_available_spatial_dataset_names(project = self.project) self.diagnostic_go_button.setEnabled(False) def updateConfigAndGuiForRun(self): config = self.xml_config.get_run_configuration(str(self.model.modeltorun)) self.config = config insert_auto_generated_cache_directory_if_needed(config) (self.start_year, self.end_year) = config['years'] #self.summaryYearRangeLabel.setText(QString("Running model from "+str(self.start_year)+" to "+str(self.end_year))) def on_cbYear_stateChanged(self, state): if self.cbYear.isChecked(): self.gb_year_progress.show() self.cbModel.setChecked(False) else: self.gb_year_progress.hide() self.gb_model_progress.hide() def on_cbModel_stateChanged(self, state): if self.cbModel.isChecked(): self.gb_model_progress.show() else: self.setUpdatesEnabled(False) self.gb_model_progress.hide() self.adjustSize() self.setUpdatesEnabled(True) def setupDiagnosticIndicatorTab(self): years = range(self.config["years"][0], self.config["years"][1]+1) # yearItems is a list of [int, boolean] pairs, where the integer is a year # and the boolean is true if the year has already been added to the drop self.yearItems = [] for year in years: #the second value in the list determines if it is already added to the drop down self.yearItems.append([year, False]); datasets = get_available_dataset_names(self.project) for dataset in datasets: self.diagnostic_dataset_name.addItem(QString(dataset)) self.setup_diagnostic_indicators() self.indicatorResultsTab.removeTab(0) QObject.connect(self.diagnostic_go_button,SIGNAL("released()"),self.on_indicatorBox) QObject.connect(self.diagnostic_dataset_name, SIGNAL("currentIndexChanged(QString)"), self.on_diagnostic_dataset_name_currentIndexChanged) def setup_diagnostic_indicators(self): dataset = str(self.diagnostic_dataset_name.currentText()) indicator_variable_nodes = get_indicator_nodes_per_dataset(self.project) if dataset in indicator_variable_nodes: indicators = indicator_variable_nodes[dataset] else: indicators = [] # indicators = self.xml_helper.get_available_indicator_names(attributes = ['dataset']) self.diagnostic_indicator_name.clear() for indicator in indicators: self.diagnostic_indicator_name.addItem(indicator.tag) # if add_baseyear: # self.diagnostic_year.addItem(str(self.config['base_year'])) def on_diagnostic_dataset_name_currentIndexChanged(self, param): if isinstance(param, int): return #qt sends two signals for the same event; only process one self.setup_diagnostic_indicators() def setup_indicator_batch_combobox(self): self.cboOptionalIndicatorBatch.addItem(QString('(None)')) # Get available batches batch_nodes = get_available_batch_nodes(self.project) for batch_node in batch_nodes: self.cboOptionalIndicatorBatch.addItem(batch_node.get('name')) def setup_run_name_line_edit(self): run_name = 'run_%s'%strftime('%Y_%m_%d_%H_%M', localtime()) self.leRunName.setText(QString(run_name)) def on_indicatorBox(self): indicator_name = str(self.diagnostic_indicator_name.currentText()) dataset_name = self.diagnostic_dataset_name.currentText() indicator_type = str(self.diagnostic_indicator_type.currentText()) year = str(self.diagnostic_year.currentText()) if year=='': return year = int(year) if dataset_name not in self.spatial_datasets and indicator_type == 'map': MessageBox.warning(mainwindow = self.mainwindow, text = "That indicator cannot be visualized as a map.", detailed_text = ('The dataset %s is either not spatial or cannot be ' 'rendered as a grid. If the latter, please try ' 'exporting to an external GIS tool.'%dataset_name)) return cache_directory = self.model.config['cache_directory'] params = {'indicators':[indicator_name]} if indicator_type == 'table': indicator_type = 'tab' params['output_type'] = 'tab' # JLM > commented this out for when implemented animations # else: # indicator_type = 'mapnik_map' visualizations = [ (indicator_type, str(dataset_name), params) ] self.batch_processor = BatchProcessor(self.project) self.batch_processor.guiElement = self self.batch_processor.set_data( visualizations = visualizations, source_data_name = self.model.run_name, years = [year, year], cache_directory = cache_directory) self.diagnosticThread = OpusGuiThread( parentThread = self.mainwindow, parentGuiElement = self, thread_object = self.batch_processor) # Use this signal from the thread if it is capable of producing its own status signal QObject.connect(self.diagnosticThread, SIGNAL("runFinished(PyQt_PyObject)"), self.visualizationsCreated) QObject.connect(self.diagnosticThread, SIGNAL("runError(PyQt_PyObject)"), self.runErrorFromThread) self.diagnosticThread.start() def visualizationsCreated(self): all_visualizations = self.batch_processor.get_visualizations() for indicator_type, visualizations in all_visualizations: for visualization in visualizations: if indicator_type == 'mapnik_map': form = ViewImageForm(visualization = visualization) elif indicator_type == 'animated_map': form = ViewAnimationForm(visualization = visualization) else: form = ViewTableForm(visualization = visualization) self.indicatorResultsTab.insertTab(0,form,form.tabIcon,form.tabLabel) def removeElement(self): return self.on_pbnRemoveModel_released() def on_pbnRemoveModel_released(self): # if(self.running == True): success = True if self.runThread: success = self.runThread.cancel() if success: if self.timer: self.timer.stop() self.running = False self.paused = False return success def on_pbnStartModel_released(self): duplicate = False self.diagnostic_go_button.setEnabled(True) if self.running and not self.paused: # Take care of pausing a run success = self.runThread.pause() if success: self.paused = True self.timer.stop() self.pbnStartModel.setText(QString("Resume simulation run...")) elif self.running and self.paused: # Need to resume a paused run success = self.runThread.resume() if success: self.paused = False self.timer.start(1000) self.pbnStartModel.setText(QString("Pause simulation run...")) elif not self.running: run_name = str(self.leRunName.text()) if run_name == '': run_name = None else: run_id = None run_nodes = get_available_run_nodes(self.project) for run_node in run_nodes: existing_run_name = run_node.tag if run_name == existing_run_name: duplicate = True r = run_node.get('run_id') if r is not None: run_id = int(r) break if duplicate: dlg_dup = OverwriteRunDialog(self) if dlg_dup.exec_() == QDialog.Rejected: return delete_simulation_run(self.project, run_node.tag) # todo change to run_node.get('name') # Update the XML self.project.update_xml_config() self.updateConfigAndGuiForRun() # Fire up a new thread and run the model self.pbnStartModel.setText(QString("Pause simulation run...")) # References to the GUI elements for status for this run... self.progressBarTotal = self.runProgressBarTotal self.progressBarYear = self.runProgressBarYear self.progressBarModel = self.runProgressBarModel #self.pbnRemoveModel.setEnabled(False) #self.pbnStartModel.setEnabled(False) # Initializing values self.progressBarTotal.setValue(0) self.progressBarYear.setValue(0) self.progressBarModel.setValue(0) self.progressBarTotal.setRange(0,0) self.progressBarYear.setRange(0,0) self.progressBarModel.setRange(0,0) batch_name = str(self.cboOptionalIndicatorBatch.currentText()) if batch_name == '(None)': batch_name = None self.runThread = RunModelThread(get_mainwindow_instance(), self, batch_name, run_name) if duplicate and run_id is not None: from opus_core.services.run_server.run_manager import RunManager as ServicesRunManager run_manager = ServicesRunManager(ServicesDatabaseConfiguration()) run_manager.delete_everything_for_this_run(run_id = run_id) run_manager.close() # Use this signal from the thread if it is capable of producing its own status signal QObject.connect(self.runThread, SIGNAL("runFinished(PyQt_PyObject)"), self.runFinishedFromThread) QObject.connect(self.runThread, SIGNAL("runError(PyQt_PyObject)"), self.runErrorFromThread) # Use this timer to call a function in the thread to check status if the thread is unable # to produce its own signal above self.timer = QTimer() QObject.connect(self.timer, SIGNAL("timeout()"), self.runStatusFromThread) self.timer.start(1000) self.running = True self.paused = False self.runThread.start() else: print "Unexpected state in the model run..." # This is not used currently since the model can not return status... instead we use a timer to # check the status from a log file. def runPingFromThread(self,value): self.progressBar.setValue(value) #print "Ping from thread!" # Called when the model is finished... peg the percentage to 100% and stop the timer. def runFinishedFromThread(self,success): self.progressBarTotal.setValue(100) self.progressBarYear.setValue(100) self.progressBarModel.setValue(100) msg = 'Simulation ran successfully!' if success else 'Simulation failed.' self.summaryCurrentYearValue.setText(QString(msg)) self.summaryCurrentModelValue.setText(QString("Finished")) self.summaryCurrentPieceValue.setText(QString("Finished")) self.timer.stop() # Get the final logfile update after model finishes... self.logFileKey = self.runThread.modelguielement.model._get_current_log(self.logFileKey) self.running = False self.paused = False self.pbnStartModel.setText(QString("Start Simulation Run...")) #get the last year to show up in the diagnostics tab. self.yearItems[-1][1] = True self.diagnostic_year.addItem(QString(str(self.yearItems[-1][0]))) if self.runThread.batch_name is not None: all_visualizations = self.runThread.batch_processor.get_visualizations() for indicator_type, visualizations in all_visualizations: form_generator = None print indicator_type if indicator_type == 'mapnik_map' or \ indicator_type == 'matplotlib_chart': form_generator = self.mainwindow.managers['results_manager'].addViewImageIndicator elif indicator_type == 'mapnik_animated_map': form_generator = self.mainwindow.managers['results_manager'].addViewAnimationIndicator elif indicator_type == 'tab': form_generator = self.mainwindow.managers['results_manager'].addViewTableIndicator if form_generator is not None: for visualization in visualizations: form_generator(visualization = visualization, indicator_type = indicator_type) # GUI elements that show progress go here. Note that they have to be set # up first in the constructor of this class, then optionally initialized in # on_pbnStartModel_released(), then calculated and updated here, and finally # when the simulation is done running, finalized values are optionally # defined in runFinishedFromThread (because status.txt doesn't refresh at # end of the simulation. def runStatusFromThread(self): totalProgress = 0 yearProgress = 0 modelProgress = 0 boxTitle = "Simulation run initializing..." # TODO: this is for the old prog bar if self.runThread.modelguielement.model.statusfile is None: boxTitle = "Simulation run initializing..." else: # Compute percent progress for the progress bar. # The statusfile is written by the _write_status_for_gui method # in class ModelSystem in urbansim.model_coordinators.model_system # The file is ascii, with the following format (1 item per line): # current year # total number of models # number of current model that is about to run (starting with 0) # name of current model # total number of pieces of current model (could be 1) # number of current piece # description of current piece (empty string if no description) statusfile = self.runThread.modelguielement.model.statusfile try: f = open(statusfile) lines = f.readlines() f.close() # use float for all numbers to help with percent computation if len(lines) > 0: current_year = float(lines[0]) total_models = float(lines[1]) current_model = float(lines[2]) current_model_names = lines[3] current_model_display_name = current_model_names#current_model_names[0] total_pieces = float(lines[4]) current_piece = float(lines[5]) current_piece_name = lines[6].strip() total_years = float(self.end_year - self.start_year + 1) # For each year, we need to run all of the models. # year_fraction_completed is the fraction completed (ignoring the currently running year) # model_fraction_completed is the additional fraction completed for the current year modelProgress = 100.0 * (current_piece / total_pieces) yearProgress = modelProgress / total_models + 100.0 * (current_model / total_models) totalProgress = yearProgress / total_years + 100.0 * ((current_year - self.start_year) / total_years) currentYearString = "("+str(int((current_year - self.start_year))+1)+"/"+str(int(total_years))+") "+str(int(current_year)) self.summaryCurrentYearValue.setText(QString(currentYearString)) currentModelString = "("+str(int(current_model)+1)+"/"+str(int(total_models))+") "+current_model_display_name self.summaryCurrentModelValue.setText(QString(currentModelString)) currentPieceString = "("+str(int(current_piece)+1)+"/"+str(int(total_pieces))+") "+current_piece_name self.summaryCurrentPieceValue.setText(QString(currentPieceString)) boxTitle = current_model_display_name # detect if a year has been completed for item in self.yearItems: if item[0] < current_year and not item[1] : self.diagnostic_year.addItem(QString(str(item[0]))) item[1] = True #hook into indicator group computation here if (self.progressBarTotal.maximum() == 0): self.progressBarTotal.setRange(0,100) self.progressBarYear.setRange(0,100) self.progressBarModel.setRange(0,100) except IOError: boxTitle = "Simulation run is initializing..." newString = QString(boxTitle) newString.leftJustified(60) # self.simprogressGroupBox.setTitle(newString) self.progressBarTotal.setValue(totalProgress) self.progressBarYear.setValue(yearProgress) self.progressBarModel.setValue(modelProgress) self.logFileKey = self.runThread.modelguielement.model._get_current_log(self.logFileKey) def runErrorFromThread(self,errorMessage): self.running = False self.paused = False self.pbnStartModel.setText(QString("Start Simulation Run...")) MessageBox.warning(mainwindow = self.mainwindow, text = "There was a problem running the simulation.", detailed_text = errorMessage)
def _run_finished(self, success): key = self.running_key self.running_key = None size = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) self.tabwidget_visualizations.setSizePolicy(size) name = '%s/%s/%s' % key new_tab = QTabWidget(self.tabwidget_visualizations) self.tabwidget_visualizations.addTab(new_tab, name) map_widget = None tab_widget = None for (visualization_type, visualizations) in self.batch_processor.get_visualizations(): if len(visualizations) > 0: if visualization_type == 'mapnik_map': viz = visualizations[0] map_widget = ViewImageForm(viz, new_tab) map_widget.setSizePolicy(size) elif visualization_type == 'mapnik_animated_map': viz = visualizations[0] map_widget = ViewAnimationForm(viz, new_tab) map_widget.setSizePolicy(size) elif visualization_type == 'table_per_year': viz = visualizations[0] tab_widget = ViewTableForm(viz, new_tab) tab_widget.setSizePolicy(size) # else: # map_widget = self.tabMap # tab_widget = self.tabTable # if not map_widget or not tab_widget: return # self.tabMap = map_widget # self.tabTable = tab_widget if tab_widget: new_tab.addTab(tab_widget, "Table") if map_widget: new_tab.addTab(map_widget, "Map") self.already_browsed[key] = (tab_widget, map_widget) # self.lblViewIndicator.setText(QString(key[1])) # self.lblViewRun.setText(QString(key[0])) # self.lblViewYear.setText(QString(repr(key[2]))) swap = self.queued_results is not None and self.queued_results[ 0] == 'swap' if self.queued_results is not None and not swap: self.running_key = self.queued_results[0] logger.log_note( 'Generating queued results for %s on run %s for year %i' % self.running_key) self.batch_processor = self.queued_results[1] self.queued_results = None runThread = OpusGuiThread(parentThread=get_mainwindow_instance(), parentGuiElement=self, thread_object=self.batch_processor) # Use this signal from the thread if it is capable of producing its own status signal QObject.connect(runThread, SIGNAL("runFinished(PyQt_PyObject)"), self._run_finished) QObject.connect(runThread, SIGNAL("runError(PyQt_PyObject)"), self._run_error) runThread.start() else: # if swap: # (map_widget, tab_widget) = self.queued_results[1] # ## self.swap_visualizations(map_widget, tab_widget) # name = '%s/%s/%s'%key # # self.swap_visualizations(map_widget, tab_widget) # self.add_visualization(map_widget = map_widget, tab_widget = tab_widget, name = name) self.queued_results = None self.generating_results = False self.pb_generate_results.setText('Results Generated')
def on_pb_generate_results_clicked(self): run_name = self.current_run indicator_name = self.current_indicator indicator_dataset = self.current_indicator_dataset start_year = int(self.current_year) end_year = start_year if run_name is None or indicator_name is None or start_year is None: return key = (run_name, indicator_name, start_year) if key in self.already_browsed: if not self.generating_results: (tab_widget, map_widget) = self.already_browsed[key] # self.swap_visualizations(map_widget, tab_widget) self.pb_generate_results.setText('Results Generated') else: self.queued_results = ('swap', (map_widget, tab_widget)) return self.pb_generate_results.setEnabled(False) self.pb_generate_results.setText('Generating Results...') indicator_nodes = get_available_indicator_nodes(self.project) dataset = None for indicator_node in indicator_nodes: ind_dataset, name = get_variable_dataset_and_name(indicator_node) if name == indicator_name and ind_dataset == indicator_dataset: dataset = ind_dataset break if dataset is None: raise Exception('Could not find dataset for indicator %s' % indicator_name) table_params = { 'name': None, 'output_type': 'tab', 'indicators': [indicator_name], } map_params = {'name': None, 'indicators': [indicator_name]} visualizations = [('table_per_year', dataset, table_params), ('mapnik_map', dataset, map_params)] batch_processor = BatchProcessor(self.project) batch_processor.guiElement = self batch_processor.set_data(visualizations=visualizations, source_data_name=run_name, years=range(start_year, end_year + 1)) if not self.generating_results: self.generating_results = True logger.log_note( 'Generating results for %s on run %s for year %indicator_node' % (run_name, indicator_name, start_year)) self.running_key = key self.batch_processor = batch_processor batch_processor_thread = OpusGuiThread( parentThread=get_mainwindow_instance(), parentGuiElement=self, thread_object=self.batch_processor) # Use this signal from the thread if it is capable of producing its own status signal self.connect(batch_processor_thread, SIGNAL("runFinished(PyQt_PyObject)"), self._run_finished) self.connect(batch_processor_thread, SIGNAL("runError(PyQt_PyObject)"), self._run_error) batch_processor_thread.start() else: self.queued_results = (key, batch_processor)
class IndicatorBatchRunForm(QDialog, Ui_runIndicatorBatch): def __init__(self, mainwindow, resultsManagerBase, batch_name = None, run_name = None): QDialog.__init__(self, mainwindow) self.setupUi(self) #mainwindow is an OpusGui self.mainwindow = mainwindow self.resultsManagerBase = resultsManagerBase self.project = resultsManagerBase.project self.available_years_for_simulation_runs = {} self.batch_processor = BatchProcessor(project = self.project) self.batch_processor.guiElement = self self.run_name = run_name self.batch_name = batch_name self._setup_co__years() def _setup_co__years(self): runs = get_simulation_runs(self.project) for run in runs: if run.get('name') == self.run_name: years = get_years_for_simulation_run(project = self.project, simulation_run_node = run) (start,end) = (min(years), max(years)) for i in range(start, end + 1): if i not in years: continue yr = QString(repr(i)) self.co_start_year.addItem(yr) self.co_end_year.addItem(yr) for i in range(1, end - start + 2): yr = QString(repr(i)) self.co_every_year.addItem(yr) def removeElement(self): return True def on_buttonBox_accepted(self): self.buttonBox.setEnabled(False) start_year = int(self.co_start_year.currentText()) end_year = int(self.co_end_year.currentText()) increment = int(self.co_every_year.currentText()) years = range(start_year, end_year + 1, increment) # (visualization_type, dataset_name, vals) visualizations = get_batch_configuration(project = self.project, batch_name = self.batch_name) self.batch_processor.set_data( visualizations = visualizations, source_data_name = self.run_name, years = years) self.runThread = OpusGuiThread( parentThread = self.mainwindow, parentGuiElement = self, thread_object = self.batch_processor) # Use this signal from the thread if it is capable of producing its own status signal QObject.connect(self.runThread, SIGNAL("runFinished(PyQt_PyObject)"), self.runFinishedFromThread) QObject.connect(self.runThread, SIGNAL("runError(PyQt_PyObject)"), self.runErrorFromThread) self.runThread.start() # Called when the model is finished... def runFinishedFromThread(self,success): all_visualizations = self.batch_processor.get_visualizations() for indicator_type, visualizations in all_visualizations: if indicator_type == 'mapnik_map' or \ indicator_type == 'matplotlib_chart': form_generator = self.resultsManagerBase.addViewImageIndicator elif indicator_type == 'mapnik_animated_map': form_generator = self.resultsManagerBase.addViewAnimationIndicator elif indicator_type == 'tab': form_generator = self.resultsManagerBase.addViewTableIndicator if form_generator is not None: for visualization in visualizations: form_generator(visualization = visualization, indicator_type = indicator_type) # Get the final logfile update after model finishes... # self.logFileKey = self.batch_processor._get_current_log(self.logFileKey) self.buttonBox.setEnabled(True) self.close() def runErrorFromThread(self,errorMessage): MessageBox.warning(mainwindow = self.mainwindow, text = "There was a problem running the batch.", detailed_text = errorMessage)
class IndicatorBatchRunForm(QDialog, Ui_runIndicatorBatch): def __init__(self, mainwindow, resultsManagerBase, batch_name = None, run_name = None): QDialog.__init__(self, mainwindow) self.setupUi(self) #mainwindow is an OpusGui self.mainwindow = mainwindow self.resultsManagerBase = resultsManagerBase self.project = resultsManagerBase.project self.available_years_for_simulation_runs = {} self.batch_processor = BatchProcessor(project = self.project) self.batch_processor.guiElement = self self.run_name = run_name self.batch_name = batch_name self._setup_co__years() def _setup_co__years(self): years = get_years_for_simulation_run(self.project, run_name=self.run_name) start,end = min(years), max(years) for i in range(start, end + 1): if i not in years: continue yr = QString(repr(i)) self.co_start_year.addItem(yr) self.co_end_year.addItem(yr) for i in range(1, end - start + 2): yr = QString(repr(i)) self.co_every_year.addItem(yr) def removeElement(self): return True def on_buttonBox_accepted(self): self.buttonBox.setEnabled(False) start_year = int(self.co_start_year.currentText()) end_year = int(self.co_end_year.currentText()) increment = int(self.co_every_year.currentText()) years = range(start_year, end_year + 1, increment) # (visualization_type, dataset_name, vals) visualizations = get_batch_configuration(project = self.project, batch_name = self.batch_name) self.batch_processor.set_data( visualizations = visualizations, source_data_name = self.run_name, years = years) self.runThread = OpusGuiThread( parentThread = self.mainwindow, parentGuiElement = self, thread_object = self.batch_processor) # Use this signal from the thread if it is capable of producing its own status signal QObject.connect(self.runThread, SIGNAL("runFinished(PyQt_PyObject)"), self.runFinishedFromThread) QObject.connect(self.runThread, SIGNAL("runError(PyQt_PyObject)"), self.runErrorFromThread) self.runThread.start() # Called when the model is finished... def runFinishedFromThread(self,success): all_visualizations = self.batch_processor.get_visualizations() for indicator_type, visualizations in all_visualizations: if indicator_type == 'mapnik_map' or \ indicator_type == 'matplotlib_chart': form_generator = self.resultsManagerBase.addViewImageIndicator elif indicator_type == 'mapnik_animated_map': form_generator = self.resultsManagerBase.addViewAnimationIndicator elif indicator_type == 'tab': form_generator = self.resultsManagerBase.addViewTableIndicator if form_generator is not None: for visualization in visualizations: form_generator(visualization = visualization, indicator_type = indicator_type) # Get the final logfile update after model finishes... # self.logFileKey = self.batch_processor._get_current_log(self.logFileKey) self.buttonBox.setEnabled(True) self.close() def runErrorFromThread(self,errorMessage): MessageBox.warning(mainwindow = self.mainwindow, text = "There was a problem running the batch.", detailed_text = errorMessage)