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 runIndicatorBatch(self): visualizations = get_batch_configuration(project=self.project, batch_name=self.batch_name) start, end = self.get_years() self.batch_processor = BatchProcessor(project=self.project) self.batch_processor.errorCallback = self.errorCallback self.batch_processor.finishedCallback = self.indicatorBatchFinishedCallback self.batch_processor.set_data(visualizations=visualizations, source_data_name=self.get_run_name(), years=range(start, end + 1)) self.batch_processor.run()
def generate_indicators(self): self.filepaths = {} for name, (projconfig, batchname, visname, datasourcename, year) in self.indicators.items(): op = OpusProject() op.open(os.path.join(PROJECTCONFIGBASE, projconfig)) bp = BatchProcessor(op) visualizationsconf = get_batch_configuration(project=op, batch_name=batchname, vis_name=visname) bp.set_data(visualizations=visualizationsconf, source_data_name=datasourcename, years=[year, year]) bp.run() visualizations = bp.get_visualizations() # visualizations in batch assert len(visualizations) == 1 vistype, visualizations = visualizations[0] # indicators in visualization assert len(visualizations) == 1 self.filepaths[name] = visualizations[0].get_file_path()
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 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 runIndicatorBatch(self): visualizations = get_batch_configuration( project = self.project, batch_name = self.batch_name) start, end = self.get_years() self.batch_processor = BatchProcessor(project = self.project) self.batch_processor.errorCallback = self.errorCallback self.batch_processor.finishedCallback = self.indicatorBatchFinishedCallback self.batch_processor.set_data( visualizations = visualizations, source_data_name = self.get_run_name(), years = range(start, end + 1)) self.batch_processor.run()
def run(xml_configuration, indicator_batch, run_name, cache_directory, years): from opus_gui.results_manager.run.batch_processor import BatchProcessor project = OpusProject() project.open(xml_configuration) bp = BatchProcessor(project) visualizations = get_batch_configuration(project = project, batch_name = indicator_batch) bp.set_data(visualizations=visualizations, source_data_name = run_name, cache_directory = cache_directory, years = eval(years), ) bp.errorCallback = lambda x: x ## bp.finishedCallback = lambda x: x ## hack to work around BatchProcessor bp.run()
def generate_indicators(self): self.filepaths = {} for name, (projconfig, batchname, visname, datasourcename, year) in self.indicators.items(): op = OpusProject() op.open(os.path.join(PROJECTCONFIGBASE, projconfig)) bp = BatchProcessor(op) visualizationsconf = get_batch_configuration(project = op, batch_name = batchname, vis_name = visname) bp.set_data(visualizations = visualizationsconf, source_data_name = datasourcename, years = [year,year]) bp.run() visualizations = bp.get_visualizations() # visualizations in batch assert len(visualizations) == 1 vistype, visualizations = visualizations[0] # indicators in visualization assert len(visualizations) == 1 self.filepaths[name] = visualizations[0].get_file_path()
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)
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_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)
try: import wingdbstub except: pass option_group = MakeIndicatorsOptionGroup() parser = option_group.parser (options, args) = parser.parse_args() if not (options.xml_configuration and options.indicator_batch and ( options.cache_directory or options.run_name) and options.years ): parser.print_help() sys.exit(0) from opus_gui.results_manager.run.batch_processor import BatchProcessor project = OpusProject() project.open(options.xml_configuration) bp = BatchProcessor(project) visualizations = get_batch_configuration(project = project, batch_name = options.indicator_batch) bp.set_data(visualizations=visualizations, source_data_name = options.run_name, cache_directory = options.cache_directory, years = eval(options.years), ) bp.errorCallback = lambda x: x ## bp.finishedCallback = lambda x: x ## hack to work around BatchProcessor bp.run()
class RunModelThread(QThread): def __init__(self, mainwindow, modelguielement, batch_name=None, run_name=None): QThread.__init__(self, mainwindow) self.modelguielement = modelguielement self.modelguielement.model.run_name = run_name self.batch_name = batch_name self.run_name = run_name self.project = get_mainwindow_instance().project def run(self): self.modelguielement.model.progressCallback = self.progressCallback self.modelguielement.model.startedCallback = self.startedCallback self.modelguielement.model.finishedCallback = self.finishedCallback self.modelguielement.model.errorCallback = self.errorCallback if self.run_name.strip() != '': self.modelguielement.model.run_name = self.run_name self.modelguielement.model.run() def pause(self): return self.modelguielement.model.pause() def resume(self): return self.modelguielement.model.resume() def cancel(self): return self.modelguielement.model.cancel() def progressCallback(self, percent): print "Ping From Model" self.emit(SIGNAL("runPing(PyQt_PyObject)"), percent) def startedCallback(self, run_id, run_name, scenario_name, run_resources): cache_directory = os.path.normpath(run_resources['cache_directory']) start_year, end_year = run_resources['years'] baseyear = run_resources['base_year'] add_simulation_run(self.project, cache_directory=cache_directory, scenario_name=scenario_name, run_name=run_name, start_year=baseyear, end_year=end_year, run_id=run_id) def finishedCallback(self, success, run_name): if success: print "Success returned from Model" if self.modelguielement.model.cancelled: self.modelguielement.model.run_manager.cancel_run() else: if self.batch_name is not None: self.runIndicatorBatch() else: print "Error returned from Model" delete_simulation_run(self.project, run_name=run_name) self.modelguielement.model.run_manager.close() self.emit(SIGNAL("runFinished(PyQt_PyObject)"), success) def get_run_name(self): return self.modelguielement.model.run_name def get_years(self): return self.modelguielement.model.config['years'] def runIndicatorBatch(self): visualizations = get_batch_configuration(project=self.project, batch_name=self.batch_name) start, end = self.get_years() self.batch_processor = BatchProcessor(project=self.project) self.batch_processor.errorCallback = self.errorCallback self.batch_processor.finishedCallback = self.indicatorBatchFinishedCallback self.batch_processor.set_data(visualizations=visualizations, source_data_name=self.get_run_name(), years=range(start, end + 1)) self.batch_processor.run() def indicatorBatchFinishedCallback(self, success): return def errorCallback(self, errorMessage): self.emit(SIGNAL("runError(PyQt_PyObject)"), 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): 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 RunModelThread(QThread): def __init__(self, mainwindow, modelguielement, batch_name = None, run_name = None): QThread.__init__(self, mainwindow) self.modelguielement = modelguielement self.modelguielement.model.run_name = run_name self.batch_name = batch_name self.run_name = run_name self.project = get_mainwindow_instance().project self.restart = False self.run_id = None self.config = None self.restart_year = None def run(self): self.modelguielement.model.progressCallback = self.progressCallback self.modelguielement.model.startedCallback = self.startedCallback self.modelguielement.model.finishedCallback = self.finishedCallback self.modelguielement.model.errorCallback = self.errorCallback if self.run_name.strip() != '': self.modelguielement.model.run_name = self.run_name if not self.restart: self.modelguielement.model.run() else: self.modelguielement.model.restart_run(self.run_id, self.config, self.restart_year, end_year=self.end_year, run_name=self.run_name) def pause(self): return self.modelguielement.model.pause() def resume(self): return self.modelguielement.model.resume() def cancel(self): return self.modelguielement.model.cancel() def setup_restart_run(self, run_id, config, restart_year, end_year=None, run_name=None): self.restart = True self.run_id = run_id self.config = config self.restart_year = restart_year self.end_year = end_year if run_name is not None: self.run_name = run_name def progressCallback(self,percent): print "Ping From Model" self.emit(SIGNAL("runPing(PyQt_PyObject)"),percent) def startedCallback(self, run_id, run_name, scenario_name, run_resources, status): cache_directory = os.path.normpath(run_resources['cache_directory']) start_year, end_year = run_resources['years'] baseyear = run_resources['base_year'] add_simulation_run(self.project, cache_directory = cache_directory, scenario_name = scenario_name, run_name = run_name, start_year = baseyear, end_year = end_year, run_id = run_id, status = status) def finishedCallback(self, success, run_name): if success: print "Success returned from Model" if self.modelguielement.model.cancelled: self.modelguielement.model.run_manager.cancel_run() else: if self.batch_name is not None: self.runIndicatorBatch() else: print "Error returned from Model" sync_available_runs(self.project) self.modelguielement.model.run_manager.close() self.emit(SIGNAL("runFinished(PyQt_PyObject)"),success) def get_run_name(self): return self.modelguielement.model.run_name def get_years(self): return self.modelguielement.model.config['years'] def runIndicatorBatch(self): visualizations = get_batch_configuration( project = self.project, batch_name = self.batch_name) start, end = self.get_years() self.batch_processor = BatchProcessor(project = self.project) self.batch_processor.errorCallback = self.errorCallback self.batch_processor.finishedCallback = self.indicatorBatchFinishedCallback self.batch_processor.set_data( visualizations = visualizations, source_data_name = self.get_run_name(), years = range(start, end + 1)) self.batch_processor.run() def indicatorBatchFinishedCallback(self, success): return def errorCallback(self,errorMessage): self.emit(SIGNAL("runError(PyQt_PyObject)"),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 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)