def regrid_climos(env, main_comm): """ regrid_climos - regrid the climos into a lat/lon grid """ import glob env['DIAG_CODE'] = env['NCLPATH'] env['WKDIR'] = env['test_path_diag'] env['WORKDIR'] = env['test_path_diag'] if main_comm.is_manager(): if not os.path.exists(env['WKDIR']): os.makedirs(env['WKDIR']) main_comm.sync() # If SE grid, convert to lat/lon grid regrid_script = 'regridclimo.ncl' # Convert Test Case if (env['test_regrid'] == 'True'): # get list of climo files to regrid # create the working directory first before calling the base class prerequisites endYr = (int(env['test_first_yr']) + int(env['test_nyrs'])) - 1 subdir = '{0}.{1}-{2}'.format(env['test_casename'], env['test_first_yr'], endYr) workdir = '{0}/{1}'.format(env['test_path_climo'], subdir) climo_files = glob.glob(workdir + '/*.nc') # partition the climo files between the ranks so each rank will get a portion of the list to regrid local_climo_files = main_comm.partition(climo_files, func=partition.EqualStride(), involved=True) for climo_file in local_climo_files: diagUtilsLib.atm_regrid(climo_file, regrid_script, env['test_res_in'], env['test_res_out'], env) main_comm.sync() # Convert CNTL Case if (env['MODEL_VS_MODEL'] and env['cntl_regrid']): if main_comm.is_manager(): print('in cntl regrid') # get list of climo files to regrid endYr = (int(env['cntl_first_yr']) + int(env['cntl_nyrs'])) - 1 subdir = '{0}.{1}-{2}'.format(env['cntl_casename'], env['cntl_first_yr'], endYr) workdir = '{0}/{1}'.format(env['cntl_path_climo'], subdir) climo_files = glob.glob(workdir + '/*.nc') # partition the climo files between the ranks so each rank will get a portion of the list to regrid local_climo_files = main_comm.partition(climo_files, func=partition.EqualStride(), involved=True) for climo_file in local_climo_files: diagUtilsLib.atm_regrid(climo_file, regrid_script, env['cntl_res_in'], env['cntl_res_out'], env)
def testEqualStride(self): for inp in self.inputs: pfunc = partition.EqualStride() actual = pfunc(*inp) expected = inp[0][inp[1]::inp[2]] msg = test_info_msg( 'EqualStride', inp[0], inp[1], inp[2], actual, expected) print(msg) testing.assert_array_equal(actual, expected, msg)
def run_diagnostics(self, env, scomm): """ call the necessary plotting routines to generate diagnostics plots """ super(modelVsControl, self).run_diagnostics(env, scomm) scomm.sync() # setup some global variables requested_plots = list() local_requested_plots = list() # define the templatePath for all tasks templatePath = '{0}/diagnostics/diagnostics/ocn/Templates'.format( env['POSTPROCESS_PATH']) # all the plot module XML vars start with MVC_PM_ need to strip off MVC_ for key, value in env.iteritems(): if (re.search("\AMVC_PM_", key) and value.upper() in ['T', 'TRUE']): k = key[4:] requested_plots.append(k) scomm.sync() print('model vs. control - after scomm.sync requested_plots = {0}'. format(requested_plots)) if scomm.is_manager(): print('model vs. control - User requested plot modules:') for plot in requested_plots: print(' {0}'.format(plot)) print('model vs. control - Creating plot html header') templateLoader = jinja2.FileSystemLoader(searchpath=templatePath) templateEnv = jinja2.Environment(loader=templateLoader) template_file = 'model_vs_control.tmpl' template = templateEnv.get_template(template_file) # get the current datatime string for the template now = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S') # set the template variables templateVars = { 'casename': env['CASE'], 'control_casename': env['CNTRLCASE'], 'tagname': env['CESM_TAG'], 'start_year': env['YEAR0'], 'stop_year': env['YEAR1'], 'control_start_year': env['CNTRLYEAR0'], 'control_stop_year': env['CNTRLYEAR1'], 'today': now } print('model vs. control - Rendering plot html header') plot_html = template.render(templateVars) scomm.sync() print('model vs. control - Partition requested plots') # partition requested plots to all tasks local_requested_plots = scomm.partition(requested_plots, func=partition.EqualStride(), involved=True) scomm.sync() for requested_plot in local_requested_plots: try: plot = ocn_diags_plot_factory.oceanDiagnosticPlotFactory( 'control', requested_plot) print( 'model vs. control - Checking prerequisite for {0} on rank {1}' .format(plot.__class__.__name__, scomm.get_rank())) plot.check_prerequisites(env) print( 'model vs. control - Generating plots for {0} on rank {1}'. format(plot.__class__.__name__, scomm.get_rank())) plot.generate_plots(env) print( 'model vs. control - Converting plots for {0} on rank {1}'. format(plot.__class__.__name__, scomm.get_rank())) plot.convert_plots(env['WORKDIR'], env['IMAGEFORMAT']) except RuntimeError as e: # unrecoverable error, bail! print("Skipped '{0}' and continuing!".format(requested_plot)) print(e) scomm.sync() # initialize OrderedDict with plot_order list entries as key html_order = collections.OrderedDict() for plot in env['MVC_PLOT_ORDER'].split(): html_order[plot] = '' if scomm.is_manager(): for plot in env['MVC_PLOT_ORDER'].split(): if plot in requested_plots: print('calling get_html for plot = {0}'.format(plot)) plot_obj = ocn_diags_plot_factory.oceanDiagnosticPlotFactory( 'control', plot) shortname, html = plot_obj.get_html( env['WORKDIR'], templatePath, env['IMAGEFORMAT']) html_order[shortname] = html for k, v in html_order.iteritems(): print('Adding html for plot = {0}'.format(k)) plot_html += v print('model vs. control - Adding footer html') with open('{0}/footer.tmpl'.format(templatePath), 'r') as tmpl: plot_html += tmpl.read() print('model vs. control - Writing plot index.html') with open('{0}/index.html'.format(env['WORKDIR']), 'w') as index: index.write(plot_html) print( '***************************************************************************' ) print( 'Successfully completed generating ocean diagnostics model vs. control plots' ) print( '***************************************************************************' ) scomm.sync() # append the web_dir location to the env key = 'OCNDIAG_WEBDIR_{0}'.format(self._name) env[key] = env['WORKDIR'] return env
def run_diagnostics(self, env, scomm): """ call the necessary plotting routines to generate diagnostics plots """ super(modelVsModel, self).run_diagnostics(env, scomm) scomm.sync() # setup some global variables requested_plot_sets = list() local_requested_plots = list() local_html_list = list() # all the plot module XML vars start with 'set_' need to strip that off for key, value in env.iteritems(): if ("PLOT_" in key and value == 'True'): ## if ("DIFF" in key or 'PLOT_REGIONS' in key): if ("DIFF" in key): requested_plot_sets.append(key) scomm.sync() # partition requested plots to all tasks # first, create plotting classes and get the number of plots each will created requested_plots = {} set_sizes = {} for plot_set in requested_plot_sets: requested_plots.update( ice_diags_plot_factory.iceDiagnosticPlotFactory(plot_set, env)) # partition based on the number of plots each set will create local_plot_list = scomm.partition(requested_plots.keys(), func=partition.EqualStride(), involved=True) timer = timekeeper.TimeKeeper() # loop over local plot lists - set env and then run plotting script #for plot_id,plot_class in local_plot_list.interitems(): timer.start(str(scomm.get_rank()) + "ncl total time on task") for plot_set in local_plot_list: timer.start(str(scomm.get_rank()) + plot_set) plot_class = requested_plots[plot_set] # set all env variables (global and particular to this plot call plot_class.check_prerequisites(env) # Stringify the env dictionary for name, value in plot_class.plot_env.iteritems(): plot_class.plot_env[name] = str(value) # call script to create plots for script in plot_class.ncl_scripts: diagUtilsLib.generate_ncl_plots(plot_class.plot_env, script) timer.stop(str(scomm.get_rank()) + plot_set) timer.stop(str(scomm.get_rank()) + "ncl total time on task") scomm.sync() print(timer.get_all_times()) # set html files if scomm.is_manager(): # Setup (local) web directories env['HTML_HOME'] = env['POSTPROCESS_PATH'] + '/ice_diag/web/' web_dir = env['WKDIR'] + '/yrs' + env['BEGYR_CONT'] + '-' + env[ 'ENDYR_CONT'] if env['CLEANUP_FILES'].lower() in ['t', 'true' ] and os.path.exists(web_dir): shutil.rmtree(web_dir) if not os.path.exists(web_dir): os.mkdir(web_dir) if not os.path.exists(web_dir + '/contour'): os.mkdir(web_dir + '/contour') if not os.path.exists(web_dir + '/vector'): os.mkdir(web_dir + '/vector') if not os.path.exists(web_dir + '/line'): os.mkdir(web_dir + '/line') if not os.path.exists(web_dir + '/obs'): os.mkdir(web_dir + '/obs') # Move images tot the oppropriate directories plot_dir_map = { 'icesat': 'obs', 'ASPeCt': 'obs', 'diff_con_': 'contour', 'diff_vec_': 'vector', 'line': 'line', 'clim': 'line' } for key, dir in plot_dir_map.iteritems(): glob_string = env['WKDIR'] + '/*' + key + '*.png' imgs = glob.glob(glob_string) if imgs > 0: for img in imgs: new_fn = web_dir + '/' + dir + '/' + os.path.basename( img) os.rename(img, new_fn) # Create/format the html files and copy txt and map files shutil.copy(env['HTML_HOME'] + '/ICESat.txt', web_dir + '/obs/ICESat.txt') shutil.copy(env['HTML_HOME'] + '/ASPeCt.txt', web_dir + '/obs/ASPeCt.txt') glob_string = env['HTML_HOME'] + '/maps/*' maps = glob.glob(glob_string) for map in maps: mn = os.path.basename(map) shutil.copy(map, web_dir + '/' + mn) print('DEBUG: model_vs_model web_dir = {0}'.format(web_dir)) html_dir = env['HTML_HOME'] create_ice_html.create_plotset_html( html_dir + '/index_diff_temp.html', web_dir + '/index.html', env) create_ice_html.create_plotset_html( html_dir + '/contour_diff.html', web_dir + '/contour.html', env) create_ice_html.create_plotset_html( html_dir + '/timeseries_diff.html', web_dir + '/timeseries.html', env) create_ice_html.create_plotset_html( html_dir + '/regional_diff.html', web_dir + '/regional.html', env) create_ice_html.create_plotset_html(html_dir + '/vector_diff.html', web_dir + '/vector.html', env) # setup the unique ICEDIAG_WEBDIR_MODEL_VS_MODEL output file env_file = '{0}/env_diags_ice.xml'.format(env['PP_CASE_PATH']) key = 'ICEDIAG_WEBDIR_{0}'.format(self._name) value = env['WKDIR'] ##web_file = '{0}/web_dirs/{1}.{2}-{3}'.format(env['PP_CASE_PATH'], key, scomm.get_size(), scomm.get_rank() ) web_file = '{0}/web_dirs/{1}.{2}'.format( env['PP_CASE_PATH'], key, datetime.datetime.now().strftime('%Y-%m-%d_%H%M%S')) try: diagUtilsLib.write_web_file(web_file, 'ice', key, value) except: print( 'WARNING ice model_vs_model unable to write {0}={1} to {2}' .format(key, value, web_file)) print( '*******************************************************************************' ) print( 'Successfully completed generating ice diagnostics model vs. model plots' ) print( '*******************************************************************************' )
def main(options, main_comm, debugMsg): """setup the environment for running the diagnostics in parallel. Calls 6 different diagnostics generation types: model vs. observation (optional BGC - ecosystem) model vs. control (optional BGC - ecosystem) model time-series (optional BGC - ecosystem) Arguments: options (object) - command line options main_comm (object) - MPI simple communicator object debugMsg (object) - vprinter object for printing debugging messages The env_diags_ocn.xml configuration file defines the way the diagnostics are generated. See (website URL here...) for a complete desciption of the env_diags_ocn XML options. """ # initialize the environment dictionary envDict = dict() # CASEROOT is given on the command line as required option --caseroot if main_comm.is_manager(): caseroot = options.caseroot[0] debugMsg('caseroot = {0}'.format(caseroot), header=True, verbosity=2) debugMsg('calling initialize_main', header=True, verbosity=2) envDict = initialize_main(envDict, caseroot, debugMsg, options.standalone) debugMsg('calling check_ncl_nco', header=True, verbosity=2) diagUtilsLib.check_ncl_nco(envDict) # broadcast envDict to all tasks envDict = main_comm.partition(data=envDict, func=partition.Duplicate(), involved=True) sys.path.append(envDict['PATH']) main_comm.sync() # get list of diagnostics types to be created diag_list = list() num_of_diags = 0 if main_comm.is_manager(): diag_list, diag_dict = setup_diags(envDict) num_of_diags = len(diag_list) if num_of_diags == 0: print('No ocean diagnostics specified. Please check the {0}/env_diags_ocn.xml settings.'.format(envDict['PP_CASE_PATH'])) sys.exit(1) print('User requested diagnostics:') for diag in diag_list: print(' {0}'.format(diag)) try: os.makedirs(envDict['WORKDIR']) except OSError as exception: if exception.errno != errno.EEXIST: err_msg = 'ERROR: ocn_diags_generator.py problem accessing the working directory {0}'.format(envDict['WORKDIR']) raise OSError(err_msg) debugMsg('Ocean diagnostics - Creating main index.html page', header=True, verbosity=2) # define the templatePath templatePath = '{0}/diagnostics/diagnostics/ocn/Templates'.format(envDict['POSTPROCESS_PATH']) templateLoader = jinja2.FileSystemLoader( searchpath=templatePath ) templateEnv = jinja2.Environment( loader=templateLoader ) template_file = 'ocean_diagnostics.tmpl' template = templateEnv.get_template( template_file ) # get the current datatime string for the template now = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S') # set the template variables templateVars = { 'casename' : envDict['CASE'], 'tagname' : envDict['CESM_TAG'], 'diag_dict' : diag_dict, 'control_casename' : envDict['CNTRLCASE'], 'start_year' : envDict['YEAR0'], 'stop_year' : envDict['YEAR1'], 'control_start_year' : envDict['CNTRLYEAR0'], 'control_stop_year' : envDict['CNTRLYEAR1'], 'today': now, 'tseries_start_year' : envDict['TSERIES_YEAR0'], 'tseries_stop_year' : envDict['TSERIES_YEAR1'] } # write the main index.html page to the top working directory main_html = template.render( templateVars ) with open( '{0}/index.html'.format(envDict['WORKDIR']), 'w') as index: index.write(main_html) debugMsg('Ocean diagnostics - Copying stylesheet', header=True, verbosity=2) shutil.copy2('{0}/Templates/diag_style.css'.format(envDict['POSTPROCESS_PATH']), '{0}/diag_style.css'.format(envDict['WORKDIR'])) debugMsg('Ocean diagnostics - Copying logo files', header=True, verbosity=2) if not os.path.exists('{0}/logos'.format(envDict['WORKDIR'])): os.mkdir('{0}/logos'.format(envDict['WORKDIR'])) for filename in glob.glob(os.path.join('{0}/Templates/logos'.format(envDict['POSTPROCESS_PATH']), '*.*')): shutil.copy(filename, '{0}/logos'.format(envDict['WORKDIR'])) # setup the unique OCNDIAG_WEBDIR output file env_file = '{0}/env_diags_ocn.xml'.format(envDict['PP_CASE_PATH']) key = 'OCNDIAG_WEBDIR' value = envDict['WORKDIR'] ##web_file = '{0}/web_dirs/{1}.{2}-{3}'.format(envDict['PP_CASE_PATH'], key, main_comm.get_size(), main_comm.get_rank() ) web_file = '{0}/web_dirs/{1}.{2}'.format(envDict['PP_CASE_PATH'], key, datetime.datetime.now().strftime('%Y-%m-%d_%H%M%S')) try: diagUtilsLib.write_web_file(web_file, 'ocn', key, value) except: print('WARNING ocn_diags_generator unable to write {0}={1} to {2}'.format(key, value, web_file)) main_comm.sync() # broadcast the diag_list to all tasks num_of_diags = main_comm.partition(num_of_diags, func=partition.Duplicate(), involved=True) diag_list = main_comm.partition(data=diag_list, func=partition.Duplicate(), involved=True) main_comm.sync() # initialize some variables for distributing diagnostics across the communicators diags_send = diag_list gmaster = main_comm.is_manager() gsize = main_comm.get_size() grank = main_comm.get_rank() local_diag_list = list() # divide the main communicator into sub_communicators to be passed to each diag class # split mpi comm world if the size of the communicator > 1 and the num_of_diags > 1 if gsize > 1 and num_of_diags > 1: temp_color = (grank % num_of_diags) if (temp_color == num_of_diags): temp_color = temp_color - 1 groups = list() for g in range(0,num_of_diags): groups.append(g) debugMsg('global_rank {0}, temp_color {1}, #of groups(diag types) {2}, groups {3}, diag_list {4}'.format(grank, temp_color, num_of_diags, groups, diag_list), header=True, verbosity=2) group = groups[temp_color] inter_comm, multi_comm = main_comm.divide(group) color = inter_comm.get_color() lsize = inter_comm.get_size() lrank = inter_comm.get_rank() lmaster = inter_comm.is_manager() debugMsg('color {0}, lsize {1}, lrank {2}, lmaster {3}'.format(color, lsize, lrank, lmaster), header=True, verbosity=2) # partition the diag_list between communicators DIAG_LIST_TAG = 10 if lmaster: local_diag_list = multi_comm.partition(diag_list,func=partition.EqualStride(),involved=True) debugMsg('lrank = {0} local_diag_list = {1}'.format(lrank, local_diag_list), header=True, verbosity=2) for b in range(1, lsize): diags_send = inter_comm.ration(data=local_diag_list, tag=DIAG_LIST_TAG) debugMsg('b = {0} diags_send = {1} lsize = {2}'.format(b, diags_send, lsize), header=True, verbosity=2) else: local_diag_list = inter_comm.ration(tag=DIAG_LIST_TAG) debugMsg('local_diag_list {0}',format(local_diag_list), header=True, verbosity=2) else: inter_comm = main_comm lmaster = main_comm.is_manager() lsize = main_comm.get_size() lrank = main_comm.get_rank() local_diag_list = diag_list inter_comm.sync() main_comm.sync() # loop through the local_diag_list for requested_diag in local_diag_list: try: debugMsg('requested_diag {0}, lrank {1}, lsize {2}, lmaster {3}'.format(requested_diag, lrank, lsize, lmaster), header=True, verbosity=2) diag = ocn_diags_factory.oceanDiagnosticsFactory(requested_diag) # check the prerequisites for the diagnostics types debugMsg('Checking prerequisites for {0}'.format(diag.__class__.__name__), header=True, verbosity=2) skip_key = '{0}_SKIP'.format(requested_diag) if lmaster: try: envDict = diag.check_prerequisites(envDict) except ocn_diags_bc.PrerequisitesError: print("Problem with check_prerequisites for '{0}' skipping!".format(requested_diag)) envDict[skip_key] = True except RuntimeError as e: # unrecoverable error, bail! print(e) envDict['unrecoverableErrorOnMaster'] = True inter_comm.sync() # broadcast the envDict envDict = inter_comm.partition(data=envDict, func=partition.Duplicate(), involved=True) if envDict.has_key('unrecoverableErrorOnMaster'): raise RuntimeError # run the diagnostics type on each inter_comm if not envDict.has_key(skip_key): # set the shell env using the values set in the XML and read into the envDict across all tasks cesmEnvLib.setXmlEnv(envDict) # run the diagnostics envDict = diag.run_diagnostics(envDict, inter_comm) inter_comm.sync() except ocn_diags_bc.RecoverableError as e: # catch all recoverable errors, print a message and continue. print(e) print("Skipped '{0}' and continuing!".format(requested_diag)) except RuntimeError as e: # unrecoverable error, bail! print(e) return 1 main_comm.sync()
def testOutOfBounds(self): self.assertRaises( IndexError, partition.EqualLength(), [1, 2, 3], 3, 3) self.assertRaises( IndexError, partition.EqualStride(), [1, 2, 3], 7, 3)
def testEqualStride(self): for inp in self.inputs: pfunc = partition.EqualStride() actual = pfunc(*inp) expected = list(inp[0][inp[1]::inp[2]]) self.assertEqual(actual, expected)
def compute_averages(self, spec): ''' Sets up the run information and computes the averages. @param spec An instance of the Specification class which holds the user settings that define which averages to compute, directories, file prefixes, etc ''' import os, sys import rover import climAverager import climFileIO import average_types as ave_t import regionOpts import string import collections from asaptools import timekeeper from asaptools import partition #============================================================================== # # Initialize # #============================================================================== # Initialize the timekeeper class and start 'total' timer timer = timekeeper.TimeKeeper() timer.start("Total Time") # Initialize some timers that are not used by all tasks timer.reset("Send Average Time") timer.reset("Variable fetch time") timer.reset("Recv Average Time") timer.reset("Write Netcdf Averages") timer.reset("Variable fetch time") timer.reset("Time to compute Average") # Check average list to make sure it complies with the standards ave_t.average_compliance(spec.avg_list) # Check if I'm the global master g_master = spec.main_comm.is_manager() for tag in spec.m_id: file_pattern = list(spec.file_pattern) if ('-999' not in tag): prefix = spec.prefix + '_' + tag p_index = file_pattern.index('$prefix') t_index = file_pattern.index('$m_id') for i in range(p_index + 1, t_index + 1): del file_pattern[p_index + 1] else: prefix = spec.prefix # Sort through the average list and figure out dependencies and do # averages in steps if need be. avg_dict = {0: spec.avg_list} for i in range(1, 20): avg_dict[i] = [] avg_dict = ave_t.sort_depend(avg_dict, 0, spec.out_directory, prefix, spec.regions) print avg_dict # Initialize the tag for the average send/recv AVE_TAG = 40 VNAME_TAG = 41 #start_level = 0 start_level = min(avg_dict.keys()) found_level = False #for i in range(0,len(avg_dict)): # if found_level == False: # if (i in avg_dict): # start_level = i # found_level = True ordered_avg_dict = collections.OrderedDict(avg_dict) #for i in range(start_level,len(avg_dict)): for i, value in ordered_avg_dict.items(): # Initialize some containers var_list = [] full_hist_dict = {} hist_dict = {} #============================================================================== # # Set the hist_dict up with file references for all years/months. # Create a list of all variables and meta variables within the file # and set the final variable list passed on user preferences. # #============================================================================== ## Set var_list and file info dictionary timer.start("Define history dictionary") if (spec.hist_type == 'series'): full_hist_dict, full_var_list, meta_list, key = rover.set_slices_and_vars_time_series( spec.in_directory, file_pattern, spec.date_pattern, prefix, spec.suffix, spec.year0, spec.year1, spec.split, spec.split_files) else: full_hist_dict, full_var_list, meta_list, key = rover.set_slices_and_vars_time_slice( spec.in_directory, file_pattern, prefix, spec.suffix, spec.year0, spec.year1) timer.stop("Define history dictionary") # Set variable list. If there was a variable list passed to the averager, use this list. Other wise, # use all variables within the file. if (len(spec.varlist) > 0): var_list = spec.varlist for v in full_var_list: if '__meta' in v: var_list.append(v) else: var_list = full_var_list meta_list = list(set(meta_list)) var_list = list(set(var_list)) #============================================================================== # # Workload Distribution # #============================================================================== # Each intercommunicator recieves a list of averages it's responsible for # Each mpi task within that intercommunicator gets a portion of the variable list num_of_avg = len(avg_dict[i]) min_procs_per_ave = min(4, spec.main_comm.get_size()) # Override user selection if they picked less than 2 or # the variable list is less than the min procs per sub-communicator if (min_procs_per_ave < 2 or len(var_list) <= (min_procs_per_ave - 1)): min_procs_per_ave = 2 # If running in paralllel mode, split the communicator and partition the averages if (spec.serial == False): size = spec.main_comm.get_size() rank = spec.main_comm.get_rank() # split mpi comm world temp_color = (rank // min_procs_per_ave) % num_of_avg num_of_groups = size / min_procs_per_ave if (temp_color == num_of_groups): temp_color = temp_color - 1 groups = [] for g in range(0, num_of_groups): groups.append(g) #print 'g_rank:',rank,'size:',size,'#of ave:',num_of_avg,'min_procs:',min_procs_per_ave,'temp_color:',temp_color,'#of groups',num_of_groups,'groups:',groups group = groups[temp_color] inter_comm, multi_comm = spec.main_comm.divide(group) color = inter_comm.get_color() lsize = inter_comm.get_size() lrank = inter_comm.get_rank() #g_master = spec.main_comm.is_manager() l_master = inter_comm.is_manager() #print 'global rank: ',rank,'local rank: ',lrank,'color: ',color,'tempcolor: ',temp_color,'group: ',group,'is local master: ',l_master laverages = [] AVE_LIST_TAG = 50 # Partion the average task list amoung the inter/split communicators if (l_master): laverages = multi_comm.partition( avg_dict[i], func=partition.EqualStride(), involved=True) for b in range(1, lsize): laverages_send = inter_comm.ration( data=laverages, tag=AVE_LIST_TAG) else: laverages = inter_comm.ration(tag=AVE_LIST_TAG) else: # Running in serial mode. Just copy the average list. laverages = avg_dict[i] inter_comm = spec.main_comm lsize = inter_comm.get_size() #g_master = spec.main_comm.is_manager() l_master = inter_comm.is_manager() # Partition the variable list between the tasks of each communicator if (lsize > 1 and spec.serial == False): lvar_list = inter_comm.partition( var_list, func=partition.EqualStride(), involved=False) if (l_master): lvar_list = var_list else: lvar_list = var_list #print rank,lvar_list #print(rank,'averages :',laverages, ' vars :',lvar_list) #============================================================================== # # Create the output directory if it doesn't exist # #============================================================================== if spec.serial or g_master: if not os.path.exists(spec.out_directory): os.makedirs(spec.out_directory) spec.main_comm.sync() #============================================================================== # # Main Averaging Loop # #============================================================================== # Files are only split for the first loop. When the depend averages start, they will operate on files # that are already stiched together. if (i != 0): spec.split_name = 'null' spec.split = False spec.split_files = 'null' # Toggle to incate that extra variables were added to the local file list (only do once per average level added_extra_vars = False for ave in laverages: for split_name in spec.split_files.split(","): # Split apart the average info to get type of average and year(s) ave_descr = ave.split(':') if ('hor.meanyr' in ave_descr[0] or 'hor.meanConcat' in ave_descr[0]): ave_name_split = ave_descr[0].split('_') region_num = ave_name_split[len(ave_name_split) - 1] region_name = spec.regions[int(region_num)] # Remove the region number as part of the average name ave_descr[0] = ave_name_split[0] else: region_name = 'null' region_num = -99 # If the average depends on other averages that have to be computed, create a new temporary dictionary if '__d' in ave_descr: yr0 = ave_descr[1] if (len(ave_descr) > 2 and '_d' not in ave_descr[2]): yr1 = ave_descr[2] else: yr1 = ave_descr[1] hist_dict = rover.set_slices_and_vars_depend( spec.out_directory, file_pattern, prefix, yr0, yr1, ave_t.average_types[ave_descr[0]], ave_descr[0], region_name) else: hist_dict = dict(full_hist_dict) # If concat' mean_diff_rms files, for each var, also add the _DIFF and _RMS variables. if ('hor.meanConcat' in ave_descr and added_extra_vars == False): new_vars = [] for v in lvar_list: if '__meta' not in v: new_vars.append(v + '_DIFF') new_vars.append(v + '_RMS') lvar_list = lvar_list + new_vars added_extra_vars = True # Create and define the average file timer.start("Create/Define Netcdf File") if (len(ave_descr) < 3 or 'hor.meanyr' in ave_descr): ave_date = string.zfill(ave_descr[1], 4) ave_date2 = str(ave_descr[1]) else: date1 = string.zfill(ave_descr[1], 4) date2 = string.zfill(ave_descr[2], 4) ave_date = date1 + '-' + date2 ave_date2 = str(ave_descr[1]) + '-' + str( ave_descr[2]) outfile_name = climFileIO.get_out_fn( ave_descr[0], prefix, ave_date, ave_t.average_types[ave_descr[0]]['fn'], region_name) if 'zonalavg' in ave_descr: l_collapse_dim = spec.collapse_dim else: l_collapse_dim = '' all_files_vars, new_file = climFileIO.define_ave_file( l_master, spec.serial, var_list, lvar_list, meta_list, hist_dict, spec.hist_type, ave_descr, prefix, outfile_name, spec.split, split_name, spec.out_directory, inter_comm, spec.ncformat, ave_t.average_types[ ave_descr[0]]['months_to_average'][0], key, spec.clobber, spec.year0, spec.year1, ave_date2, collapse_dim=l_collapse_dim) timer.stop("Create/Define Netcdf File") # Start loops to compute averages # create a list of years that are needed for this average years = [] if '__d' in ave_descr: if (ave_t.average_types[ ave_descr[0]]['depend_type'] == 'month' or '_d' in ave_descr[2]): years.append(int(ave_descr[1])) else: years = list( range(int(ave_descr[1]), int(ave_descr[2]) + 1)) depend = True else: if (len(ave_descr) == 2): years.append(int(ave_descr[1])) else: years = list( range(int(ave_descr[1]), int(ave_descr[2]) + 1)) depend = False # Get the first year. If part of a sig avg, this will be the sig first year, not year of indiv average fyr = years[0] if i + 1 in avg_dict.keys(): for a in avg_dict[i + 1]: if (ave_descr[0] + '_sig') in a: spl = a.split(':') fyr = int(spl[1]) file_dict = [] open_list = [] # Open all of the files that this rank will need for this average (for time slice files) if ((spec.hist_type == 'slice' or '__d' in ave_descr) and (spec.serial or not l_master) and len(lvar_list) > 0): file_dict = [] open_list = [] file_dict, open_list = climFileIO.open_all_files( hist_dict, ave_t.average_types[ave_descr[0]] ['months_to_average'], years, lvar_list[0], 'null', ave_descr[0], depend, fyr) # If concat of file instead of average, piece file together here. If not, enter averaging loop if (('mavg' in ave_descr or 'moc' in ave_descr or 'annall' in ave_descr or 'mons' in ave_descr or '_mean' in ave_descr[0]) and len(lvar_list) > 0): file_dict = [] open_list = [] if (spec.serial or not l_master): # Open files file_dict, open_list = climFileIO.open_all_files( hist_dict, ave_t.average_types[ ave_descr[0]]['months_to_average'], years, lvar_list[0], 'null', ave_descr[0], depend, fyr) # Loop through variables and compute the averages for orig_var in lvar_list: # Some variable names were suffixed with a meta label indicaticating that the variable exists in all files, # but there isn't a didicated ts file to open. Pick the first variable off the list and get values from there if ('__meta' in orig_var): var = key else: var = orig_var # Open all of the files that this rank will need for this average (for time series files) if ((spec.hist_type == 'series' and '__d' not in ave_descr) and (spec.serial or not l_master)): if ('mavg' not in ave_descr or 'moc' not in ave_descr or 'annall' not in ave_descr or 'mons' not in ave_descr or '_mean' not in ave_descr[0]): file_dict = [] open_list = [] file_dict, open_list = climFileIO.open_all_files( hist_dict, ave_t.average_types[ ave_descr[0]]['months_to_average'], years, var, split_name, ave_descr[0], depend, fyr) # We now have open files to pull values from. Now reset var name if ('__meta' in orig_var): parts = orig_var.split('__') var = parts[0] # If concat, all of the procs will participate in this call if ('mavg' in ave_descr or 'moc' in ave_descr or 'mocm' in ave_descr or 'hor.meanConcat' in ave_descr or 'annall' in ave_descr or 'mons' in ave_descr or '_mean' in ave_descr[0] or 'zonalavg' in ave_descr): if 'zonalavg' in ave_descr: l_collapse_dim = spec.collapse_dim else: l_collapse_dim = '' # Concat var_avg_results = climAverager.time_concat( var, years, hist_dict, ave_t.average_types[ave_descr[0]], file_dict, ave_descr[0], inter_comm, all_files_vars, spec.serial, timer, collapse_dim=spec.collapse_dim) # Else (not concat), each slave will compute averages and each master will collect and write else: if spec.serial or not l_master: # mean_diff_rsm file if ('hor.meanyr' in ave_descr and '__meta' not in orig_var): obs_file = spec.obs_dir + "/" + spec.obs_file reg_obs_file = spec.obs_dir + "/" + region_name + spec.reg_obs_file_suffix # The mean diff rsm function will send the variables once they are created var_avg_results, var_DIFF_results, var_RMS_results = climAverager.mean_diff_rms( var, region_name, region_num, spec.region_nc_var, spec.region_wgt_var, years, hist_dict, ave_t.average_types[ave_descr[0]], file_dict, obs_file, reg_obs_file, inter_comm, spec.serial, VNAME_TAG, AVE_TAG) else: if ('__metaChar' in orig_var): # Handle special meta var_avg_results = climAverager.get_metaCharValue( var, years, hist_dict, ave_t.average_types[ ave_descr[0]], file_dict, timer) else: # Average if (spec.weighted == True and 'weights' in ave_t.average_types[ ave_descr[0]]): var_avg_results = climAverager.weighted_avg_var( var, years, hist_dict, ave_t.average_types[ ave_descr[0]], file_dict, ave_descr[0], timer, depend, fyr) else: var_avg_results = climAverager.avg_var( var, years, hist_dict, ave_t.average_types[ ave_descr[0]], file_dict, ave_descr[0], timer, depend, fyr) # Close all open files (for time series files) if ((spec.hist_type == 'series' and '__d' not in ave_descr) and (spec.serial or not l_master)): climFileIO.close_all_files( open_list) # Pass the average results to master rank for writing var_shape = var_avg_results.shape var_dtype = var_avg_results.dtype var_type = type(var_avg_results) md_message = { 'name': var, 'shape': var_shape, 'dtype': var_dtype, 'average': var_avg_results, 'type': var_type } if not spec.serial: timer.start("Send Average Time") #inter_comm.collect(data=md_message, tag=AVE_TAG) inter_comm.collect(data=var, tag=VNAME_TAG) inter_comm.collect( data=var_avg_results, tag=AVE_TAG) timer.stop("Send Average Time") if spec.serial or l_master: # If ave_descr is hor.meanyr, there will be three variables to write for each variable. # Other wise, there will only be 1 if ('hor.meanyr' in ave_descr and '__meta' not in orig_var): var_cnt = 3 else: var_cnt = 1 for r in range(0, var_cnt): if not spec.serial: timer.start("Recv Average Time") #r_rank,results = inter_comm.collect(tag=AVE_TAG) #r_var_avg_results = results['average'] r_rank, var_name = inter_comm.collect( tag=VNAME_TAG) r_rank, r_var_avg_results = inter_comm.collect( tag=AVE_TAG) #var_name = results['name'] timer.start("Recv Average Time") else: var_name = var r_var_avg_results = var_avg_results timer.start("Write Netcdf Averages") climFileIO.write_averages( all_files_vars, r_var_avg_results, var_name) if ('hor.meanyr' in ave_descr and spec.serial ) and '__meta' not in orig_var: climFileIO.write_averages( all_files_vars, var_DIFF_results, var_name + '_DIFF') climFileIO.write_averages( all_files_vars, var_RMS_results, var_name + '_RMS') timer.stop("Write Netcdf Averages") # Close all open files (for time slice files) if (('mavg' in ave_descr or 'moc__d' == ave_descr[0] or 'annall' in ave_descr or 'mons' in ave_descr or '_mean' in ave_descr[0]) and len(lvar_list) > 0): if (spec.serial or not l_master): climFileIO.close_all_files(open_list) elif ((spec.hist_type == 'slice' or '__d' in ave_descr) and (spec.serial or not l_master) and len(lvar_list) > 0): climFileIO.close_all_files(open_list) # Sync the local communicator before closing the averaged netcdf file and moving to the next average inter_comm.sync() # Close the newly created average file if spec.serial or l_master: new_file.close() # If needed, stitch spatially split files together. if spec.serial or l_master: if (len(spec.split_files.split(",")) > 1): fn1 = spec.out_directory + '/nh_' + outfile_name fn2 = spec.out_directory + '/sh_' + outfile_name out_fn = spec.out_directory + '/' + outfile_name dim_info = spec.split_orig_size.split(",") dim1 = dim_info[0].split("=") dim2 = dim_info[1].split("=") regionOpts.combine_regions(fn1, fn2, out_fn, dim1[0], int(dim1[1]), dim2[0], int(dim2[1]), "nj", spec.clobber) if not spec.serial: # Free the inter-communicators #intercomm.Free() # Sync all mpi tasks / All averages should have been computed at this point spec.main_comm.sync() #============================================================================== # # Collect and print timing information # #============================================================================== timer.stop("Total Time") my_times = spec.main_comm.allreduce(timer.get_all_times(), 'max') if g_master: print("==============================================") print "COMPLETED SUCCESSFULLY" print my_times print("==============================================")
def run_diagnostics(self, env, scomm): """ call the necessary plotting routines to generate diagnostics plots """ super(modelVsModel, self).run_diagnostics(env, scomm) scomm.sync() # setup some global variables requested_plot_sets = list() local_requested_plots = list() local_html_list = list() # all the plot module XML vars start with 'set_' for key, value in env.iteritems(): if ("set_" in key and value == 'True'): requested_plot_sets.append(key) scomm.sync() if scomm.is_manager(): print('DEBUG model_vs_model requested_plot_sets = {0}'.format( requested_plot_sets)) # partition requested plots to all tasks # first, create plotting classes and get the number of plots each will created requested_plots = {} set_sizes = {} #plots_weights = [] for plot_set in requested_plot_sets: requested_plots.update( lnd_diags_plot_factory.LandDiagnosticPlotFactory( plot_set, env)) #for plot_id,plot_class in requested_plots.iteritems(): # if hasattr(plot_class, 'weight'): # factor = plot_class.weight # else: # factor = 1 # plots_weights.append((plot_id,len(plot_class.expectedPlots)*factor)) # partition based on the number of plots each set will create #local_plot_list = scomm.partition(plots_weights, func=partition.WeightBalanced(), involved=True) if scomm.is_manager(): print('DEBUG model_vs_model requested_plots.keys = {0}'.format( requested_plots.keys())) local_plot_list = scomm.partition(requested_plots.keys(), func=partition.EqualStride(), involved=True) scomm.sync() timer = timekeeper.TimeKeeper() # loop over local plot lists - set env and then run plotting script timer.start(str(scomm.get_rank()) + "ncl total time on task") for plot_set in local_plot_list: timer.start(str(scomm.get_rank()) + plot_set) plot_class = requested_plots[plot_set] # set all env variables (global and particular to this plot call print( 'model vs. model - Checking prerequisite for {0} on rank {1}'. format(plot_class.__class__.__name__, scomm.get_rank())) plot_class.check_prerequisites(env) # Stringify the env dictionary for name, value in plot_class.plot_env.iteritems(): plot_class.plot_env[name] = str(value) # call script to create plots for script in plot_class.ncl_scripts: print( 'model vs. model - Generating plots for {0} on rank {1} with script {2}' .format(plot_class.__class__.__name__, scomm.get_rank(), script)) diagUtilsLib.generate_ncl_plots(plot_class.plot_env, script) timer.stop(str(scomm.get_rank()) + plot_set) timer.stop(str(scomm.get_rank()) + "ncl total time on task") scomm.sync() print(timer.get_all_times()) #w = 0 #for p in plots_weights: # if p[0] in local_plot_list: # w = w + p[1] #print(str(scomm.get_rank())+' weight:'+str(w)) # set html files if scomm.is_manager(): # Create web dirs and move images/tables to that web dir for n in ('1', '2', '3', '4', '5', '6', '7', '8', '9'): web_dir = env['WKDIR'] set_dir = web_dir + '/set' + n # Create the plot set web directory if not os.path.exists(set_dir): os.makedirs(set_dir) # Copy plots into the correct web dir glob_string = web_dir + '/set' + n + '_*' imgs = glob.glob(glob_string) if len(imgs) > 0: for img in imgs: new_fn = set_dir + '/' + os.path.basename(img) os.rename(img, new_fn) # Copy the set1Diff and set1Anom plots to set_1 web dir if n == '1': glob_string = web_dir + '/set1Diff' + '_*' imgs = glob.glob(glob_string) if len(imgs) > 0: for img in imgs: new_fn = set_dir + '/' + os.path.basename(img) os.rename(img, new_fn) glob_string = web_dir + '/set1Anom' + '_*' imgs = glob.glob(glob_string) if len(imgs) > 0: for img in imgs: new_fn = set_dir + '/' + os.path.basename(img) os.rename(img, new_fn) env['WEB_DIR'] = web_dir shutil.copy2( env['POSTPROCESS_PATH'] + '/lnd_diag/inputFiles/' + env['VAR_MASTER'], web_dir + '/variable_master.ncl') if n == '9': web_script = env[ 'POSTPROCESS_PATH'] + '/lnd_diag/shared/lnd_statTable.pl' rc2, err_msg = cesmEnvLib.checkFile(web_script, 'read') if rc2: try: subprocess.check_call(web_script) except subprocess.CalledProcessError as e: print('WARNING: {0} error executing command:'.format( web_script)) print(' {0}'.format(e.cmd)) print(' rc = {0}'.format(e.returncode)) else: print('{0}... {1} file not found'.format( err_msg, web_script)) # copy the set9_statTable.html to the set9 subdir set9_statTable = web_dir + '/set9_statTable.html' rc2, err_msg = cesmEnvLib.checkFile(set9_statTable, 'read') if rc2: new_fn = web_dir + '/set9/' + os.path.basename( set9_statTable) try: os.rename(set9_statTable, new_fn) except os.OSError as e: print('WARNING: rename error for file {0}'.format( set9_statTable)) print(' rc = {0}'.format(e.returncode)) else: print('{0}... {1} file not found'.format( err_msg, set9_statTable)) web_script_1 = env[ 'POSTPROCESS_PATH'] + '/lnd_diag/shared/lnd_create_webpage.pl' web_script_2 = env[ 'POSTPROCESS_PATH'] + '/lnd_diag/shared/lnd_lookupTable.pl' print('Creating Web Pages') # set the shell environment cesmEnvLib.setXmlEnv(env) # lnd_create_webpage.pl call rc1, err_msg = cesmEnvLib.checkFile(web_script_1, 'read') if rc1: try: subprocess.check_call(web_script_1) except subprocess.CalledProcessError as e: print('WARNING: {0} error executing command:'.format( web_script_1)) print(' {0}'.format(e.cmd)) print(' rc = {0}'.format(e.returncode)) else: print('{0}... {1} file not found'.format( err_msg, web_script_1)) # lnd_lookupTable.pl call rc2, err_msg = cesmEnvLib.checkFile(web_script_2, 'read') if rc2: try: subprocess.check_call(web_script_2) except subprocess.CalledProcessError as e: print('WARNING: {0} error executing command:'.format( web_script_2)) print(' {0}'.format(e.cmd)) print(' rc = {0}'.format(e.returncode)) else: print('{0}... {1} file not found'.format( err_msg, web_script_2)) # move all the plots to the diag_path with the years appended to the path endYr1 = (int(env['clim_first_yr_1']) + int(env['clim_num_yrs_1'])) - 1 endYr2 = (int(env['clim_first_yr_2']) + int(env['clim_num_yrs_2'])) - 1 diag_path = '{0}/diag/{1}.{2}_{3}-{4}.{5}_{6}'.format( env['OUTPUT_ROOT_PATH'], env['caseid_1'], env['clim_first_yr_1'], str(endYr1), env['caseid_2'], env['clim_first_yr_2'], str(endYr2)) move_files = True try: os.makedirs(diag_path) except OSError as exception: if exception.errno != errno.EEXIST: err_msg = 'ERROR: {0} problem accessing directory {1}'.format( self.__class__.__name__, diag_path) raise OSError(err_msg) move_files = False elif env['CLEANUP_FILES'].lower() in ['t', 'true']: # delete all the files in the diag_path directory for root, dirs, files in os.walk('diag_path'): for f in files: os.unlink(os.path.join(root, f)) for d in dirs: shutil.rmtree(os.path.join(root, d)) elif env['CLEANUP_FILES'].lower() in ['f', 'false']: print( 'WARNING: {0} exists and is not empty and LNDDIAG_CLEANUP_FILES = False. Leaving new diagnostics files in {1}' .format(diag_path, web_dir)) diag_path = web_dir move_files = False # move the files to the new diag_path if move_files: try: print('DEBUG: model_vs_model renaming web files') os.rename(web_dir, diag_path) except OSError as e: print('WARNING: Error renaming %s to %s: %s' % (web_dir, diag_path, e)) diag_path = web_dir print('DEBUG: model vs. model web_dir = {0}'.format(web_dir)) print('DEBUG: model vs. model diag_path = {0}'.format(diag_path)) # setup the unique LNDDIAG_WEBDIR_MODEL_VS_MODEL output file env_file = '{0}/env_diags_lnd.xml'.format(env['PP_CASE_PATH']) key = 'LNDDIAG_WEBDIR_{0}'.format(self._name) value = diag_path ##web_file = '{0}/web_dirs/{1}.{2}-{3}'.format(env['PP_CASE_PATH'], key, scomm.get_size(), scomm.get_rank() ) web_file = '{0}/web_dirs/{1}.{2}'.format( env['PP_CASE_PATH'], key, datetime.datetime.now().strftime('%Y-%m-%d_%H%M%S')) try: diagUtilsLib.write_web_file(web_file, 'lnd', key, value) except: print( 'WARNING lnd model_vs_model unable to write {0}={1} to {2}' .format(key, value, web_file)) print( '*******************************************************************************' ) print( 'Successfully completed generating land diagnostics model vs. model plots' ) print( '*******************************************************************************' )
def main(options, main_comm, debugMsg): """setup the environment for running the diagnostics in parallel. Calls 2 different diagnostics generation types: model vs. observation model vs. model Arguments: options (object) - command line options main_comm (object) - MPI simple communicator object debugMsg (object) - vprinter object for printing debugging messages The env_diags_atm.xml configuration file defines the way the diagnostics are generated. See (website URL here...) for a complete desciption of the env_diags_atm XML options. """ # initialize the environment dictionary envDict = dict() # CASEROOT is given on the command line as required option --caseroot if main_comm.is_manager(): caseroot = options.caseroot[0] debugMsg('caseroot = {0}'.format(caseroot), header=True) debugMsg('calling initialize_main', header=True) envDict = initialize_main(envDict, caseroot, debugMsg, options.standalone) debugMsg('calling check_ncl_nco', header=True) diagUtilsLib.check_ncl_nco(envDict) # broadcast envDict to all tasks envDict = main_comm.partition(data=envDict, func=partition.Duplicate(), involved=True) sys.path.append(envDict['PATH']) main_comm.sync() # check to see if the climos need to be regridded into a lat/lon grid if (envDict['test_regrid'] == 'True' or envDict['cntl_regrid'] == 'True'): regrid_climos(envDict, main_comm) main_comm.sync() # get list of diagnostics types to be created diag_list = list() diag_list = setup_diags(envDict) if main_comm.is_manager(): print('User requested diagnostics:') for diag in diag_list: print(' {0}'.format(diag)) main_comm.sync() # broadcast the diag_list to all tasks num_of_diags = len(diag_list) num_of_diags = main_comm.partition(num_of_diags, func=partition.Duplicate(), involved=True) diag_list = main_comm.partition(data=diag_list, func=partition.Duplicate(), involved=True) main_comm.sync() # initialize some variables for distributing diagnostics across the communicators diags_send = diag_list gmaster = main_comm.is_manager() gsize = main_comm.get_size() grank = main_comm.get_rank() local_diag_list = list() # divide the main communicator into sub_communicators to be passed to each diag class # split mpi comm world if the size of the communicator > 1 and the num_of_diags > 1 if gsize > 1 and num_of_diags > 1: temp_color = (grank % num_of_diags) if (temp_color == num_of_diags): temp_color = temp_color - 1 groups = list() for g in range(0, num_of_diags): groups.append(g) debugMsg( 'global_rank {0}, temp_color {1}, #of groups(diag types) {2}, groups {3}, diag_list {4}' .format(grank, temp_color, num_of_diags, groups, diag_list)) group = groups[temp_color] inter_comm, multi_comm = main_comm.divide(group) color = inter_comm.get_color() lsize = inter_comm.get_size() lrank = inter_comm.get_rank() lmaster = inter_comm.is_manager() debugMsg('color {0}, lsize {1}, lrank {2}, lmaster {3}'.format( color, lsize, lrank, lmaster)) # partition the diag_list between communicators DIAG_LIST_TAG = 10 if lmaster: local_diag_list = multi_comm.partition( diag_list, func=partition.EqualStride(), involved=True) for b in range(1, lsize): diags_send = inter_comm.ration(data=local_diag_list, tag=DIAG_LIST_TAG) else: local_diag_list = inter_comm.ration(tag=DIAG_LIST_TAG) debugMsg('local_diag_list {0}', format(local_diag_list)) else: inter_comm = main_comm lmaster = main_comm.is_manager() lsize = main_comm.get_size() lrank = main_comm.get_rank() local_diag_list = diag_list inter_comm.sync() main_comm.sync() debugMsg('lsize = {0}, lrank = {1}'.format(lsize, lrank)) inter_comm.sync() # loop through the local_diag_list list for requested_diag in local_diag_list: try: diag = atm_diags_factory.atmosphereDiagnosticsFactory( requested_diag, envDict) # check the prerequisites for the diagnostics types debugMsg('Checking prerequisites for {0}'.format( diag.__class__.__name__), header=True) #if lmaster: envDict = diag.check_prerequisites(envDict, inter_comm) inter_comm.sync() ## broadcast the envDict #envDict = inter_comm.partition(data=envDict, func=partition.Duplicate(), involved=True) # set the shell env using the values set in the XML and read into the envDict across all tasks #cesmEnvLib.setXmlEnv(envDict) debugMsg('inter_comm = {0}'.format(inter_comm)) diag.run_diagnostics(envDict, inter_comm) except atm_diags_bc.RecoverableError as e: # catch all recoverable errors, print a message and continue. print(e) print("Skipped '{0}' and continuing!".format(request_diag)) except RuntimeError as e: # unrecoverable error, bail! print(e) return 1 main_comm.sync()
def run_diagnostics(self, env, scomm): """ call the necessary plotting routines to generate diagnostics plots """ super(modelVsObsEcosys, self).run_diagnostics(env, scomm) scomm.sync() # setup some global variables requested_plots = list() local_requested_plots = list() local_html_list = list() # define the templatePath for all tasks templatePath = '{0}/diagnostics/diagnostics/ocn/Templates'.format( env['POSTPROCESS_PATH']) # all the plot module XML vars start with MVOECOSYS_PM_ need to strip that off for key, value in env.iteritems(): if (re.search("\AMVOECOSYS_PM_", key) and value.upper() in ['T', 'TRUE']): k = key[10:] requested_plots.append(k) scomm.sync() print('model vs. obs ecosys - after scomm.sync requested_plots = {0}'. format(requested_plots)) if scomm.is_manager(): print('model vs. obs ecosys - User requested plot modules:') for plot in requested_plots: print(' {0}'.format(plot)) print('model vs. obs ecosys - Creating plot html header') templateLoader = jinja2.FileSystemLoader(searchpath=templatePath) templateEnv = jinja2.Environment(loader=templateLoader) template_file = 'model_vs_obs_ecosys.tmpl' template = templateEnv.get_template(template_file) # get the current datatime string for the template now = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S') # test the template variables templateVars = { 'casename': env['CASE'], 'username': env['USER_NAME'], 'tagname': env['CESM_TAG'], 'start_year': env['YEAR0'], 'stop_year': env['YEAR1'], 'today': now } print('model vs. obs ecosys - Rendering plot html header') plot_html = template.render(templateVars) scomm.sync() print('model vs. obs ecosys - Partition requested plots') # partition requested plots to all tasks local_requested_plots = scomm.partition(requested_plots, func=partition.EqualStride(), involved=True) scomm.sync() for requested_plot in local_requested_plots: try: plot = ocn_diags_plot_factory.oceanDiagnosticPlotFactory( 'obs', requested_plot) print( 'model vs. obs ecosys - Checking prerequisite for {0} on rank {1}' .format(plot.__class__.__name__, scomm.get_rank())) plot.check_prerequisites(env) print( 'model vs. obs ecosys - Generating plots for {0} on rank {1}' .format(plot.__class__.__name__, scomm.get_rank())) plot.generate_plots(env) print( 'model vs. obs ecosys - Converting plots for {0} on rank {1}' .format(plot.__class__.__name__, scomm.get_rank())) plot.convert_plots(env['WORKDIR'], env['IMAGEFORMAT']) print( 'model vs. obs ecosys - Creating HTML for {0} on rank {1}'. format(plot.__class__.__name__, scomm.get_rank())) html = plot.get_html(env['WORKDIR'], templatePath, env['IMAGEFORMAT']) local_html_list.append(str(html)) #print('local_html_list = {0}'.format(local_html_list)) except RecoverableError as e: # catch all recoverable errors, print a message and continue. print(e) print("model vs. obs ecosys - Skipped '{0}' and continuing!". format(requested_plot)) except RuntimeError as e: # unrecoverable error, bail! print(e) return 1 scomm.sync() # define a tag for the MPI collection of all local_html_list variables html_msg_tag = 1 all_html = list() all_html = [local_html_list] if scomm.get_size() > 1: if scomm.is_manager(): all_html = [local_html_list] for n in range(1, scomm.get_size()): rank, temp_html = scomm.collect(tag=html_msg_tag) all_html.append(temp_html) #print('all_html = {0}'.format(all_html)) else: return_code = scomm.collect(data=local_html_list, tag=html_msg_tag) scomm.sync() if scomm.is_manager(): # merge the all_html list of lists into a single list all_html = list(itertools.chain.from_iterable(all_html)) for each_html in all_html: #print('each_html = {0}'.format(each_html)) plot_html += each_html print('model vs. obs ecosys - Adding footer html') with open('{0}/footer.tmpl'.format(templatePath), 'r') as tmpl: plot_html += tmpl.read() print('model vs. obs ecosys - Writing plot index.html') with open('{0}/index.html'.format(env['WORKDIR']), 'w') as index: index.write(plot_html) print( '*****************************************************************************************' ) print( 'Successfully completed generating ocean diagnostics model vs. observation ecosystem plots' ) print( '*****************************************************************************************' ) scomm.sync() # append the web_dir location to the env key = 'OCNDIAG_WEBDIR_{0}'.format(self._name) env[key] = env['WORKDIR'] return env
def testEqualStride(self): for inp in self.inputs: pfunc = partition.EqualStride() actual = pfunc(*inp) expected = inp[0][inp[1]::inp[2]] testing.assert_array_equal(actual, expected)