1 /*
2   This file is part of CDO. CDO is a collection of Operators to manipulate and analyse Climate model Data.
3 
4   Author: Uwe Schulzweida
5 
6 */
7 
8 #include <cstdlib>
9 #include <string>
10 
11 #include "cdo_options.h"
12 #include "cdo_output.h"
13 #include "process_int.h"
14 #include "pmlist.h"
15 #include "convert_units.h"
16 #include "param_conversion.h"
17 #include "parse_literals.h"
18 #include "cdo_cmor.h"
19 #include "cdo_cdi_wrapper.h"
20 
21 int string_to_param(const char *paramstr);
22 
23 void
mapvar(int vlistID,int varID,const KeyValues & kv,const std::string & key,CmorVar * var,bool & lvalid_min,bool & lvalid_max,int ptab,bool isnPtmodeName)24 mapvar(int vlistID, int varID, const KeyValues &kv, const std::string &key, CmorVar *var, bool &lvalid_min, bool &lvalid_max,
25        int ptab, bool isnPtmodeName)
26 {
27   const char *value = (kv.nvalues > 0) ? kv.values[0].c_str() : nullptr;
28   const bool lv1 = (kv.nvalues == 1);
29 
30   // printf("key=%s  value=%s\n", key, value ? value : "");
31 
32   // clang-format off
33   if (!var)
34     {
35       if (key == "cn")
36         {
37           char name[CDI_MAX_NAME];
38           vlistInqVarName(vlistID, varID, name);
39           if (name[0] != 0) cdiDefAttTxt(vlistID, varID, "original_name", (int) strlen(name), parameter_to_word(name));
40           cdiDefKeyString(vlistID, varID, CDI_KEY_NAME, parameter_to_word(value));
41         }
42       else if (key == "u")
43         cdiDefKeyString(vlistID, varID, CDI_KEY_UNITS, value);
44       else if (key == "cm")
45         cdiDefAttTxt(vlistID, varID, "cell_methods", (int) strlen(value), value);
46       else if (key == "ca")
47         cdiDefAttTxt(vlistID, varID, "character_axis", (int) strlen(value), value);
48       else if (key == "za")
49         cdiDefAttTxt(vlistID, varID, "z_axis", (int) strlen(value), value);
50       else if (key == "vc")
51         cdiDefAttTxt(vlistID, varID, "variable_comment", (int) strlen(value), value);
52       else if (key == "p")
53         {
54           if (!isspace(value[0])) cdiDefAttTxt(vlistID, varID, "positive", (int) strlen(value), value);
55         }
56       else
57         {
58           if (Options::cdoVerbose) cdo_print("In applying the mapping table:\n          Key: '%s' is ignored.", key);
59         }
60     }
61   else
62     {
63       if      (lv1 && key == "standard_name") cdiDefKeyString(vlistID, varID, CDI_KEY_STDNAME, value);
64       else if (lv1 && key == "long_name") cdiDefKeyString(vlistID, varID, CDI_KEY_LONGNAME, value);
65       else if (lv1 && key == "units") cdiDefKeyString(vlistID, varID, CDI_KEY_UNITS, value);
66       else if (lv1 && key == "name")
67         {
68           if (isnPtmodeName) cdiDefKeyString(vlistID, varID, CDI_KEY_NAME, parameter_to_word(value));
69         }
70       else if (lv1 && key == "out_name")
71         {
72           const auto outname = parameter_to_word(value);
73           if (!cdo_cmpstr(var->name, outname))
74             {
75               cdiDefKeyString(vlistID, varID, CDI_KEY_NAME, outname);
76               cdiDefAttTxt(vlistID, varID, "original_name", (int) strlen(var->name), var->name);
77             }
78         }
79       else if (lv1 && key == "param")
80         vlistDefVarParam(vlistID, varID, string_to_param(parameter_to_word(value)));
81       else if (lv1 && key == "out_param")
82         vlistDefVarParam(vlistID, varID, string_to_param(parameter_to_word(value)));
83       else if (lv1 && key == "code")
84         vlistDefVarParam(vlistID, varID, cdiEncodeParam(parameter_to_int(value), ptab, 255));
85       else if (lv1 && key == "out_code")
86         vlistDefVarParam(vlistID, varID, cdiEncodeParam(parameter_to_int(value), ptab, 255));
87       else if (lv1 && key == "uvRelativeToGrid")
88         cdiDefKeyInt(vlistID, varID, CDI_KEY_UVRELATIVETOGRID, parameter_to_bool(value));
89       else if (lv1 && key == "comment")
90         cdiDefAttTxt(vlistID, varID, key.c_str(), (int) strlen(value), value);
91       else if (lv1 && key == "chunktype") ;
92       else if (lv1 && key == "cell_methods")
93         cdiDefAttTxt(vlistID, varID, key.c_str(), (int) strlen(value), value);
94       else if (lv1 && key == "cell_measures")
95         cdiDefAttTxt(vlistID, varID, key.c_str(), (int) strlen(value), value);
96       else if (lv1 && key == "delete") var->remove = parameter_to_bool(value);
97       else if (lv1 && key == "convert") var->convert = parameter_to_bool(value);
98       else if (lv1 && key == "factor")
99         {
100           var->lfactor = true;
101           var->factor = parameter_to_double(value);
102           if (Options::cdoVerbose) cdo_print("%s - scale factor %g", var->name, var->factor);
103         }
104       else if (lv1 && (key == "missval" || key == "missing_value"))
105         {
106           const auto missval = parameter_to_double(value);
107           const auto missval_old = vlistInqVarMissval(vlistID, varID);
108           if (!DBL_IS_EQUAL(missval, missval_old))
109             {
110               if (Options::cdoVerbose) cdo_print("%s - change missval from %g to %g", var->name, missval_old, missval);
111               var->changemissval = true;
112               var->missval_old = missval_old;
113               vlistDefVarMissval(vlistID, varID, missval);
114             }
115         }
116       else if (lv1 && key == "valid_min")
117         {
118           lvalid_min = true;
119           var->valid_min = parameter_to_double(value);
120         }
121       else if (lv1 && key == "valid_max")
122         {
123           lvalid_max = true;
124           var->valid_max = parameter_to_double(value);
125         }
126       else if (lv1 && key == "ok_min_mean_abs")
127         {
128           var->check_min_mean_abs = true;
129           var->ok_min_mean_abs = parameter_to_double(value);
130         }
131       else if (lv1 && key == "ok_max_mean_abs")
132         {
133           var->check_max_mean_abs = true;
134           var->ok_max_mean_abs = parameter_to_double(value);
135         }
136       else if (lv1 && (key == "datatype" || key == "type"))
137         {
138           const auto datatype = cdo_str_to_datatype(parameter_to_word(value));
139           if (datatype != -1) vlistDefVarDatatype(vlistID, varID, datatype);
140         }
141       else if (lv1 && key == "dimensions")
142         {
143         }
144       else
145         {
146           const auto &values = kv.values;
147           const auto &rvalue = kv.values[0];
148           int nvalues = kv.nvalues;
149           if (nvalues == 1 && rvalue.empty()) nvalues = 0;
150 
151           const int dtype = literals_find_datatype(nvalues, values);
152 
153           if (dtype == CDI_DATATYPE_INT8 || dtype == CDI_DATATYPE_INT16 || dtype == CDI_DATATYPE_INT32)
154             {
155               std::vector<int> ivals(nvalues);
156               for (int i = 0; i < nvalues; ++i) ivals[i] = literal_to_int(values[i]);
157               cdiDefAttInt(vlistID, varID, key.c_str(), dtype, nvalues, ivals.data());
158             }
159           else if (dtype == CDI_DATATYPE_FLT32 || dtype == CDI_DATATYPE_FLT64)
160             {
161               std::vector<double> dvals(nvalues);
162               for (int i = 0; i < nvalues; ++i) dvals[i] = literal_to_double(values[i]);
163               cdiDefAttFlt(vlistID, varID, key.c_str(), dtype, nvalues, dvals.data());
164             }
165           else
166             {
167               const int len = (int)rvalue.size();
168               cdiDefAttTxt(vlistID, varID, key.c_str(), len, rvalue.c_str());
169             }
170         }
171     }
172   // clang-format on
173 }
174