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)
Example #2
0
 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)
Example #3
0
    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
Example #4
0
    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()
Example #6
0
 def testOutOfBounds(self):
     self.assertRaises(
         IndexError, partition.EqualLength(), [1, 2, 3], 3, 3)
     self.assertRaises(
         IndexError, partition.EqualStride(), [1, 2, 3], 7, 3)
Example #7
0
 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)
Example #8
0
    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("==============================================")
Example #9
0
    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(
                '*******************************************************************************'
            )
Example #10
0
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
Example #12
0
 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)