IODA
ObsFrameWrite.cc
Go to the documentation of this file.
1 /*
2  * (C) Copyright 2017-2019 UCAR
3  *
4  * This software is licensed under the terms of the Apache Licence Version 2.0
5  * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0.
6  */
7 
8 #include "oops/util/abor1_cpp.h"
9 
10 #include "oops/util/Logger.h"
11 
12 #include "ioda/io/ObsFrameWrite.h"
13 
14 namespace ioda {
15 
16 //--------------------------- public functions ---------------------------------------
17 //------------------------------------------------------------------------------------
18 
20  ObsFrame(params) {
21  // Create the ObsIo object
23  max_frame_size_ = params.top_level_.obsOutFile.value()->maxFrameSize;
24  oops::Log::debug() << "ObsFrameWrite: maximum frame size: " << max_frame_size_ << std::endl;
25 }
26 
28 
29 //------------------------------------------------------------------------------------
31  const VarNameObjectList & dimVarList,
32  const VarDimMap & varDimMap, const Dimensions_t maxVarSize) {
33  frame_start_ = 0;
34  max_var_size_ = maxVarSize;
35 
36  // create an ObsGroup based frame with an in-memory backend
37  createFrameFromObsGroup(varList, dimVarList, varDimMap);
38 
39  // copy dimension coordinates from the newly created frame to the ObsIo backend
40  copyObsIoDimCoords(obs_frame_.vars, obs_io_->vars(), dimVarList);
41 
42  // create variables in the ObsIo backend
43  createObsIoVariables(obs_frame_.vars, obs_io_->vars(), varDimMap);
44 }
45 
46 //------------------------------------------------------------------------------------
48  // Transfer the current frame variable data to the ObsIo backend.
49  Dimensions_t frameStart = this->frameStart();
50  for (auto & varNameObject : varList) {
51  std::string varName = varNameObject.first;
52  Variable sourceVar = obs_frame_.vars.open(varName);
53  Dimensions_t frameCount = this->frameCount(varName);
54  if (frameCount > 0) {
55  // Transfer the variable data for this frame. Do this in two steps:
56  // frame storage --> memory buffer --> ObsIo
57 
58  // Selection objects for transfer;
59  Variable destVar = obs_io_->vars().open(varName);
60  std::vector<Dimensions_t> destVarShape = destVar.getDimensions().dimsCur;
61  std::vector<Dimensions_t> sourceVarShape = sourceVar.getDimensions().dimsCur;
62 
63  Selection obsFrameSelect = createEntireFrameSelection(sourceVarShape, frameCount);
64  Selection memBufferSelect = createMemSelection(sourceVarShape, frameCount);
65  Selection obsIoSelect = createObsIoSelection(destVarShape, frameStart, frameCount);
66 
67  // Transfer the data
68  if (destVar.isA<int>()) {
69  std::vector<int> varValues;
70  sourceVar.read<int>(varValues, memBufferSelect, obsFrameSelect);
71  destVar.write<int>(varValues, memBufferSelect, obsIoSelect);
72  } else if (destVar.isA<float>()) {
73  std::vector<float> varValues;
74  sourceVar.read<float>(varValues, memBufferSelect, obsFrameSelect);
75  destVar.write<float>(varValues, memBufferSelect, obsIoSelect);
76  } else if (destVar.isA<std::string>()) {
77  std::vector<std::string> varValues;
78  sourceVar.read<std::string>(varValues, memBufferSelect, obsFrameSelect);
79  destVar.write<std::string>(varValues, memBufferSelect, obsIoSelect);
80  }
81  }
82  }
83 
85 }
86 
87 //------------------------------------------------------------------------------------
89  return (frame_start_ < max_var_size_);
90 }
91 
92 //------------------------------------------------------------------------------------
93 Dimensions_t ObsFrameWrite::frameStart() {
94  return frame_start_;
95 }
96 
97 //------------------------------------------------------------------------------------
98 Dimensions_t ObsFrameWrite::frameCount(const std::string & varName) {
99  Dimensions_t count;
100  Variable var = obs_io_->vars().open(varName);
101  Dimensions_t varSize0 = var.getDimensions().dimsCur[0];
102  if ((frame_start_ + max_frame_size_) > varSize0) {
103  count = varSize0 - frame_start_;
104  if (count < 0) { count = 0; }
105  } else {
106  count = max_frame_size_;
107  }
108  return count;
109 }
110 
111 //-----------------------------------------------------------------------------------
112 void ObsFrameWrite::writeFrameVar(const std::string & varName,
113  const std::vector<int> & varData) {
114  writeFrameVarHelper<int>(varName, varData);
115 }
116 void ObsFrameWrite::writeFrameVar(const std::string & varName,
117  const std::vector<float> & varData) {
118  writeFrameVarHelper<float>(varName, varData);
119 }
120 void ObsFrameWrite::writeFrameVar(const std::string & varName,
121  const std::vector<std::string> & varData) {
122  writeFrameVarHelper<std::string>(varName, varData);
123 }
124 
125 //--------------------------- private functions --------------------------------------
126 
127 // -----------------------------------------------------------------------------
129  Has_Variables & destVarContainer,
130  const VarNameObjectList & dimVarList) {
131  // fill in dimension coordinate values
132  for (auto & dimVarNameObject : dimVarList) {
133  std::string dimVarName = dimVarNameObject.first;
134  Variable srcDimVar = srcVarContainer.open(dimVarName);
135  Variable destDimVar = destVarContainer.open(dimVarName);
136  std::cout << "DEBUG: dim var name: " << dimVarName << std::endl;
137 
138  // Set up the dimension selection objects.
139  std::vector<Dimensions_t> srcDimShape = srcDimVar.getDimensions().dimsCur;
140  std::vector<Dimensions_t> destDimShape = destDimVar.getDimensions().dimsCur;
141  Dimensions_t frameCount = srcDimShape[0];
142  // Transfer the coordinate values
143  if (frameCount > 0) {
144  Selection srcSelect = createEntireFrameSelection(srcDimShape, frameCount);
145  Selection memSelect = createMemSelection(destDimShape, frameCount);
146  Selection destSelect = createObsIoSelection(destDimShape, 0, frameCount);
147 
148  if (srcDimVar.isA<int>()) {
149  std::vector<int> dimCoords;
150  srcDimVar.read<int>(dimCoords, memSelect, srcSelect);
151  destDimVar.write<int>(dimCoords, memSelect, destSelect);
152  } else if (srcDimVar.isA<float>()) {
153  std::vector<float> dimCoords;
154  srcDimVar.read<float>(dimCoords, memSelect, srcSelect);
155  destDimVar.write<float>(dimCoords, memSelect, destSelect);
156  }
157  }
158  }
159 }
160 
161 // -----------------------------------------------------------------------------
163  Has_Variables & destVarContainer,
164  const VarDimMap & dimsAttachedToVars) {
165  // Walk through map to get list of variables to create along with
166  // their dimensions. Use the srcVarContainer to get the var data type.
167  for (auto & ivar : dimsAttachedToVars) {
168  std::string varName = ivar.first;
169  std::vector<std::string> varDimNames = ivar.second;
170 
172  params.chunk = true;
173  params.compressWithGZIP();
174 
175  // Create a vector with dimension scale vector from destination container
176  std::vector<Variable> varDims;
177  for (auto & dimVarName : varDimNames) {
178  varDims.push_back(destVarContainer.open(dimVarName));
179  }
180 
181  Variable srcVar = srcVarContainer.open(varName);
182  if (srcVar.isA<int>()) {
183  if (srcVar.hasFillValue()) {
184  auto varFillValue = srcVar.getFillValue();
185  params.setFillValue<int>(ioda::detail::getFillValue<int>(varFillValue));
186  }
187  destVarContainer.createWithScales<int>(varName, varDims, params);
188  } else if (srcVar.isA<float>()) {
189  if (srcVar.hasFillValue()) {
190  auto varFillValue = srcVar.getFillValue();
191  params.setFillValue<float>(ioda::detail::getFillValue<float>(varFillValue));
192  }
193  destVarContainer.createWithScales<float>(varName, varDims, params);
194  } else if (srcVar.isA<std::string>()) {
195  if (srcVar.hasFillValue()) {
196  auto varFillValue = srcVar.getFillValue();
197  params.setFillValue<std::string>(
198  ioda::detail::getFillValue<std::string>(varFillValue));
199  }
200  destVarContainer.createWithScales<std::string>(varName, varDims, params);
201  } else {
202  oops::Log::warning() << "WARNING: ObsWriteFrame::createObsIoVariables: "
203  << "Skipping variable due to an unexpected data type for variable: "
204  << varName << std::endl;
205  }
206  }
207 }
208 
209 //------------------------------------------------------------------------------------
210 void ObsFrameWrite::createFrameSelection(const std::string & varName, Selection & feSelect,
211  Selection & beSelect) {
212  // Form the selection objects for this frame. The frontend selection will
213  // simply be the current size (according to the variable) of the frame going from
214  // 0 to size-1.
215  //
216  // The backend selection will start at the frame start value (instead of zero) and
217  // be determined by the size of the frame for the given variable.
218 
219  // Grab the variable dimensions and use this as a template for the selection operators.
220  std::vector<Dimensions_t> varDims = obs_io_->vars().open(varName).getDimensions().dimsCur;
221  Dimensions_t frameStart = this->frameStart();
222  Dimensions_t frameCount = this->frameCount(varName);
223 
224  // Substitute the frameCount for the first dimension size of the variable.
225  varDims[0] = frameCount;
226 
227  // For the frontend, treat the data as a vector with a total size given by the product
228  // of the dimension sizes considering the possible adjustment of the fisrt
229  // dimension (varDims). Use hyperslab style selection since we will be consolidating
230  // the selected locations into a contiguous series.
231  Dimensions_t numElements = std::accumulate(
232  varDims.begin(), varDims.end(), 1, std::multiplies<Dimensions_t>());
233  std::vector<Dimensions_t> feStarts(1, 0);
234  std::vector<Dimensions_t> feCounts(1, numElements);
235  feSelect.extent(feCounts).select({ SelectionOperator::SET, feStarts, feCounts });
236 
237  // For the backend, use a hyperslab style.
238  std::vector<Dimensions_t> beStarts(varDims.size(), 0);
239  beStarts[0] = frameStart;
240  std::vector<Dimensions_t> beCounts = varDims;
241  beSelect.select({ SelectionOperator::SET, beStarts, beCounts });
242 }
243 
244 //-----------------------------------------------------------------------------------
245 void ObsFrameWrite::print(std::ostream & os) const {
246  os << "ObsFrameWrite: " << std::endl;
247 }
248 
249 } // namespace ioda
This class exists inside of ioda::Group and provides the interface to manipulating Variables.
std::shared_ptr< ObsIo > obs_io_
ObsIo object.
Definition: ObsFrame.h:161
Selection createMemSelection(const std::vector< Dimensions_t > &varShape, const Dimensions_t frameCount)
create selection object for accessing a memory buffer
Definition: ObsFrame.cc:26
virtual void frameNext()
move to the next frame for a read frame object
Definition: ObsFrame.h:111
virtual void frameInit()
initialize frame for a read frame object
Definition: ObsFrame.h:99
void createFrameFromObsGroup(const VarNameObjectList &varList, const VarNameObjectList &dimVarList, const VarDimMap &varDimMap)
create a frame object based on dimensions and variables from a source ObsGroup
Definition: ObsFrame.cc:109
Dimensions_t max_frame_size_
maximum frame size
Definition: ObsFrame.h:183
Dimensions_t max_var_size_
maximum variable size
Definition: ObsFrame.h:186
Selection createEntireFrameSelection(const std::vector< Dimensions_t > &varShape, const Dimensions_t frameCount)
create selection object for accessing the entire frame variable
Definition: ObsFrame.cc:49
Dimensions_t frame_start_
current frame starting index
Definition: ObsFrame.h:189
Selection createObsIoSelection(const std::vector< Dimensions_t > &varShape, const Dimensions_t frameStart, const Dimensions_t frameCount)
create selection object for accessing an ObsIo variable
Definition: ObsFrame.cc:91
ObsGroup obs_frame_
ObsGroup object (temporary storage for a single frame)
Definition: ObsFrame.h:164
ObsFrameWrite(const ObsSpaceParameters &params)
void writeFrameVar(const std::string &varName, const std::vector< int > &varData)
write a frame variable
void print(std::ostream &os) const override
print routine for oops::Printable base class
Dimensions_t frameCount(const std::string &varName) override
return current frame count for variable
void createObsIoVariables(const Has_Variables &srcVarContainer, Has_Variables &destVarContainer, const VarDimMap &dimsAttachedToVars)
create set of variables from source variables and lists in the ObsIo backend
void copyObsIoDimCoords(const Has_Variables &srcVarContainer, Has_Variables &destVarContainer, const VarNameObjectList &dimVarList)
copy dimension coordinate values from the frame to the ObsIo backend
void createFrameSelection(const std::string &varName, Selection &feSelect, Selection &beSelect)
set up frontend and backend selection objects for the given variable
bool frameAvailable() override
true if a frame is available (not past end of frames)
Dimensions_t frameStart() override
return current frame starting index
static std::shared_ptr< ObsIo > create(ObsIoModes mode, const ObsSpaceParameters &parameters)
Create and return a new instance of an ObsIo subclass.
Definition: ObsIoFactory.cc:24
A Selection represents the bounds of the data, in ioda or in userspace, that you are reading or writi...
Definition: Selection.h:48
Variables store data!
Definition: Variable.h:680
Has_Variables vars
Use this to access variables.
Definition: Group.h:123
Variable createWithScales(const std::string &name, const std::vector< Variable > &dimension_scales, const VariableCreationParameters &params=VariableCreationParameters::defaulted< DataType >())
Convenience function to create a Variable from certain dimension scales.
virtual Variable open(const std::string &name) const
Open a Variable by name.
virtual FillValueData_t getFillValue() const
Retrieve the fill value.
Definition: Variable.cpp:111
bool isA() const
Convenience function to check a Variable's storage type.
Definition: Variable.h:99
virtual bool hasFillValue() const
Check if a variable has a fill value set.
Definition: Variable.cpp:98
virtual Dimensions getDimensions() const
Definition: Variable.cpp:160
virtual Variable read(gsl::span< char > data, const Type &in_memory_dataType, const Selection &mem_selection=Selection::all, const Selection &file_selection=Selection::all) const
Read the Variable - as char array. Ordering is row-major.
Definition: Variable.cpp:330
virtual Variable write(gsl::span< char > data, const Type &in_memory_dataType, const Selection &mem_selection=Selection::all, const Selection &file_selection=Selection::all)
The fundamental write function. Backends overload this function to implement all write operations.
Definition: Variable.cpp:317
Selection & extent(const VecDimensions_t &sz)
Provide the dimensions of the object that you are selecting from.
Definition: Selection.h:111
Selection & select(const SingleSelection &s)
Append a new selection.
Definition: Selection.h:103
std::vector< std::pair< std::string, Variable > > VarNameObjectList
typedef for holding list of variable names with associated variable object
Definition: IodaUtils.h:30
std::map< std::string, std::vector< std::string > > VarDimMap
typedef for holding dim names attached to variables
Definition: IodaUtils.h:36
std::vector< Dimensions_t > dimsCur
The dimensions of the data.
Definition: Dimensions.h:23
Used to specify Variable creation-time properties.
Definition: Has_Variables.h:57