Ignore:
Timestamp:
08/25/15 16:52:45 (9 years ago)
Author:
rlacroix
Message:

Add support for indexed output.

If the new field attribute "indexed_output" is set to true and a mask is defined (either at grid, domain or axis level), the indexed data will be outputed instead of the full data with missing values.

See http://cfconventions.org/Data/cf-conventions/cf-conventions-1.5/build/cf-conventions.html#compression-by-gathering for more information.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • XIOS/trunk/src/output/nc4_data_output.cpp

    r665 r676  
    741741     } 
    742742 
     743     //-------------------------------------------------------------- 
     744 
     745     void CNc4DataOutput::writeGridCompressed_(CGrid* grid) 
     746     { 
     747       if (grid->isScalarGrid() || grid->isWrittenCompressed(this->filename)) return; 
     748 
     749       try 
     750       { 
     751         CArray<bool,1> axisDomainOrder = grid->axis_domain_order; 
     752         std::vector<StdString> domainList = grid->getDomainList(); 
     753         std::vector<StdString> axisList   = grid->getAxisList(); 
     754         int numElement = axisDomainOrder.numElements(), idxDomain = 0, idxAxis = 0; 
     755 
     756         std::vector<StdString> dims; 
     757 
     758         if (grid->isCompressible()) 
     759         { 
     760           StdString varId = grid->getId() + "_points"; 
     761 
     762           int nbIndexes = (SuperClass::type == MULTI_FILE) ? grid->getNumberWrittenIndexes() : grid->getTotalNumberWrittenIndexes(); 
     763           SuperClassWriter::addDimension(varId, nbIndexes); 
     764 
     765           dims.push_back(varId); 
     766           SuperClassWriter::addVariable(varId, NC_INT, dims); 
     767 
     768           StdOStringStream compress; 
     769           for (int i = numElement - 1; i >= 0; --i) 
     770           { 
     771             if (axisDomainOrder(i)) 
     772             { 
     773               CDomain* domain = CDomain::get(domainList[domainList.size() - idxDomain - 1]); 
     774               StdString domId = !domain->name.isEmpty() ? domain->name.getValue() : domain->getId(); 
     775               StdString appendDomId  = singleDomain ? "" : "_" + domId; 
     776 
     777               switch (domain->type) 
     778               { 
     779                 case CDomain::type_attr::curvilinear: 
     780                   compress << "y" << appendDomId << " x" << appendDomId; 
     781                   break; 
     782                 case CDomain::type_attr::rectilinear: 
     783                   compress << "lat" << appendDomId << " lon" << appendDomId; 
     784                   break; 
     785                 case CDomain::type_attr::unstructured: 
     786                   compress << "cell" << appendDomId; 
     787                   break; 
     788               } 
     789               ++idxDomain; 
     790             } 
     791             else 
     792             { 
     793               CAxis* axis = CAxis::get(axisList[axisList.size() - idxAxis - 1]); 
     794               compress << (!axis->name.isEmpty() ? axis->name.getValue() : axis->getId()); 
     795               ++idxAxis; 
     796             } 
     797 
     798             if (i != 0) compress << ' '; 
     799           } 
     800           SuperClassWriter::addAttribute("compress", compress.str(), &varId); 
     801 
     802           grid->computeCompressedIndex(); 
     803 
     804           CArray<int, 1> indexes(grid->getNumberWrittenIndexes()); 
     805           std::map<int, CArray<size_t, 1> >::const_iterator it; 
     806           for (it = grid->outIndexFromClient.begin(); it != grid->outIndexFromClient.end(); ++it) 
     807           { 
     808             const CArray<size_t, 1> compressedIndexes = grid->compressedOutIndexFromClient[it->first]; 
     809             for (int i = 0; i < it->second.numElements(); i++) 
     810               indexes(compressedIndexes(i)) = it->second(i); 
     811           } 
     812 
     813           switch (SuperClass::type) 
     814           { 
     815             case (MULTI_FILE): 
     816             { 
     817               SuperClassWriter::writeData(indexes, varId, isCollective, 0); 
     818               break; 
     819             } 
     820             case (ONE_FILE): 
     821             { 
     822               if (grid->doGridHaveDataDistributed()) 
     823                 grid->getDistributionServer()->computeGlobalIndex(indexes); 
     824 
     825               std::vector<StdSize> start, count; 
     826               start.push_back(grid->getOffsetWrittenIndexes()); 
     827               count.push_back(grid->getNumberWrittenIndexes()); 
     828 
     829               SuperClassWriter::writeData(indexes, varId, isCollective, 0, &start, &count); 
     830               break; 
     831             } 
     832           } 
     833         } 
     834         else 
     835         { 
     836           for (int i = 0; i < numElement; ++i) 
     837           { 
     838             StdString varId, compress; 
     839             CArray<int, 1> indexes; 
     840             bool isDistributed; 
     841             StdSize nbIndexes, totalNbIndexes, offset; 
     842             int firstGlobalIndex; 
     843 
     844             if (axisDomainOrder(i)) 
     845             { 
     846               CDomain* domain = CDomain::get(domainList[idxDomain]); 
     847               if (!domain->isCompressible() 
     848                    || domain->type == CDomain::type_attr::unstructured 
     849                    || domain->isWrittenCompressed(this->filename)) 
     850                 continue; 
     851 
     852               StdString domId = !domain->name.isEmpty() ? domain->name.getValue() : domain->getId(); 
     853               StdString appendDomId  = singleDomain ? "" : "_" + domId; 
     854 
     855               varId = domId + "_points"; 
     856               switch (domain->type) 
     857               { 
     858                 case CDomain::type_attr::curvilinear: 
     859                   compress = "y" + appendDomId + " x" + appendDomId; 
     860                   break; 
     861                 case CDomain::type_attr::rectilinear: 
     862                   compress = "lat" + appendDomId + " lon" + appendDomId; 
     863                   break; 
     864               } 
     865 
     866               const std::vector<int>& indexesToWrite = domain->getIndexesToWrite(); 
     867               indexes.resize(indexesToWrite.size()); 
     868               for (int n = 0; n < indexes.numElements(); ++n) 
     869                 indexes(n) = indexesToWrite[n]; 
     870 
     871               isDistributed = domain->isDistributed(); 
     872               nbIndexes = domain->getNumberWrittenIndexes(); 
     873               totalNbIndexes = domain->getTotalNumberWrittenIndexes(); 
     874               offset = domain->getOffsetWrittenIndexes(); 
     875               firstGlobalIndex = domain->ibegin + domain->jbegin * domain->ni_glo; 
     876 
     877               domain->addRelFileCompressed(this->filename); 
     878               ++idxDomain; 
     879             } 
     880             else 
     881             { 
     882               CAxis* axis = CAxis::get(axisList[idxAxis]); 
     883               if (!axis->isCompressible() || axis->isWrittenCompressed(this->filename)) 
     884                 continue; 
     885 
     886               StdString axisId = !axis->name.isEmpty() ? axis->name.getValue() : axis->getId(); 
     887               varId = axisId + "_points"; 
     888               compress = axisId; 
     889 
     890               const std::vector<int>& indexesToWrite = axis->getIndexesToWrite(); 
     891               indexes.resize(indexesToWrite.size()); 
     892               for (int n = 0; n < indexes.numElements(); ++n) 
     893                 indexes(n) = indexesToWrite[n]; 
     894 
     895               isDistributed = axis->isDistributed(); 
     896               nbIndexes = axis->getNumberWrittenIndexes(); 
     897               totalNbIndexes = axis->getTotalNumberWrittenIndexes(); 
     898               offset = axis->getOffsetWrittenIndexes(); 
     899               firstGlobalIndex = axis->begin; 
     900 
     901               axis->addRelFileCompressed(this->filename); 
     902               ++idxAxis; 
     903             } 
     904 
     905             if (!varId.empty()) 
     906             { 
     907               SuperClassWriter::addDimension(varId, (SuperClass::type == MULTI_FILE) ? nbIndexes : totalNbIndexes); 
     908 
     909               dims.clear(); 
     910               dims.push_back(varId); 
     911               SuperClassWriter::addVariable(varId, NC_INT, dims); 
     912 
     913               SuperClassWriter::addAttribute("compress", compress, &varId); 
     914 
     915               switch (SuperClass::type) 
     916               { 
     917                 case (MULTI_FILE): 
     918                 { 
     919                   indexes -= firstGlobalIndex; 
     920                   SuperClassWriter::writeData(indexes, varId, isCollective, 0); 
     921                   break; 
     922                 } 
     923                 case (ONE_FILE): 
     924                 { 
     925                   std::vector<StdSize> start, count; 
     926                   start.push_back(offset); 
     927                   count.push_back(nbIndexes); 
     928 
     929                   SuperClassWriter::writeData(indexes, varId, isCollective, 0, &start, &count); 
     930                   break; 
     931                 } 
     932               } 
     933             } 
     934           } 
     935 
     936           if (!dims.empty()) 
     937             grid->computeCompressedIndex(); 
     938         } 
     939 
     940         grid->addRelFileCompressed(this->filename); 
     941       } 
     942       catch (CNetCdfException& e) 
     943       { 
     944         StdString msg("On writing compressed grid : "); 
     945         msg.append(grid->getId()); msg.append("\n"); 
     946         msg.append("In the context : "); 
     947         CContext* context = CContext::getCurrent(); 
     948         msg.append(context->getId()); msg.append("\n"); 
     949         msg.append(e.what()); 
     950         ERROR("CNc4DataOutput::writeGridCompressed_(CGrid* grid)", << msg); 
     951       } 
     952     } 
     953 
     954     //-------------------------------------------------------------- 
     955 
    743956     void CNc4DataOutput::writeTimeDimension_(void) 
    744957     { 
     
    757970       } 
    758971     } 
     972 
    759973      //-------------------------------------------------------------- 
    760974 
     
    779993         bool hasArea = false; 
    780994         StdString cellMeasures = "area:"; 
     995         bool compressedOutput = !field->indexed_output.isEmpty() && field->indexed_output; 
    781996 
    782997         for (int i = 0; i < numElement; ++i) 
     
    7851000           { 
    7861001             CDomain* domain = CDomain::get(domainList[idxDomain]); 
    787              StdString domid = (!domain->name.isEmpty()) 
    788                                  ? domain->name.getValue() : domain->getId(); 
    789              StdString appendDomid  = (singleDomain) ? "" : "_"+domid ; 
     1002             StdString domId = !domain->name.isEmpty() ? domain->name.getValue() : domain->getId(); 
     1003             StdString appendDomId  = singleDomain ? "" : "_" + domId ; 
     1004 
     1005             if (compressedOutput && domain->isCompressible() && domain->type != CDomain::type_attr::unstructured) 
     1006             { 
     1007               dimIdList.push_back(domId + "_points"); 
     1008               field->setUseCompressedOutput(); 
     1009             } 
     1010 
    7901011             switch (domain->type) 
    7911012             { 
    792                case CDomain::type_attr::curvilinear : 
    793                  dimXid     = StdString("x").append(appendDomid); 
     1013               case CDomain::type_attr::curvilinear: 
     1014                 if (!compressedOutput || !domain->isCompressible()) 
     1015                 { 
     1016                   dimXid     = StdString("x").append(appendDomId); 
     1017                   dimIdList.push_back(dimXid); 
     1018                   dimYid     = StdString("y").append(appendDomId); 
     1019                   dimIdList.push_back(dimYid); 
     1020                 } 
     1021                 dimCoordList.push_back(StdString("nav_lon").append(appendDomId)); 
     1022                 dimCoordList.push_back(StdString("nav_lat").append(appendDomId)); 
     1023                 break ; 
     1024               case CDomain::type_attr::rectilinear: 
     1025                 if (!compressedOutput || !domain->isCompressible()) 
     1026                 { 
     1027                   dimXid     = StdString("lon").append(appendDomId); 
     1028                   dimIdList.push_back(dimXid); 
     1029                   dimYid     = StdString("lat").append(appendDomId); 
     1030                   dimIdList.push_back(dimYid); 
     1031                 } 
     1032                 break ; 
     1033               case CDomain::type_attr::unstructured: 
     1034                 dimXid     = StdString("cell").append(appendDomId); 
    7941035                 dimIdList.push_back(dimXid); 
    795                  dimYid     = StdString("y").append(appendDomid); 
    796                  dimIdList.push_back(dimYid); 
    797                  dimCoordList.push_back(StdString("nav_lon").append(appendDomid)); 
    798                  dimCoordList.push_back(StdString("nav_lat").append(appendDomid)); 
     1036                 dimCoordList.push_back(StdString("lon").append(appendDomId)); 
     1037                 dimCoordList.push_back(StdString("lat").append(appendDomId)); 
    7991038                 break ; 
    800                case CDomain::type_attr::rectilinear : 
    801                  dimXid     = StdString("lon").append(appendDomid); 
    802                  dimIdList.push_back(dimXid); 
    803                  dimYid     = StdString("lat").append(appendDomid); 
    804                  dimIdList.push_back(dimYid); 
    805                  break ; 
    806                case CDomain::type_attr::unstructured : 
    807                  dimXid     = StdString("cell").append(appendDomid); 
    808                  dimIdList.push_back(dimXid); 
    809                  dimCoordList.push_back(StdString("lon").append(appendDomid)); 
    810                  dimCoordList.push_back(StdString("lat").append(appendDomid)); 
    811                  break ; 
    812             } 
    813             if (domain->hasArea) 
    814             { 
    815               hasArea = true; 
    816               cellMeasures += " area" + appendDomid; 
    817             } 
    818             ++idxDomain; 
     1039             } 
     1040             if (domain->hasArea) 
     1041             { 
     1042               hasArea = true; 
     1043               cellMeasures += " area" + appendDomId; 
     1044             } 
     1045             ++idxDomain; 
    8191046           } 
    8201047           else 
    8211048           { 
    8221049             CAxis* axis = CAxis::get(axisList[idxAxis]); 
    823              StdString axisid = (!axis->name.isEmpty()) 
    824                                 ? axis->name.getValue() : axis->getId(); 
    825              dimIdList.push_back(axisid); 
    826              dimCoordList.push_back(axisid); 
    827             ++idxAxis; 
     1050             StdString axisId = !axis->name.isEmpty() ? axis->name.getValue() : axis->getId(); 
     1051 
     1052             if (compressedOutput && axis->isCompressible()) 
     1053             { 
     1054               dimIdList.push_back(axisId + "_points"); 
     1055               field->setUseCompressedOutput(); 
     1056             } 
     1057             else 
     1058               dimIdList.push_back(axisId); 
     1059 
     1060             dimCoordList.push_back(axisId); 
     1061             ++idxAxis; 
    8281062           } 
    8291063         } 
     
    8671101         } 
    8681102 
    869          while (!dimIdList.empty()) 
    870          { 
    871            dims.push_back(dimIdList.back()); 
    872            dimIdList.pop_back(); 
     1103         if (compressedOutput && grid->isCompressible()) 
     1104         { 
     1105           dims.push_back(grid->getId() + "_points"); 
     1106           field->setUseCompressedOutput(); 
     1107         } 
     1108         else 
     1109         { 
     1110           while (!dimIdList.empty()) 
     1111           { 
     1112             dims.push_back(dimIdList.back()); 
     1113             dimIdList.pop_back(); 
     1114           } 
    8731115         } 
    8741116 
     
    12111453         try 
    12121454         { 
    1213            CArray<double,1> fieldData(grid->getWrittenDataSize()); 
     1455           size_t writtenSize; 
     1456           if (field->getUseCompressedOutput()) 
     1457             writtenSize = grid->getNumberWrittenIndexes(); 
     1458           else 
     1459             writtenSize = grid->getWrittenDataSize(); 
     1460 
     1461           CArray<double,1> fieldData(writtenSize); 
    12141462           if (!field->default_value.isEmpty()) fieldData = field->default_value; 
    1215            field->outputField(fieldData); 
     1463 
     1464           if (field->getUseCompressedOutput()) 
     1465             field->outputCompressedField(fieldData); 
     1466           else 
     1467             field->outputField(fieldData); 
     1468 
    12161469           if (!field->prec.isEmpty() && field->prec==2) fieldData=round(fieldData) ; 
    12171470 
     
    12321485              case (ONE_FILE) : 
    12331486              { 
    1234                 std::vector<int> nZoomBeginGlobal = grid->getDistributionServer()->getZoomBeginGlobal(); 
    1235                 std::vector<int> nZoomBeginServer = grid->getDistributionServer()->getZoomBeginServer(); 
    1236                 std::vector<int> nZoomSizeServer  = grid->getDistributionServer()->getZoomSizeServer(); 
    1237  
    1238                 int ssize = nZoomBeginGlobal.size(); 
    1239  
    1240                 std::vector<StdSize> start(ssize) ; 
    1241                 std::vector<StdSize> count(ssize) ; 
    1242  
    1243                 for (int i = 0; i < ssize; ++i) 
     1487                const std::vector<int>& nZoomBeginGlobal = grid->getDistributionServer()->getZoomBeginGlobal(); 
     1488                const std::vector<int>& nZoomBeginServer = grid->getDistributionServer()->getZoomBeginServer(); 
     1489                const std::vector<int>& nZoomSizeServer  = grid->getDistributionServer()->getZoomSizeServer(); 
     1490 
     1491                std::vector<StdSize> start, count; 
     1492 
     1493                if (field->getUseCompressedOutput()) 
    12441494                { 
    1245                   start[i] = nZoomBeginServer[ssize-i-1] - nZoomBeginGlobal[ssize-i-1]; 
    1246                   count[i] = nZoomSizeServer[ssize-i-1]; 
     1495                  if (grid->isCompressible()) 
     1496                  { 
     1497                    start.push_back(grid->getOffsetWrittenIndexes()); 
     1498                    count.push_back(grid->getNumberWrittenIndexes()); 
     1499                  } 
     1500                  else 
     1501                  { 
     1502                    CArray<bool,1> axisDomainOrder = grid->axis_domain_order; 
     1503                    std::vector<StdString> domainList = grid->getDomainList(); 
     1504                    std::vector<StdString> axisList   = grid->getAxisList(); 
     1505                    int numElement = axisDomainOrder.numElements(); 
     1506                    int idxDomain = domainList.size() - 1, idxAxis = axisList.size() - 1; 
     1507                    int idx = nZoomBeginGlobal.size() - 1; 
     1508 
     1509                    start.reserve(nZoomBeginGlobal.size()); 
     1510                    count.reserve(nZoomBeginGlobal.size()); 
     1511 
     1512 
     1513                    for (int i = numElement - 1; i >= 0; --i) 
     1514                    { 
     1515                      if (axisDomainOrder(i)) 
     1516                      { 
     1517                        CDomain* domain = CDomain::get(domainList[idxDomain]); 
     1518 
     1519                        if (domain->isCompressible()) 
     1520                        { 
     1521                          start.push_back(domain->getOffsetWrittenIndexes()); 
     1522                          count.push_back(domain->getNumberWrittenIndexes()); 
     1523                        } 
     1524                        else 
     1525                        { 
     1526                          start.push_back(nZoomBeginServer[idx] - nZoomBeginGlobal[idx]); 
     1527                          count.push_back(nZoomSizeServer[idx]); 
     1528                          start.push_back(nZoomBeginServer[idx - 1] - nZoomBeginGlobal[idx - 1]); 
     1529                          count.push_back(nZoomSizeServer[idx - 1]); 
     1530                        } 
     1531 
     1532                        --idxDomain; 
     1533                        idx -= 2; 
     1534                      } 
     1535                      else 
     1536                      { 
     1537                        CAxis* axis = CAxis::get(axisList[idxAxis]); 
     1538 
     1539                        if (axis->isCompressible()) 
     1540                        { 
     1541                          start.push_back(axis->getOffsetWrittenIndexes()); 
     1542                          count.push_back(axis->getNumberWrittenIndexes()); 
     1543                        } 
     1544                        else 
     1545                        { 
     1546                          start.push_back(nZoomBeginServer[idx] - nZoomBeginGlobal[idx]); 
     1547                          count.push_back(nZoomSizeServer[idx]); 
     1548                        } 
     1549 
     1550                        --idxAxis; 
     1551                        --idx; 
     1552                      } 
     1553                    } 
     1554                  } 
    12471555                } 
    1248  
    1249                 SuperClassWriter::writeData(fieldData, fieldid, isCollective, field->getNStep()-1,&start,&count ); 
     1556                else 
     1557                { 
     1558                  int ssize = nZoomBeginGlobal.size(); 
     1559 
     1560                  start.resize(ssize); 
     1561                  count.resize(ssize); 
     1562 
     1563                  for (int i = 0; i < ssize; ++i) 
     1564                  { 
     1565                    start[i] = nZoomBeginServer[ssize - i - 1] - nZoomBeginGlobal[ssize - i - 1]; 
     1566                    count[i] = nZoomSizeServer[ssize - i - 1]; 
     1567                  } 
     1568                } 
     1569 
     1570                SuperClassWriter::writeData(fieldData, fieldid, isCollective, field->getNStep() - 1, &start, &count); 
    12501571                if (wtime) 
    12511572                { 
    1252                   SuperClassWriter::writeTimeAxisData(time_data, timeAxisId, isCollective, field->getNStep()-1,isRoot ); 
    1253                   SuperClassWriter::writeTimeAxisData(time_counter, string("time_counter"), isCollective, field->getNStep()-1,isRoot ); 
    1254                   SuperClassWriter::writeTimeAxisData(time_counter_bound, timeBoundId, isCollective, field->getNStep()-1, isRoot ); 
    1255                   SuperClassWriter::writeTimeAxisData(time_data_bound, timeAxisBoundId, isCollective, field->getNStep()-1, isRoot); 
     1573                  SuperClassWriter::writeTimeAxisData(time_data, timeAxisId, isCollective, field->getNStep() - 1, isRoot); 
     1574                  SuperClassWriter::writeTimeAxisData(time_counter, string("time_counter"), isCollective, field->getNStep() - 1, isRoot); 
     1575                  SuperClassWriter::writeTimeAxisData(time_counter_bound, timeBoundId, isCollective, field->getNStep() - 1, isRoot); 
     1576                  SuperClassWriter::writeTimeAxisData(time_data_bound, timeAxisBoundId, isCollective, field->getNStep() - 1, isRoot); 
    12561577                } 
    12571578 
Note: See TracChangeset for help on using the changeset viewer.