"Fossies" - the Fresh Open Source Software Archive

Member "fimex-1.6.7/src/CDMOverlay.cc" (1 Jul 2021, 6181 Bytes) of package /linux/privat/fimex-1.6.7.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "CDMOverlay.cc" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 1.6.6_vs_1.6.7.

    1 /*
    2  * Fimex, CDMOverlay.cc
    3  *
    4  * (C) Copyright 2013-2021, met.no
    5  *
    6  * Project Info:  https://wiki.met.no/fimex/start
    7  *
    8  * This library is free software; you can redistribute it and/or modify it
    9  * under the terms of the GNU Lesser General Public License as published by
   10  * the Free Software Foundation; either version 2.1 of the License, or
   11  * (at your option) any later version.
   12  *
   13  * This library is distributed in the hope that it will be useful, but
   14  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
   15  * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
   16  * License for more details.
   17  *
   18  * You should have received a copy of the GNU Lesser General Public
   19  * License along with this library; if not, write to the Free Software
   20  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301,
   21  * USA.
   22  *
   23  *  Created on: Nov 6, 2013
   24  *      Author: Alexander B├╝rger
   25  */
   26 
   27 #include "fimex/CDMOverlay.h"
   28 
   29 #include "fimex/CDM.h"
   30 #include "fimex/CDMException.h"
   31 #include "fimex/CDMInterpolator.h"
   32 #include "fimex/Data.h"
   33 #include "fimex/Logger.h"
   34 #include "fimex/MathUtils.h"
   35 
   36 #include "CDMMergeUtils.h"
   37 
   38 using namespace std;
   39 
   40 namespace MetNoFimex {
   41 
   42 static Logger_p logger(getLogger("fimex.CDMOverlay"));
   43 
   44 // ========================================================================
   45 
   46 struct CDMOverlayPrivate {
   47     CDMReader_p readerB;
   48     CDMReader_p readerT;
   49     CDMInterpolator_p interpolatedB;
   50 
   51     CDM init(int gridInterpolationMethod, bool keepOuterVariables);
   52 };
   53 
   54 // ========================================================================
   55 
   56 // base == big == outer, top == small == inner
   57 CDMOverlay::CDMOverlay(CDMReader_p base, CDMReader_p top, int grim, bool keepOuterVariables)
   58     : p(new CDMOverlayPrivate)
   59 {
   60     p->readerB = base;
   61     p->readerT = top;
   62     *cdm_ = p->init(grim, keepOuterVariables);
   63 }
   64 
   65 CDMOverlay::~CDMOverlay() {}
   66 
   67 // ------------------------------------------------------------------------
   68 
   69 namespace {
   70 template<class T> bool value_is_nan(T) { return false; }
   71 template<> bool value_is_nan<float>(float f) { return mifi_isnan(f); }
   72 template<> bool value_is_nan<double>(double d) { return mifi_isnan(d); }
   73 
   74 template <class T>
   75 DataPtr overlayDataSlices(T fillT, T fillB, DataPtr sliceT, DataPtr sliceB)
   76 {
   77     const shared_array<T> valuesT = dataAs<T>(sliceT);
   78     shared_array<T> valuesB = dataAs<T>(sliceB);
   79     for (size_t i = 0; i < sliceB->size(); ++i) {
   80         const T valueT = valuesT[i];
   81         T& valueB = valuesB[i];
   82         if (!(value_is_nan<T>(valueT) || valueT == fillT))
   83             valueB = valueT;
   84         if (value_is_nan<T>(valueB) || valueB == fillB)
   85             valueB = fillT; // need to use FillValue from top
   86     }
   87     return createData(sliceB->size(), valuesB);
   88 }
   89 } // namespace
   90 
   91 DataPtr CDMOverlay::getDataSlice(const std::string &varName, size_t unLimDimPos)
   92 {
   93     const CDM& cdmT = p->readerT->getCDM();
   94 
   95     // use cdmB if not defined in cdmT
   96     // get simple coordinate variables from readerT
   97     if (cdm_->hasDimension(varName) && cdmT.hasVariable(varName)) {
   98         // read dimension variables from top
   99         return p->readerT->getDataSlice(varName, unLimDimPos); // not scaled
  100     }
  101 
  102     if (!cdmT.hasVariable(varName)) {
  103         // use complete base-data
  104         return p->interpolatedB->getDataSlice(varName, unLimDimPos);
  105     }
  106 
  107     const CDM& cdmB = p->interpolatedB->getCDM();
  108     if (not cdmB.hasVariable(varName))
  109         THROW("variable '" << varName << "' unknown in base");
  110 
  111     const std::string unitsT = cdmT.getUnits(varName);
  112     const std::string unitsB = cdmB.getUnits(varName);
  113 
  114     const CDMDataType dtT = cdmT.getVariable(varName).getDataType();
  115     const CDMDataType dtB = cdmB.getVariable(varName).getDataType();
  116 
  117     if (unitsT == unitsB
  118         && dtT == dtB
  119         && cdmT.getScaleFactor(varName) == cdmB.getScaleFactor(varName)
  120         && cdmT.getAddOffset(varName) == cdmB.getAddOffset(varName))
  121     {
  122         DataPtr sliceT = p->readerT->getDataSlice(varName, unLimDimPos);
  123         DataPtr sliceB = p->interpolatedB->getDataSlice(varName, unLimDimPos);
  124         if (dtT == CDM_FLOAT) {
  125             LOG4FIMEX(logger, Logger::DEBUG, "overlay using float without scaling");
  126             return overlayDataSlices<float>(cdmT.getFillValue(varName), cdmB.getFillValue(varName), sliceT, sliceB);
  127         } else if (dtT == CDM_DOUBLE) {
  128             LOG4FIMEX(logger, Logger::DEBUG, "overlay using double without scaling");
  129             return overlayDataSlices<double>(cdmT.getFillValue(varName), cdmB.getFillValue(varName), sliceT, sliceB);
  130         }
  131     }
  132 
  133     // getScaledDataSlice always returns DataPtr with CDM_DOUBLE
  134     const bool emptyUnits = unitsT.empty() || unitsB.empty();
  135     DataPtr sliceT = p->readerT->getScaledDataSlice(varName, unLimDimPos);
  136     DataPtr sliceB;
  137     if (emptyUnits || unitsT == unitsB) {
  138         if (emptyUnits) {
  139             LOG4FIMEX(logger, Logger::WARN,
  140                       "no unit conversion for variable '" << varName << "': units '" << unitsT << "' in top and '" << unitsB << "' in base");
  141         }
  142         sliceB = p->interpolatedB->getScaledDataSlice(varName, unLimDimPos);
  143     } else {
  144         LOG4FIMEX(logger, Logger::INFO, "unit conversion for variable '" << varName << "' from '" << unitsB << "' in base to '" << unitsT << "' in top");
  145         sliceB = p->interpolatedB->getScaledDataSliceInUnit(varName, unitsT, unLimDimPos);
  146     }
  147 
  148     for (size_t i=0; i<sliceB->size(); ++i) {
  149       const double valueT = sliceT->getDouble(i);
  150       if (not mifi_isnan(valueT))
  151         sliceB->setValue(i, valueT);
  152     }
  153 
  154     double scale=1, offset=0;
  155     getScaleAndOffsetOf(varName, scale, offset);
  156     return sliceB->convertDataType(MIFI_UNDEFINED_D, 1, 0,
  157         cdm_->getVariable(varName).getDataType(),
  158         cdm_->getFillValue(varName), scale, offset);
  159 }
  160 
  161 // ########################################################################
  162 
  163 CDM CDMOverlayPrivate::init(int gridInterpolationMethod, bool keepOuterVariables)
  164 {
  165     string nameX, nameY;
  166     return makeMergedCDM(readerT, readerB, gridInterpolationMethod, interpolatedB, nameX, nameY, keepOuterVariables);
  167 }
  168 
  169 } // namespace MetNoFimex