def _setup_remappers(self, fileName): # {{{ """ Set up the remappers for remapping from observations to the comparison grids. Parameters ---------- fileName : str The name of the observation file used to determine the source grid """ # Authors # ------- # Xylar Asay-Davis config = self.config sectionName = '{}Observations'.format(self.componentName) obsDescriptor = self.get_observation_descriptor(fileName) outFilePrefix = self.outFilePrefix self.remappers = {} for comparisonGridName in self.comparisonGridNames: comparisonDescriptor = get_comparison_descriptor( config, comparisonGridName=comparisonGridName) self.remappers[comparisonGridName] = get_remapper( config=config, sourceDescriptor=obsDescriptor, comparisonDescriptor=comparisonDescriptor, mappingFilePrefix='map_obs_{}'.format(outFilePrefix), method=config.get(sectionName, 'interpolationMethod'), logger=self.logger)
def compute_vel_mag(prefix, inGridName, inDir): config = MpasAnalysisConfigParser() config.read('mpas_analysis/config.default') outDescriptor = get_comparison_descriptor(config, 'antarctic') outGridName = outDescriptor.meshName description = 'Monthly velocity magnitude climatologies from ' \ '2005-2010 average of the Southern Ocean State ' \ 'Estimate (SOSE)' botDescription = 'Monthly velocity magnitude climatologies at sea ' \ 'floor from 2005-2010 average from SOSE' for gridName in [outGridName]: outFileName = '{}_vel_mag_{}.nc'.format(prefix, gridName) uFileName = '{}_zonal_vel_{}.nc'.format(prefix, gridName) vFileName = '{}_merid_vel_{}.nc'.format(prefix, gridName) if not os.path.exists(outFileName): with xarray.open_dataset(uFileName) as dsU: with xarray.open_dataset(vFileName) as dsV: dsVelMag = dsU.drop(['zonalVel', 'botZonalVel']) dsVelMag['velMag'] = xarray.ufuncs.sqrt(dsU.zonalVel**2 + dsV.meridVel**2) dsVelMag.velMag.attrs['units'] = 'm s$^{-1}$' dsVelMag.velMag.attrs['description'] = description dsVelMag['botVelMag'] = xarray.ufuncs.sqrt( dsU.botZonalVel**2 + dsV.botMeridVel**2) dsVelMag.botVelMag.attrs['units'] = 'm s$^{-1}$' dsVelMag.botVelMag.attrs['description'] = botDescription write_netcdf(dsVelMag, outFileName)
def _setup_remappers(self): # {{{ """ Set up the remappers for remapping from the MPAS to the comparison grids. """ # Authors # ------- # Xylar Asay-Davis config = self.config # make reamppers mappingFilePrefix = 'map' self.remappers = {} for comparisonGridName in self.comparisonGridNames: comparisonDescriptor = get_comparison_descriptor( config, comparisonGridName) self.comparisonGridName = comparisonDescriptor.meshName mpasDescriptor = MpasMeshDescriptor(self.restartFileName, meshName=config.get( 'input', 'mpasMeshName')) self.mpasMeshName = mpasDescriptor.meshName self.remappers[comparisonGridName] = get_remapper( config=config, sourceDescriptor=mpasDescriptor, comparisonDescriptor=comparisonDescriptor, mappingFilePrefix=mappingFilePrefix, method=config.get('climatology', 'mpasInterpolationMethod'), logger=self.logger)
def compute_pot_density(prefix, inGridName, inDir): config = MpasAnalysisConfigParser() config.read('mpas_analysis/config.default') outDescriptor = get_comparison_descriptor(config, 'antarctic') outGridName = outDescriptor.meshName description = 'Monthly potential density climatologies from ' \ '2005-2010 average of the Southern Ocean State ' \ 'Estimate (SOSE)' botDescription = 'Monthly potential density climatologies at sea ' \ 'floor from 2005-2010 average from SOSE' for gridName in [inGridName, outGridName]: outFileName = '{}_pot_den_{}.nc'.format(prefix, gridName) TFileName = '{}_pot_temp_{}.nc'.format(prefix, gridName) SFileName = '{}_salinity_{}.nc'.format(prefix, gridName) if not os.path.exists(outFileName): with xarray.open_dataset(TFileName) as dsT: with xarray.open_dataset(SFileName) as dsS: dsPotDensity = dsT.drop(['theta', 'botTheta']) lat, lon, z = xarray.broadcast(dsS.lat, dsS.lon, dsS.z) pressure = gsw.p_from_z(z.values, lat.values) SA = gsw.SA_from_SP(dsS.salinity.values, pressure, lon.values, lat.values) CT = gsw.CT_from_pt(SA, dsT.theta.values) dsPotDensity['potentialDensity'] = (dsS.salinity.dims, gsw.rho(SA, CT, 0.)) dsPotDensity.potentialDensity.attrs['units'] = \ 'kg m$^{-3}$' dsPotDensity.potentialDensity.attrs['description'] = \ description lat, lon, z = xarray.broadcast(dsS.lat, dsS.lon, dsS.zBot) pressure = gsw.p_from_z(z.values, lat.values) SA = gsw.SA_from_SP(dsS.botSalinity.values, pressure, lon.values, lat.values) CT = gsw.CT_from_pt(SA, dsT.botTheta.values) dsPotDensity['botPotentialDensity'] = \ (dsS.botSalinity.dims, gsw.rho(SA, CT, 0.)) dsPotDensity.botPotentialDensity.attrs['units'] = \ 'kg m$^{-3}$' dsPotDensity.botPotentialDensity.attrs['description'] = \ botDescription write_netcdf(dsPotDensity, outFileName)
def remap_v(prefix, inGridName, inGridFileName, inDir, inVPrefix): cacheVFileName = '{}_merid_vel_{}.nc'.format(prefix, inGridName) config = MpasAnalysisConfigParser() config.read('mpas_analysis/config.default') matGrid = loadmat(inGridFileName) # lat/lon is a tensor grid so we can use 1-D arrays lon = matGrid['XC'][:, 0] lat = matGrid['YG'][0, :] z = matGrid['RC'][:, 0] cellFraction = matGrid['hFacS'] botIndices = get_bottom_indices(cellFraction) with sose_v_to_nc('{}/{}'.format(inDir, inVPrefix), cacheVFileName, lon, lat, z, cellFraction, botIndices) \ as dsV: inDescriptor = LatLonGridDescriptor() inDescriptor = LatLonGridDescriptor.read(cacheVFileName, latVarName='lat', lonVarName='lon') outDescriptor = get_comparison_descriptor(config, 'antarctic') outGridName = outDescriptor.meshName outVFileName = '{}_merid_vel_{}.nc'.format(prefix, outGridName) mappingFileName = '{}/map_V_{}_to_{}.nc'.format( inDir, inGridName, outGridName) remapper = Remapper(inDescriptor, outDescriptor, mappingFileName) remapper.build_mapping_file(method='bilinear') if not os.path.exists(outVFileName): print('Remapping meridional velocity...') with remapper.remap(dsV, renormalizationThreshold=0.01) \ as remappedV: print('Done.') remappedV.attrs['history'] = ' '.join(sys.argv) write_netcdf(remappedV, outVFileName)
def remap(inDir, outDir): inGridName = 'SouthernOcean_0.25x0.125degree' inFileName = '{}/Schmidtko_et_al_2014_bottom_PT_S_PD_{}.nc'.format( inDir, inGridName) config = MpasAnalysisConfigParser() config.read('mpas_analysis/config.default') inDescriptor = LatLonGridDescriptor() inDescriptor = LatLonGridDescriptor.read(inFileName, latVarName='lat', lonVarName='lon') outDescriptor = get_comparison_descriptor(config, 'antarctic') outGridName = outDescriptor.meshName outFileName = '{}/Schmidtko_et_al_2014_bottom_PT_S_PD_{}.nc'.format( outDir, outGridName) mappingFileName = '{}/map_{}_to_{}.nc'.format(inDir, inGridName, outGridName) remapper = Remapper(inDescriptor, outDescriptor, mappingFileName) remapper.build_mapping_file(method='bilinear') if not os.path.exists(outFileName): print('Remapping...') with xarray.open_dataset(inFileName) as dsIn: with remapper.remap(dsIn, renormalizationThreshold=0.01) \ as remappedMLD: print('Done.') remappedMLD.attrs['history'] = ' '.join(sys.argv) write_netcdf(remappedMLD, outFileName)
def remap_pt_s(prefix, inGridName, inGridFileName, inDir, inTPrefix, inSPrefix, inGammaNPrefix): cacheTFileName = '{}_pot_temp_{}.nc'.format(prefix, inGridName) cacheSFileName = '{}_salinity_{}.nc'.format(prefix, inGridName) cacheGammaNFileName = '{}_neut_den_{}.nc'.format(prefix, inGridName) config = MpasAnalysisConfigParser() config.read('mpas_analysis/config.default') matGrid = loadmat(inGridFileName) # lat/lon is a tensor grid so we can use 1-D arrays lon = matGrid['XC'][:, 0] lat = matGrid['YC'][0, :] z = matGrid['RC'][:, 0] cellFraction = matGrid['hFacC'] botIndices = get_bottom_indices(cellFraction) with sose_pt_to_nc('{}/{}'.format(inDir, inTPrefix), cacheTFileName, lon, lat, z, cellFraction, botIndices) \ as dsT: inDescriptor = LatLonGridDescriptor() inDescriptor = LatLonGridDescriptor.read(cacheTFileName, latVarName='lat', lonVarName='lon') outDescriptor = get_comparison_descriptor(config, 'antarctic') outGridName = outDescriptor.meshName outTFileName = '{}_pot_temp_{}.nc'.format(prefix, outGridName) outSFileName = '{}_salinity_{}.nc'.format(prefix, outGridName) outGammaNFileName = '{}_neut_den_{}.nc'.format(prefix, outGridName) mappingFileName = '{}/map_C_{}_to_{}.nc'.format( inDir, inGridName, outGridName) remapper = Remapper(inDescriptor, outDescriptor, mappingFileName) remapper.build_mapping_file(method='bilinear') if not os.path.exists(outTFileName): dsT.reset_coords(names='zBot', inplace=True) print('Remapping potential temperature...') with remapper.remap(dsT, renormalizationThreshold=0.01) \ as remappedT: print('Done.') remappedT.attrs['history'] = ' '.join(sys.argv) remappedT.set_coords(names='zBot', inplace=True) write_netcdf(remappedT, outTFileName) with sose_s_to_nc('{}/{}'.format(inDir, inSPrefix), cacheSFileName, lon, lat, z, cellFraction, botIndices) \ as dsS: if not os.path.exists(outSFileName): dsS.reset_coords(names='zBot', inplace=True) print('Remapping salinity...') with remapper.remap(dsS, renormalizationThreshold=0.01) \ as remappedS: print('Done.') remappedS.attrs['history'] = ' '.join(sys.argv) remappedS.set_coords(names='zBot', inplace=True) write_netcdf(remappedS, outSFileName) with sose_gammaN_to_nc('{}/{}'.format(inDir, inGammaNPrefix), cacheGammaNFileName, lon, lat, z, cellFraction, botIndices) \ as dsGammaN: if not os.path.exists(outGammaNFileName): dsGammaN.reset_coords(names='zBot', inplace=True) print('Remapping neutral density...') with remapper.remap(dsGammaN, renormalizationThreshold=0.01) \ as remappedGammaN: print('Done.') remappedGammaN.attrs['history'] = ' '.join(sys.argv) remappedGammaN.set_coords(names='zBot', inplace=True) write_netcdf(remappedGammaN, outGammaNFileName)
def __init__(self, mpasClimatologyTask, parentTask, climatologyName, variableList, seasons, comparisonGridNames=None, iselValues=None, subtaskName='remapMpasClimatology', useNcremap=None): # {{{ ''' Construct the analysis task and adds it as a subtask of the ``parentTask``. Parameters ---------- mpasClimatologyTask : ``MpasClimatologyTask`` The task that produced the climatology to be remapped parentTask : ``AnalysisTask`` The parent task, used to get the ``taskName``, ``config`` and ``componentName`` climatologyName : str A name that describes the climatology (e.g. a short version of the important field(s) in the climatology) used to name the subdirectories for each stage of the climatology variableList : list of str A list of variable names in ``timeSeriesStatsMonthly`` to be included in the climatologies seasons : list of str A list of seasons (keys in ``shared.constants.monthDictionary``) to be computed or ['none'] (not ``None``) if only monthly climatologies are needed. comparisonGridNames : list of {'latlon', 'antarctic'}, optional The name(s) of the comparison grid to use for remapping. If none is supplied, `add_comparison_descriptor()` must be called to add one or more comparison grids. iselValues : dict, optional A dictionary of dimensions and indices (or ``None``) used to extract a slice of the MPAS field(s). subtaskName : str, optional The name of the subtask useNcremap : bool, optional Whether to use ncremap to do the remapping (the other option being an internal python code that handles more grid types and extra dimensions). This defaults to the config option ``useNcremap`` if it is not explicitly given. If a comparison grid other than ``latlon`` is given, ncremap is not supported so this flag is set to ``False``. ''' # Authors # ------- # Xylar Asay-Davis tags = ['climatology'] # call the constructor from the base class (AnalysisTask) super(RemapMpasClimatologySubtask, self).__init__( config=mpasClimatologyTask.config, taskName=parentTask.taskName, subtaskName=subtaskName, componentName=parentTask.componentName, tags=tags) self.variableList = variableList self.seasons = seasons self.comparisonDescriptors = {} if comparisonGridNames is not None: for comparisonGridName in comparisonGridNames: comparisonDescriptor = get_comparison_descriptor( self.config, comparisonGridName) self.comparisonDescriptors[comparisonGridName] = \ comparisonDescriptor self.iselValues = iselValues self.climatologyName = climatologyName self.mpasClimatologyTask = mpasClimatologyTask self.run_after(mpasClimatologyTask) parentTask.add_subtask(self) # this is a stopgap until MPAS implements the _FillValue attribute # correctly self._fillValue = -9.99999979021476795361e+33 if useNcremap is None: self.useNcremap = self.config.getboolean('climatology', 'useNcremap') else: self.useNcremap = useNcremap
def _setup_file_names(self): # {{{ """ Create a dictionary of file names and directories for this climatology """ # Authors # ------- # Xylar Asay-Davis config = self.config climatologyBaseDirectory = build_config_full_path( config, 'output', 'mpasClimatologySubdirectory') mpasMeshName = config.get('input', 'mpasMeshName') comparisonFullMeshNames = {} for comparisonGridName in self.comparisonGridNames: comparisonDescriptor = get_comparison_descriptor( config, comparisonGridName) comparisonFullMeshNames[comparisonGridName] = \ comparisonDescriptor.meshName keys = [] for season in self.seasons: stage = 'masked' keys.append((season, stage)) stage = 'remapped' for comparisonGridName in self.comparisonGridNames: keys.append((season, stage, comparisonGridName)) self._outputDirs = {} self._outputFiles = {} for key in keys: season = key[0] stage = key[1] if stage == 'remapped': comparisonGridName = key[2] stageDirectory = '{}/{}'.format(climatologyBaseDirectory, stage) if stage == 'masked': directory = '{}/{}_{}'.format(stageDirectory, self.climatologyName, mpasMeshName) elif stage == 'remapped': directory = '{}/{}_{}_to_{}'.format( stageDirectory, self.climatologyName, mpasMeshName, comparisonFullMeshNames[comparisonGridName]) make_directories(directory) monthValues = sorted(constants.monthDictionary[season]) startMonth = monthValues[0] endMonth = monthValues[-1] suffix = '{:04d}{:02d}_{:04d}{:02d}_climo'.format( self.mpasClimatologyTask.startYear, startMonth, self.mpasClimatologyTask.endYear, endMonth) if season in constants.abrevMonthNames: season = '{:02d}'.format(monthValues[0]) fileName = '{}/{}_{}_{}.nc'.format( directory, self.mpasClimatologyTask.ncclimoModel, season, suffix) self._outputDirs[key] = directory self._outputFiles[key] = fileName
def get_remapped_mpas_climatology_file_name(config, season, componentName, climatologyName, comparisonGridName, op='avg'): # {{{ """ Get the file name for a masked MPAS climatology Parameters ---------- config : ``MpasAnalysisConfigParser`` Configuration options season : str One of the seasons in ``constants.monthDictionary`` componentName : {'ocean', 'seaIce'} The MPAS component for which the climatology is being computed climatologyName : str The name of the climatology (typically the name of a field to mask and later remap) comparisonGridName : str The name of the comparison grid to use for remapping. If it is one of the default comparison grid names ``{'latlon', 'antarctic', 'arctic'}``, the full grid name is looked up via get_comparison_descriptor op : {'avg', 'min', 'max'} operator for monthly stats """ # Authors # ------- # Xylar Asay-Davis startYear = config.getint('climatology', 'startYear') endYear = config.getint('climatology', 'endYear') mpasMeshName = config.get('input', 'mpasMeshName') if componentName == 'ocean': ncclimoModel = 'mpaso' elif componentName == 'seaIce': ncclimoModel = 'mpascice' else: raise ValueError('component {} is not supported by ncclimo.\n' 'Check with Charlie Zender and Xylar Asay-Davis\n' 'about getting it added'.format(componentName)) climatologyOpDirectory = get_climatology_op_directory(config, op) if comparisonGridName in ['latlon', 'antarctic', 'arctic']: comparisonDescriptor = get_comparison_descriptor(config, comparisonGridName) comparisonFullMeshName = comparisonDescriptor.meshName else: comparisonFullMeshName = comparisonGridName stageDirectory = '{}/remapped'.format(climatologyOpDirectory) directory = '{}/{}_{}_to_{}'.format(stageDirectory, climatologyName, mpasMeshName, comparisonFullMeshName) make_directories(directory) monthValues = sorted(constants.monthDictionary[season]) startMonth = monthValues[0] endMonth = monthValues[-1] suffix = '{:04d}{:02d}_{:04d}{:02d}_climo'.format( startYear, startMonth, endYear, endMonth) if season in constants.abrevMonthNames: season = '{:02d}'.format(monthValues[0]) fileName = '{}/{}_{}_{}.nc'.format( directory, ncclimoModel, season, suffix) return fileName # }}}
def main(): parser = argparse.ArgumentParser( description=__doc__, formatter_class=argparse.RawTextHelpFormatter) parser.add_argument("-i", "--inDir", dest="inDir", required=True, help="Directory where intermediate files used in " "processing should be downloaded") parser.add_argument("-o", "--outDir", dest="outDir", required=True, help="Directory where final preprocessed observation " "are stored") args = parser.parse_args() date = '20190603' inGridName = 'SouthernOcean_0.167x0.167degree_{}'.format(date) inTPrefix = 'THETA_mnthlyBar.0000000100' inSPrefix = 'SALT_mnthlyBar.0000000100' inMLDPrefix = 'MLD_mnthlyBar.0000000100' inUPrefix = 'UVEL_mnthlyBar.0000000100' inVPrefix = 'VVEL_mnthlyBar.0000000100' inGammaNPrefix = 'GAMMA_mnthlyBar.0000000100' # size in km of the polar stereographic grid antarcticStereoWidth = 10000 config = MpasAnalysisConfigParser() config.read('mpas_analysis/config.default') config.set('climatology', 'comparisonAntarcticStereoWidth', '{}'.format(antarcticStereoWidth)) outDescriptor = get_comparison_descriptor(config, 'antarctic') outGridName = '{}_{}'.format(outDescriptor.meshName, date) inPrefixes = [ inTPrefix, inSPrefix, inMLDPrefix, inUPrefix, inVPrefix, inGammaNPrefix ] inGridFileName = '{}/grid.mat'.format(args.inDir) try: os.makedirs(args.inDir) except OSError: pass try: os.makedirs(args.outDir) except OSError: pass # dowload the desired file download_files(['GRID_README.txt'], urlBase='http://sose.ucsd.edu/DATA', outDir=args.inDir) urlBase = 'http://sose.ucsd.edu/DATA/SO6_V2' fileList = ['grid.mat'] for prefix in inPrefixes: fileList.append('{}.data.gz'.format(prefix)) fileList.append('{}.meta'.format(prefix)) download_files(fileList, urlBase, args.inDir) unzip_sose_data(inPrefixes, args.inDir) prefix = '{}/SOSE'.format(args.outDir) sose_volume_to_nc(prefix, inGridName, inGridFileName, args.inDir) prefix = '{}/SOSE_2005-2010_monthly'.format(args.outDir) remap_pt_s(prefix, inGridName, inGridFileName, args.inDir, inTPrefix, inSPrefix, inGammaNPrefix, outDescriptor, outGridName) remap_mld(prefix, inGridName, inGridFileName, args.inDir, inMLDPrefix, outDescriptor, outGridName) remap_u(prefix, inGridName, inGridFileName, args.inDir, inUPrefix, outDescriptor, outGridName) remap_v(prefix, inGridName, inGridFileName, args.inDir, inVPrefix, outDescriptor, outGridName) compute_vel_mag(prefix, inGridName, args.inDir, outGridName) compute_pot_density(prefix, inGridName, args.inDir, outGridName)
def _plot_polar(self, remappedModelClimatology, remappedRefClimatology): # {{{ """ plotting an Arctic or Antarctic data set """ season = self.season comparisonGridName = self.comparisonGridName config = self.config configSectionName = self.configSectionName mainRunName = config.get('runs', 'mainRunName') oceanMask = remappedModelClimatology['validMask'].values self.landMask = np.ma.masked_array(np.ones(oceanMask.shape), mask=np.logical_not( np.isnan(oceanMask))) modelOutput = nans_to_numpy_mask( remappedModelClimatology[self.mpasFieldName].values) if remappedRefClimatology is None: refOutput = None bias = None else: refOutput = nans_to_numpy_mask( remappedRefClimatology[self.refFieldName].values) bias = modelOutput - refOutput comparisonDescriptor = get_comparison_descriptor( config, comparisonGridName) x = comparisonDescriptor.xCorner y = comparisonDescriptor.yCorner filePrefix = self.filePrefix outFileName = '{}/{}.png'.format(self.plotsDirectory, filePrefix) title = '{} ({}, years {:04d}-{:04d})'.format(self.fieldNameInTitle, season, self.startYear, self.endYear) if self.comparisonGridName == 'antarctic': hemisphere = 'south' else: # arctic hemisphere = 'north' plot_polar_projection_comparison(config, x, y, self.landMask, modelOutput, refOutput, bias, fileout=outFileName, colorMapSectionName=configSectionName, title=title, modelTitle='{}'.format(mainRunName), refTitle=self.refTitleLabel, diffTitle=self.diffTitleLabel, cbarlabel=self.unitsLabel, hemisphere=hemisphere) upperGridName = comparisonGridName[0].upper() + comparisonGridName[1:] caption = '{} {}'.format(season, self.imageCaption) write_image_xml(config, filePrefix, componentName='Ocean', componentSubdirectory='ocean', galleryGroup='{} {}'.format(upperGridName, self.galleryGroup), groupSubtitle=self.groupSubtitle, groupLink='{}_{}'.format(comparisonGridName, self.groupLink), gallery=self.galleryName, thumbnailDescription=self.thumbnailDescription, imageDescription=caption, imageCaption=caption)