libpniio
field.hpp
Go to the documentation of this file.
1 //
2 // (c) Copyright 2014 DESY, Eugen Wintersberger <eugen.wintersberger@desy.de>
3 //
4 // This file is part of libpniio.
5 //
6 // libpniio is free software: you can redistribute it and/or modify
7 // it under the terms of the GNU General Public License as published by
8 // the Free Software Foundation, either version 2 of the License, or
9 // (at your option) any later version.
10 //
11 // libpniio is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU General Public License for more details.
15 //
16 // You should have received a copy of the GNU General Public License
17 // along with libpniio. If not, see <http://www.gnu.org/licenses/>.
18 // ===========================================================================
19 //
20 // Created on: Nov 25, 2014
21 // Author: Eugen Wintersberger <eugen.wintersberger@desy.de>
22 //
23 
24 #pragma once
25 
26 #include <pni/core/types.hpp>
27 #include <pni/core/type_erasures.hpp>
28 
29 #include "../algorithms/create_field.hpp"
30 #include "../algorithms/create_attribute.hpp"
31 #include "../algorithms/write.hpp"
32 #include "../algorithms/get_name.hpp"
33 #include "../algorithms/get_unit.hpp"
34 #include "../algorithms/as_field.hpp"
35 #include "../algorithms/as_group.hpp"
36 #include "../algorithms/get_size.hpp"
37 #include "../algorithms/get_shape.hpp"
38 #include "../nxobject.hpp"
39 #include "node.hpp"
40 #include "dimensions.hpp"
41 #include "io_node.hpp"
42 
43 
44 
45 namespace pni{
46 namespace io{
47 namespace nx{
48 namespace xml{
49 
53  struct field : public io_node
54  {
55 
56  //--------------------------------------------------------------------
65  static pni::core::string unit(const node &field_node);
66 
67  //--------------------------------------------------------------------
77  static pni::core::string long_name(const node &field_node);
78 
79  //--------------------------------------------------------------------
90  static pni::core::shape_t chunk(const node &field_node);
91 
92  //--------------------------------------------------------------------
114  template<
115  typename GTYPE,
116  typename FTYPE,
117  typename ATYPE,
118  typename LTYPE
119  >
122  const node &field_node)
123  {
124  using namespace pni::core;
125 
126  typedef nxobject<GTYPE,FTYPE,ATYPE,LTYPE> object_type;
127  //determine basic field parameters
128  string field_name = name(field_node);
129  shape_t field_shape = shape(field_node);
130  type_id_t tid = type_id(field_node);
131  shape_t chunk_shape = chunk(field_node);
132 
133  if(chunk_shape.empty())
134  {
135  chunk_shape = field_shape;
136  chunk_shape[0] = 1;
137 
138  //if we have only a scalar field we set the chunk size to 1K
139  if(field_shape.size()==1)
140  chunk_shape[0] = 1024;
141  }
142  else
143  {
144  if(chunk_shape.size() != field_shape.size())
145  throw shape_mismatch_error(EXCEPTION_RECORD,
146  "Rank of chunk and dimensions tag do not match!");
147  }
148 
149  //if the field tag contains a strategy tag we have to check
150  //for possible compression attributes
151  bool use_compression = false;
152  bool use_shuffle = false;
153  size_t compression_rate = 0;
154  auto strategy = field_node.get_child_optional("strategy");
155  if(strategy)
156  {
157  if(has_attribute(*strategy,"compression"))
158  use_compression = data_from_xml<bool>(
159  get_attribute(*strategy,"compression"));
160 
161  if(has_attribute(*strategy,"shuffle"))
162  use_shuffle = data_from_xml<bool>(
163  get_attribute(*strategy,"shuffle"));
164 
165  if(has_attribute(*strategy,"rate"))
166  compression_rate = data_from_xml<size_t>(
167  get_attribute(*strategy,"rate"));
168 
169  }
170 
171  //construct the field object
172  object_type f;
173  if(use_compression)
174  {
175  typedef nximp_code_map<GTYPE> map_type;
176  typedef nxobject_trait<map_type::icode> trait_type;
177  typedef typename trait_type::deflate_type deflate_type;
178 
179  deflate_type comp(compression_rate,use_shuffle);
180  f = create_field(parent,tid,field_name,field_shape,chunk_shape,comp);
181  }
182  else
183  f = create_field(parent,tid,field_name,field_shape,chunk_shape);
184 
185  //add long name if requested by XML
186  if(has_attribute(field_node,"long_name"))
187  write(create_attribute<string>(f,"long_name"),
188  long_name(field_node));
189 
190  //add units if requested by XML
191  if(has_attribute(field_node,"units"))
192  write(create_attribute<string>(f,"units"),
193  unit(field_node));
194 
195  return f;
196  }
197 
198  //-----------------------------------------------------------------
216  template<
217  typename GTYPE,
218  typename FTYPE,
219  typename ATYPE,
220  typename LTYPE
221  >
223  {
224  using namespace pni::core;
225 
226  node field_node;
227  FTYPE fo = as_field(f); //throw type_error if f is not a field
228  string buffer;
229 
230  //write name and type attributes
231  field_node.put("<xmlattr>.name",fo.name());
232  field_node.put("<xmlattr>.type",str_from_type_id(fo.type_id()));
233 
234  //add a units attribute if the original field has one
235  if(fo.attributes.exists("units"))
236  {
237  fo.attributes["units"].read(buffer);
238  field_node.put("<xmlattr>.units",buffer);
239  }
240 
241  //add a long_name attributes if the original field has one
242  if(fo.attributes.exists("long_name"))
243  {
244  fo.attributes["long_name"].read(buffer);
245  field_node.put("<xmlattr>.long_name",buffer);
246  }
247 
248  //write the shape if it is not scalar field
249  auto s = get_shape<shape_t>(f);
250  if(s.size() && (get_size(f)!=1))
251  field_node.add_child("dimensions",dimensions::object_to_xml(s));
252 
253  return field_node;
254  }
255 
256  };
257 
258 
259 //end of namespace
260 }
261 }
262 }
263 }
static pni::core::shape_t chunk(const node &field_node)
get chunk shape
Definition: field.cpp:65
static pni::core::string long_name(const node &field_node)
return long name
Definition: field.cpp:51
bool has_attribute(const node &parent, const pni::core::string &name)
check for attribute existence
nexus object traits
Definition: nxobject_traits.hpp:44
read and write field data
Definition: field.hpp:53
static node object_to_xml(const nxobject< GTYPE, FTYPE, ATYPE, LTYPE > &f)
create XML object from field
Definition: field.hpp:222
size_t get_size(const OTYPE< IMPID > &o)
get number of elements
Definition: get_size.hpp:61
static pni::core::type_id_t type_id(const node &io_node)
get type id
Definition: io_node.cpp:72
nxobject< GTYPE, FTYPE, ATYPE, LTYPE > create_field(const nxobject< GTYPE, FTYPE, ATYPE, LTYPE > &location, const PATHT &path, const STYPE &shape, const STYPE &chunk, const FILTERT &filter)
field construction
Definition: create_field.hpp:232
Definition: cbf_reader.hpp:41
static pni::core::string unit(const node &field_node)
return field unit
Definition: field.cpp:37
boost::property_tree::ptree node
alias for ptree
Definition: node.hpp:39
FTYPE as_field(const nxobject< GTYPE, FTYPE, ATYPE, LTYPE > &o)
as field wrapper
Definition: as_field.hpp:166
static node object_to_xml(const pni::core::shape_t &s)
create dimension node
Definition: dimensions.cpp:105
static pni::core::string name(const node &io_node)
return object name
Definition: io_node.cpp:54
static nxobject< GTYPE, FTYPE, ATYPE, LTYPE > object_from_xml(const nxobject< GTYPE, FTYPE, ATYPE, LTYPE > &parent, const node &field_node)
create field from XML
Definition: field.hpp:121
implementation code type map
Definition: nximp_code_map.hpp:37
node get_attribute(const node &parent, const pni::core::string &name)
get attribute node
boost::variant< GTYPE, FTYPE, ATYPE, LTYPE > nxobject
Definition: nxobject.hpp:44
static pni::core::shape_t shape(const node &io_node)
return object shape
Definition: io_node.cpp:61
general IO objects
Definition: io_node.hpp:43
void write(const OTYPE< IMPID > &o, const ATYPE &a)
write data to an attribute or field
Definition: write.hpp:61