NASA Logo
Ocean Color Science Software

ocssw V2022
l3mapmerge.py
Go to the documentation of this file.
1 #! /usr/bin/env python3
2 
3 '''
4 This L3 aggregator script will:
5 1. Take in L3 mapped files
6 2. Merge data
7 '''
8 
9 import argparse
10 
11 import sys
12 import netCDF4 as nc
13 import os
14 
15 __version__ = "1.0"
16 verbose = False
17 
18 # Copy groups from topB to topA
19 
20 def copyGroups(topA, topB):
21  for group_name, group in topB.groups.items():
22  topA.createGroup(group_name)
23 
24  # Copy group attributes
25  for attr in group.ncattrs():
26  topA[group_name].setncattr(attr, group.getncattr(attr))
27 
28  if verbose:
29  print("copying variables for group", group_name, ":")
30 
31  # Iterate through variables and copy all variables and their attributes
32  for name, variable in group.variables.items():
33  if verbose:
34  print(" ", name)
35 
36  if "_FillValue" in variable.ncattrs():
37  fill_value = variable.getncattr("_FillValue")
38  else:
39  fill_value = None
40 
41  topA[group_name].createVariable(name, variable.datatype, variable.dimensions, fill_value=fill_value)
42 
43  for attr in variable.ncattrs():
44  if attr != "_FillValue":
45  topA[group_name].variables[name].setncattr(attr, variable.getncattr(attr))
46 
47  topA[group_name].variables[name][:] = variable[:]
48 
49  if len(group.groups) != 0:
50  copyGroups(topA[group_name], group)
51 
52 
53 
54 def merge(idatasets,ofile, products):
55  # delete output file if it exists
56  try:
57  os.remove(ofile)
58  except OSError as e:
59  pass
60  pass
61  # Create output file
62  orootgrp = nc.Dataset(ofile, "w", format="NETCDF4")
63  # Create dimensions for output file. Note all L2 files will/should have the same dimensions.
64  for name, dim in idatasets[0].dimensions.items():
65  orootgrp.createDimension(name, len(dim) if not dim.isunlimited() else None)
66 
67  # copy global attributes from first L3 file into mergefile
68  for attr in idatasets[0].ncattrs():
69  if attr == "product_name":
70  orootgrp.setncattr(attr, ofile)
71  else:
72  orootgrp.setncattr(attr, idatasets[0].getncattr(attr))
73 
74  # recursively copy first dataset's contents into orootgrp
75  copyGroups(orootgrp, idatasets[0])
76  dims = orootgrp.dimensions
77  nlat : int = dims["lat"].size
78  nlon : int = dims["lon"].size
79  if verbose:
80  print("copying variables from the file roots:")
81  for ds in idatasets:
82  dims = ds.dimensions
83  if dims["lat"].size != nlat:
84  print(f"--Error--: latitude dimenstions mismatch for {ds.product_name}")
85  exit(1)
86  if dims["lon"].size != nlon:
87  print(f"--Error--: longitude dimenstions mismatch for {ds.product_name}")
88  exit(1)
89  for name, ivariable in ds.variables.items():
90  if name in products:
91  if (name not in orootgrp.variables):
92  if verbose:
93  print(" ", name)
94 
95  if "_FillValue" in ivariable.ncattrs():
96  fill_value = ivariable.getncattr("_FillValue")
97  else:
98  fill_value = None
99  ovariable = orootgrp.createVariable(name, ivariable.datatype, ivariable.dimensions, fill_value=fill_value)
100 
101  for attr in ivariable.ncattrs():
102  #create a new attribute name/value pair
103  if attr != "_FillValue":
104  ovariable.setncattr(attr, ivariable.getncattr(attr))
105 
106  ovariable[:] = ivariable[:]
107 
108  orootgrp.close()
109 
110 
111 if __name__ == "__main__":
112  # parse command line
113  parser = argparse.ArgumentParser(
114  description='Merge Level 3 mapped files')
115  parser.add_argument('--version', action='store_true', help='print program version')
116  parser.add_argument('-v', '--verbose', help='print status messages', action='store_true')
117  parser.add_argument('ifile', help='Input files (comma separated list of filenames) or a ASCII file which contains paths of L3 netcdf4 files to be merged')
118  parser.add_argument('ofile', help='Output netcdf file which will contain merged L3 file data')
119  parser.add_argument('--product', type=str, help='product(s) to map; comma separated', default = None)
120 
121  print("l3mapmerge", __version__)
122  if len(sys.argv) == 1:
123  parser.print_help()
124  sys.exit(1)
125  if(sys.argv[1] == "--version"):
126  sys.exit(0)
127 
128  args = parser.parse_args()
129  verbose = args.verbose
130  ifile : str = args.ifile
131  ifiles = ifile.split(sep=',')
132  # Read and store each line in the .txt infile as a netcdf dataset
133  idatasets = []
134  if len(ifiles) == 1: # supplied txt file
135  try:
136  with open(args.ifile) as infile:
137  for line in infile:
138  idatasets.append(nc.Dataset(line.strip(), 'r'))
139  except IOError as e:
140  print("--Error-- when trying to open input file: ", e)
141  sys.exit(1)
142  else:
143  try:
144  for ncfile in ifiles:
145  idatasets.append(nc.Dataset(ncfile.strip(), 'r'))
146  except IOError as e:
147  print("--Error-- when trying to open input file: ", e)
148  sys.exit(1)
149  if not args.product:
150  print("No products were specified. Exiting ...")
151  exit(1)
152  products : list[str] = args.product.split(",") + ['lat', 'lon']
153 
154  print("Merging datasets...")
155  merge(idatasets, args.ofile, products)
character(len=1000) if
Definition: names.f90:13
def copyGroups(topA, topB)
Definition: l3mapmerge.py:20
void print(std::ostream &stream, const char *format)
Definition: PrintDebug.hpp:38
def merge(idatasets, ofile, products)
Definition: l3mapmerge.py:54