def test_open(self): """ Open file and check a field. """ f = umfile.UMFile(self.restart_dump) assert(len(f.fields) > 0) assert(f.fields[2].__str__() == 'U COMPNT OF WIND AFTER TIMESTEP')
def test_array_read(self): """ Read data using array syntax. """ f = umfile.UMFile(self.restart_dump) u_wnd = f.fields[2][:] assert(u_wnd.shape == (145, 192)) assert(np.mean(u_wnd) > -0.1 and np.mean(u_wnd) < 0)
def test_array_write(self): """ Write data using array syntax. """ f = umfile.UMFile(self.restart_dump) assert(np.sum(f.fields[2][:]) != 0) f.fields[2][:] = 0 assert(np.sum(f.fields[2][:]) == 0)
def test_close(self): """ Modify data and check that changes are written out. """ # First make a copy of the test file. restart_dump_copy = self.restart_dump + '.copy' shutil.copyfile(self.restart_dump, restart_dump_copy) f = umfile.UMFile(restart_dump_copy, 'r+') assert(np.sum(f.fields[2][:]) != 0) f.fields[2][:] = 0 assert(np.sum(f.fields[2][:]) == 0) f.close() f = umfile.UMFile(restart_dump_copy) assert(np.sum(f.fields[2][:]) == 0) os.remove(restart_dump_copy)
import umfile, stashvar verbose = False try: optlist, args = getopt.getopt(sys.argv[1:], 'v') for opt in optlist: if opt[0] == '-v': verbose = True except getopt.error: print "Usage: polar_anom [-v] ifile " sys.exit(2) if args: ifile = args[0] f = umfile.UMFile(ifile) if not f.fieldsfile: print "Not a UM fieldsfile" sys.exit(1) if f.fixhd[FH_HorizGrid] != 0: print "Error - not a global grid" sys.exit(1) for k in range(f.fixhd[FH_LookupSize2]): ilookup = f.ilookup[k] rlookup = f.rlookup[k] lbegin = ilookup[LBEGIN] # lbegin is offset from start if lbegin == -99: break
# Here check for this # Usage is check_land_overlap.py global_mask regional_mask # Note that this isn't going to work for rotated grids. # Martin Dix [email protected] import numpy as np import sys import umfile from um_fileheaders import * file1 = sys.argv[1] file2 = sys.argv[2] f = umfile.UMFile(file1) g = umfile.UMFile(file2) def getfld(f): # Expecting only a single field ilookup = f.ilookup[0] # Check field name and data type. # Expecting stash code 1 0 30 LAND MASK if ilookup[ITEM_CODE] != 30: print "Variable is not land mask, stashcode is", ilookup[ITEM_CODE] sys.exit(1) if ilookup[DATA_TYPE] != 3: print "Variable is not expected logical type, code is", ilookup[ DATA_TYPE]
#!/usr/bin/env python # Change the calendar in a UM ancillary file from Gregorian to 360 day # Assuming monthly data, change to appropriate middle of month dates. from um_fileheaders import * import umfile, sys print sys.argv[1] f = umfile.UMFile(sys.argv[1], 'r+') if f.fixhd[FH_CalendarType] == 1: f.fixhd[FH_CalendarType] = 2 print "Changing from Gregorian to 360 day" else: print "Already 360 day" sys.exit(0) for k in range(f.fixhd[FH_LookupSize2]): ilookup = f.ilookup[k] # print "Validity time", ilookup[LBYR], ilookup[LBMON], ilookup[LBDAT], \ # ilookup[LBHR], ilookup[LBMIN], ilookup[LBDAY] # print "Data time", ilookup[LBYRD], ilookup[LBMOND], ilookup[LBDATD], \ # ilookup[LBHRD], ilookup[LBMIND], ilookup[LBDAYD] # print "LBTIM", ilookup[LBTIM] ilookup[LBDAT] = ilookup[LBDATD] = 16 ilookup[LBHR] = ilookup[LBHRD] = 0 ilookup[LBMIN] = ilookup[LBMIND] = 0 ilookup[LBDAY] = ilookup[LBDAYD] = 16 + (ilookup[LBMON] - 1) * 30 if ilookup[LBTIM] % 10 == 1: # Reset units part of value from 1 to 2. ilookup[LBTIM] += 1 # Crucial for CDMS.
try: optlist, args = getopt.getopt(sys.argv[1:], 'v:') for opt in optlist: if opt[0] == '-v': oldindex, newindex = opt[1].split(",") oldindex = int(oldindex) newindex = int(newindex) vdict[oldindex] = newindex except getopt.error: print "Usage: change_stashcode.py -v oldindex,newindex file" print " Variables specified by STASH index = Section Number * 1000 + item number" print " May use multiple -v arguments" sys.exit(2) ifile = args[0] f = umfile.UMFile(ifile, 'r+') changed = False for k in range(f.fixhd[FH_LookupSize2]): ilookup = f.ilookup[k] lbegin = ilookup[LBEGIN] if lbegin == -99: break # Format is Section Number * 1000 + item number if ilookup[ITEM_CODE] in vdict: changed = True ilookup[ITEM_CODE] = vdict[ilookup[ITEM_CODE]] if not changed: print "Warning - no fields changed"
#!/usr/bin/env python # Change the initial and valid date of a UM dump file # Change both the file header and the date header of each record. # The latter may not be strictly necessary but it makes looking at file with # xconv less confusing. import getopt, sys import umfile from um_fileheaders import * ifile = sys.argv[1] f = umfile.UMFile(ifile, "r+") print "Initial Time", f.fixhd[FH_DTYear], f.fixhd[FH_DTMonth], f.fixhd[FH_DTDay], \ f.fixhd[FH_DTHour], f.fixhd[FH_DTMinute], f.fixhd[FH_DTSecond] print "Valid Time", f.fixhd[FH_VTYear], f.fixhd[FH_VTMonth], f.fixhd[FH_VTDay], \ f.fixhd[FH_VTHour], f.fixhd[FH_VTMinute], f.fixhd[FH_VTSecond] s = raw_input('Enter year month day\n') s = s.split() year = int(s[0]) month = int(s[1]) day = int(s[2]) print "Using", year, month, day f.fixhd[FH_DTYear] = f.fixhd[FH_VTYear] = year f.fixhd[FH_DTMonth] = f.fixhd[FH_VTMonth] = month
if opt[0] == '-i': ifile = opt[1] elif opt[0] == '-o': ofile = opt[1] elif opt[0] == '-v': # Allow comma separated lists for v in opt[1].split(","): vlist.append(int(v)) except getopt.error: print "Usage: um_copy_field.py -i ifile -o ofile -v var" print " Copy fields from ifile to ofile" print " Variables specified by STASH index = Section Number * 1000 + item number" print " May use a list specififed as -v var1,var2,..." sys.exit(2) f = umfile.UMFile(ifile, "r") g = umfile.UMFile(ofile, "r+") # Find the indices of the desired fields in each file. # This assumes that each is in normal stashcode order # (as all files produced by model are) findex = [] gindex = [] for k in range(f.fixhd[FH_LookupSize2]): ilookup = f.ilookup[k] lbegin = ilookup[LBEGIN] # lbegin is offset from start if lbegin == -99: break if ilookup[ITEM_CODE] in vlist: findex.append(k)
optlist, args = getopt.getopt(sys.argv[1:], 'i:o:m:') for opt in optlist: if opt[0] == '-i': ifile = opt[1] elif opt[0] == '-o': ofile = opt[1] elif opt[0] == '-m': maskfile = opt[1] except getopt.error: usage() if not ifile or not ofile or not maskfile: print "Error: filenames undefined" usage() m = umfile.UMFile(maskfile) f = umfile.UMFile(ifile) # Target grid properties nlon_target = m.inthead[IC_XLen] nlat_target = m.inthead[IC_YLen] # Create new axes for the output grid outgrid = cdms2.createUniformGrid(m.realhead[RC_FirstLat], nlat_target, m.realhead[RC_LatSpacing], m.realhead[RC_FirstLong], nlon_target, m.realhead[RC_LongSpacing]) g = umfile.UMFile(ofile, "w") g.copyheader(f)
parser.add_argument('-o', dest='ofile', help='Output UM dump') parser.add_argument('-f', dest='fracfile', help='New vegetation fraction (ancillary or netCDF)') parser.add_argument('-v', '--verbose', dest='verbose', action='store_true', default=False, help='verbose output') args = parser.parse_args() ntiles = 17 # Get old vegetation fraction from dump file f = umfile.UMFile(args.ifile) vlist = [] for k in range(f.fixhd[FH_LookupSize2]): ilookup = f.ilookup[k] lbegin = ilookup[LBEGIN] if lbegin == -99: break if ilookup[ITEM_CODE] == 216: a = f.readfld(k) vlist.append(a) assert len(vlist) == ntiles, 'Error - expected %d vegetation classes' % ntiles old_vegfrac = np.array(vlist) if args.fracfile.endswith(".nc"): # Read from a netCDF version of a dump file
# Usage is show_land_overlap.py global_mask regional_mask disallowed # Note that this isn't going to work for rotated grids. # Martin Dix [email protected] import numpy as np import sys import umfile from um_fileheaders import * file1 = sys.argv[1] file2 = sys.argv[2] file3 = sys.argv[3] f = umfile.UMFile(file1) g = umfile.UMFile(file2, 'r+') h = umfile.UMFile(file3, 'w') h.copyheader(g) h.ilookup[:] = -99 # Used as missing value h.rlookup[:] = np.fromstring(np.array([-99],h.int).tostring(),h.float) def getfld(f): # Expecting only a single field ilookup = f.ilookup[0] # Check field name and data type. # Expecting stash code 1 0 30 LAND MASK if ilookup[ITEM_CODE] != 30: print "Variable is not land mask, stashcode is", ilookup[ITEM_CODE]
#!/usr/bin/env python # List of valid data times in a file from um_fileheaders import * import umfile, sys, collections, datetime f = umfile.UMFile(sys.argv[1]) times=collections.defaultdict(int) for k in range(f.fixhd[FH_LookupSize2]): ilookup = f.ilookup[k] if ilookup[LBEGIN] == -99: break t = datetime.datetime(ilookup[LBYR], ilookup[LBMON], ilookup[LBDAT], ilookup[LBHR], ilookup[LBMIN], ilookup[LBDAY]) times[t] += 1 print "Valid_times", for t in sorted(times.keys()): print t.strftime('%Y%m%d%H%M'), print if len(set(times.values())) > 1: print "Warning - not all times have same number of fields"
elif opt[0] == '-y': y0 = int(opt[1].split(',')[0]) ny = int(opt[1].split(',')[1]) except getopt.error: usage() sys.exit(2) if len(args) != 3: print "Missing filename arguments" usage() # Section to take if verbose: print "Section", x0, y0, nx, ny f1 = umfile.UMFile(args[0]) f2 = umfile.UMFile(args[1]) g = umfile.UMFile(args[2], "w") g.copyheader(f1) for k in range(f1.fixhd[FH_LookupSize2]): if f1.ilookup[k][LBEGIN] == -99 or f2.ilookup[k][LBEGIN] == -99: break if f1.ilookup[k][ITEM_CODE] != f2.ilookup[k][ITEM_CODE]: raise Exception( "files do not match %d %d %d" % (k, f1.ilookup[k][ITEM_CODE], f2.ilookup[k][ITEM_CODE])) data1 = f1.readfld(k) dataout = f2.readfld(k)
from um_fileheaders import * def usage(): print "Usage: mergefiles.py -file1 file2 outputfile" sys.exit(2) vlist = [] xlist = [] nfields = 9999999999 prognostic = False if len(sys.argv) != 4: print "Missing filename arguments" usage() f1 = umfile.UMFile(sys.argv[1]) f2 = umfile.UMFile(sys.argv[2]) g = umfile.UMFile(sys.argv[3], "w") g.copyheader(f) print "Lookup sizes", f1.fixhd[FH_LookupSize2], f1.fixhd[FH_LookupSize1], \ f2.fixhd[FH_LookupSize2], f2.fixhd[FH_LookupSize1] g.ilookup[:] = -99 # Used as missing value # Start of data is at fixhd[FH_DataStart], # This should be a multiple of 2048 + 1 # Start of lookup table fixhd[FH_LookupStart] min_dstart = g.fixhd[FH_LookupStart] + np.prod(olookup.shape)
import getopt, sys import umfile from um_fileheaders import * try: optlist, args = getopt.getopt(sys.argv[1:], 'i:o:') for opt in optlist: if opt[0] == '-i': ifile = opt[1] elif opt[0] == '-o': ofile = opt[1] except getopt.error: print "Usage: change_endianness.py -i ifile -o ofile" sys.exit(2) f = umfile.UMFile(ifile) g = umfile.UMFile(ofile, "w") g.copyheader(f) g.rlookup = g.rlookup.byteswap() # Set output byteorder to be opposite of input if f.byteorder == '>': g.byteorder = '<' elif f.byteorder == '<': g.byteorder = '>' else: # Native if sys.byteorder == 'little': g.byteorder = '>' # Big else:
dest='ncvarname', required=True, help='netCDF variable name') parser.add_argument('target', help='UM File to change') args = parser.parse_args() d = cdms2.open(args.ncfile) try: # Remove singleton dimensions (time or level in surface fields) ncvar = d.variables[args.ncvarname](squeeze=1) except KeyError: print "\nError: variable %s not in %s" % (args.ncvarname, args.ncfile) sys.exit(1) f = umfile.UMFile(args.target, "r+") # Set new missing value to match the UM missing value arr = MV2.array(ncvar[:]) arr.setMissing(f.missval_r) arr = MV2.filled(arr).astype(f.float) # Loop over all the fields replaced = False for k in range(f.fixhd[FH_LookupSize2]): ilookup = f.ilookup[k] lbegin = ilookup[LBEGIN] # lbegin is offset from start if lbegin == -99: break if ilookup[ITEM_CODE] == args.varcode: print "Replacing field", k, ilookup[ITEM_CODE]