/** * Sets the surface grids based on a ncepNam (surface only!) forecast. * @param input The WindNinjaInputs for misc. info. * @param airGrid The air temperature grid to be filled. * @param cloudGrid The cloud cover grid to be filled. * @param uGrid The u velocity grid to be filled. * @param vGrid The v velocity grid to be filled. * @param wGrid The w velocity grid to be filled (filled with zeros here?). */ void genericSurfInitialization::setSurfaceGrids( WindNinjaInputs &input, AsciiGrid<double> &airGrid, AsciiGrid<double> &cloudGrid, AsciiGrid<double> &uGrid, AsciiGrid<double> &vGrid, AsciiGrid<double> &wGrid ) { int bandNum = -1; //get time list std::vector<boost::local_time::local_date_time> timeList( getTimeList(input.ninjaTimeZone) ); //Search time list for our time to identify our band number for cloud/speed/dir for(unsigned int i = 0; i < timeList.size(); i++) { if(input.ninjaTime == timeList[i]) { bandNum = i + 1; break; } } if(bandNum < 0) throw std::runtime_error("Could not match ninjaTime with a band number in the forecast file."); //get some info from the nam file in input //Acquire a lock to protect the non-thread safe netCDF library #ifdef _OPENMP omp_guard netCDF_guard(netCDF_lock); #endif GDALDataset* poDS; //attempt to grab the projection from the dem? //check for member prjString first std::string dstWkt; dstWkt = input.dem.prjString; if ( dstWkt.empty() ) { //try to open original poDS = (GDALDataset*)GDALOpen( input.dem.fileName.c_str(), GA_ReadOnly ); if( poDS == NULL ) { CPLDebug( "ncepNdfdInitialization::setSurfaceGrids()", "Bad projection reference" ); //throw(); } dstWkt = poDS->GetProjectionRef(); if( dstWkt.empty() ) { CPLDebug( "ncepNdfdInitialization::setSurfaceGrids()", "Bad projection reference" ); //throw() } GDALClose((GDALDatasetH) poDS ); } poDS = (GDALDataset*)GDALOpen( input.forecastFilename.c_str(), GA_ReadOnly ); if( poDS == NULL ) { CPLDebug( "ncepNdfdInitialization::setSurfaceGrids()", "Bad forecast file" ); } else GDALClose((GDALDatasetH) poDS ); // open ds one by one and warp, then write to grid GDALDataset *srcDS, *wrpDS; std::string temp; std::string srcWkt; std::vector<std::string> varList = getVariableList(); /* * Set the initial values in the warped dataset to no data */ GDALWarpOptions* psWarpOptions; for( unsigned int i = 0;i < varList.size();i++ ) { temp = "NETCDF:" + input.forecastFilename + ":" + varList[i]; srcDS = (GDALDataset*)GDALOpenShared( temp.c_str(), GA_ReadOnly ); if( srcDS == NULL ) { CPLDebug( "ncepNdfdInitialization::setSurfaceGrids()", "Bad forecast file" ); } srcWkt = srcDS->GetProjectionRef(); if( srcWkt.empty() ) { CPLDebug( "ncepNdfdInitialization::setSurfaceGrids()", "Bad forecast file" ); //throw } /* * Grab the first band to get the nodata value for the variable, * assume all bands have the same ndv */ GDALRasterBand *poBand = srcDS->GetRasterBand( 1 ); int pbSuccess; double dfNoData = poBand->GetNoDataValue( &pbSuccess ); psWarpOptions = GDALCreateWarpOptions(); int nBandCount = srcDS->GetRasterCount(); psWarpOptions->nBandCount = nBandCount; psWarpOptions->padfDstNoDataReal = (double*) CPLMalloc( sizeof( double ) * nBandCount ); psWarpOptions->padfDstNoDataImag = (double*) CPLMalloc( sizeof( double ) * nBandCount ); for( int b = 0;b < srcDS->GetRasterCount();b++ ) { psWarpOptions->padfDstNoDataReal[b] = dfNoData; psWarpOptions->padfDstNoDataImag[b] = dfNoData; } if( pbSuccess == false ) dfNoData = -9999.0; psWarpOptions->papszWarpOptions = CSLSetNameValue( psWarpOptions->papszWarpOptions, "INIT_DEST", "NO_DATA" ); wrpDS = (GDALDataset*) GDALAutoCreateWarpedVRT( srcDS, srcWkt.c_str(), dstWkt.c_str(), GRA_NearestNeighbour, 1.0, psWarpOptions ); if( varList[i] == "Temperature_height_above_ground" ) { GDAL2AsciiGrid( wrpDS, bandNum, airGrid ); if( CPLIsNan( dfNoData ) ) { airGrid.set_noDataValue(-9999.0); airGrid.replaceNan( -9999.0 ); } } else if( varList[i] == "V-component_of_wind_height_above_ground" ) { GDAL2AsciiGrid( wrpDS, bandNum, vGrid ); if( CPLIsNan( dfNoData ) ) { vGrid.set_noDataValue(-9999.0); vGrid.replaceNan( -9999.0 ); } } else if( varList[i] == "U-component_of_wind_height_above_ground" ) { GDAL2AsciiGrid( wrpDS, bandNum, uGrid ); if( CPLIsNan( dfNoData ) ) { uGrid.set_noDataValue(-9999.0); uGrid.replaceNan( -9999.0 ); } } else if( varList[i] == "Total_cloud_cover" ) { GDAL2AsciiGrid( wrpDS, bandNum, cloudGrid ); if( CPLIsNan( dfNoData ) ) { cloudGrid.set_noDataValue(-9999.0); cloudGrid.replaceNan( -9999.0 ); } } GDALDestroyWarpOptions( psWarpOptions ); GDALClose((GDALDatasetH) srcDS ); GDALClose((GDALDatasetH) wrpDS ); } cloudGrid /= 100.0; wGrid.set_headerData( uGrid ); wGrid = 0.0; }
int QgsRasterCalculator::processCalculation( QProgressDialog* p ) { //prepare search string / tree QString errorString; QgsRasterCalcNode* calcNode = QgsRasterCalcNode::parseRasterCalcString( mFormulaString, errorString ); if ( !calcNode ) { //error } double targetGeoTransform[6]; outputGeoTransform( targetGeoTransform ); //open all input rasters for reading QMap< QString, GDALRasterBandH > mInputRasterBands; //raster references and corresponding scanline data QMap< QString, QgsRasterMatrix* > inputScanLineData; //stores raster references and corresponding scanline data QVector< GDALDatasetH > mInputDatasets; //raster references and corresponding dataset QVector<QgsRasterCalculatorEntry>::const_iterator it = mRasterEntries.constBegin(); for ( ; it != mRasterEntries.constEnd(); ++it ) { if ( !it->raster ) // no raster layer in entry { return 2; } GDALDatasetH inputDataset = GDALOpen( it->raster->source().toLocal8Bit().data(), GA_ReadOnly ); if ( inputDataset == NULL ) { return 2; } //check if the input dataset is south up or rotated. If yes, use GDALAutoCreateWarpedVRT to create a north up raster double inputGeoTransform[6]; if ( GDALGetGeoTransform( inputDataset, inputGeoTransform ) == CE_None && ( inputGeoTransform[1] < 0.0 || inputGeoTransform[2] != 0.0 || inputGeoTransform[4] != 0.0 || inputGeoTransform[5] > 0.0 ) ) { GDALDatasetH vDataset = GDALAutoCreateWarpedVRT( inputDataset, NULL, NULL, GRA_NearestNeighbour, 0.2, NULL ); mInputDatasets.push_back( vDataset ); mInputDatasets.push_back( inputDataset ); inputDataset = vDataset; } else { mInputDatasets.push_back( inputDataset ); } GDALRasterBandH inputRasterBand = GDALGetRasterBand( inputDataset, it->bandNumber ); if ( inputRasterBand == NULL ) { return 2; } int nodataSuccess; double nodataValue = GDALGetRasterNoDataValue( inputRasterBand, &nodataSuccess ); mInputRasterBands.insert( it->ref, inputRasterBand ); inputScanLineData.insert( it->ref, new QgsRasterMatrix( mNumOutputColumns, 1, new float[mNumOutputColumns], nodataValue ) ); } //open output dataset for writing GDALDriverH outputDriver = openOutputDriver(); if ( outputDriver == NULL ) { return 1; } GDALDatasetH outputDataset = openOutputFile( outputDriver ); GDALRasterBandH outputRasterBand = GDALGetRasterBand( outputDataset, 1 ); float outputNodataValue = -FLT_MAX; GDALSetRasterNoDataValue( outputRasterBand, outputNodataValue ); float* resultScanLine = ( float * ) CPLMalloc( sizeof( float ) * mNumOutputColumns ); if ( p ) { p->setMaximum( mNumOutputRows ); } QgsRasterMatrix resultMatrix; //read / write line by line for ( int i = 0; i < mNumOutputRows; ++i ) { if ( p ) { p->setValue( i ); } if ( p && p->wasCanceled() ) { break; } //fill buffers QMap< QString, QgsRasterMatrix* >::iterator bufferIt = inputScanLineData.begin(); for ( ; bufferIt != inputScanLineData.end(); ++bufferIt ) { double sourceTransformation[6]; GDALRasterBandH sourceRasterBand = mInputRasterBands[bufferIt.key()]; GDALGetGeoTransform( GDALGetBandDataset( sourceRasterBand ), sourceTransformation ); //the function readRasterPart calls GDALRasterIO (and ev. does some conversion if raster transformations are not the same) readRasterPart( targetGeoTransform, 0, i, mNumOutputColumns, 1, sourceTransformation, sourceRasterBand, bufferIt.value()->data() ); } if ( calcNode->calculate( inputScanLineData, resultMatrix ) ) { bool resultIsNumber = resultMatrix.isNumber(); float* calcData; if ( resultIsNumber ) //scalar result. Insert number for every pixel { calcData = new float[mNumOutputColumns]; for ( int j = 0; j < mNumOutputColumns; ++j ) { calcData[j] = resultMatrix.number(); } } else //result is real matrix { calcData = resultMatrix.data(); } //replace all matrix nodata values with output nodatas for ( int j = 0; j < mNumOutputColumns; ++j ) { if ( calcData[j] == resultMatrix.nodataValue() ) { calcData[j] = outputNodataValue; } } //write scanline to the dataset if ( GDALRasterIO( outputRasterBand, GF_Write, 0, i, mNumOutputColumns, 1, calcData, mNumOutputColumns, 1, GDT_Float32, 0, 0 ) != CE_None ) { qWarning( "RasterIO error!" ); } if ( resultIsNumber ) { delete[] calcData; } } } if ( p ) { p->setValue( mNumOutputRows ); } //close datasets and release memory delete calcNode; QMap< QString, QgsRasterMatrix* >::iterator bufferIt = inputScanLineData.begin(); for ( ; bufferIt != inputScanLineData.end(); ++bufferIt ) { delete bufferIt.value(); } inputScanLineData.clear(); QVector< GDALDatasetH >::iterator datasetIt = mInputDatasets.begin(); for ( ; datasetIt != mInputDatasets.end(); ++ datasetIt ) { GDALClose( *datasetIt ); } if ( p && p->wasCanceled() ) { //delete the dataset without closing (because it is faster) GDALDeleteDataset( outputDriver, mOutputFile.toLocal8Bit().data() ); return 3; } GDALClose( outputDataset ); CPLFree( resultScanLine ); return 0; }
/** * Sets the surface grids based on a ncep HRRR (surface only!) forecast. * @param input The WindNinjaInputs for misc. info. * @param airGrid The air temperature grid to be filled. * @param cloudGrid The cloud cover grid to be filled. * @param uGrid The u velocity grid to be filled. * @param vGrid The v velocity grid to be filled. * @param wGrid The w velocity grid to be filled (filled with zeros here?). */ void ncepHrrrSurfInitialization::setSurfaceGrids( WindNinjaInputs &input, AsciiGrid<double> &airGrid, AsciiGrid<double> &cloudGrid, AsciiGrid<double> &uGrid, AsciiGrid<double> &vGrid, AsciiGrid<double> &wGrid ) { int bandNum = -1; GDALDataset *srcDS; srcDS = (GDALDataset*)GDALOpenShared( input.forecastFilename.c_str(), GA_ReadOnly ); if( srcDS == NULL ) { CPLDebug( "ncepHRRRSurfaceInitialization::identify()", "Bad forecast file" ); } GDALRasterBand *poBand; const char *gc; //get time list std::vector<boost::local_time::local_date_time> timeList( getTimeList( input.ninjaTimeZone ) ); //Search time list for our time to identify our band number for cloud/speed/dir //Right now, just one time step per file std::vector<int> bandList; for(unsigned int i = 0; i < timeList.size(); i++) { if(input.ninjaTime == timeList[i]) { for(unsigned int j = 1; j < srcDS->GetRasterCount(); j++) { poBand = srcDS->GetRasterBand( j ); gc = poBand->GetMetadataItem( "GRIB_COMMENT" ); std::string bandName( gc ); if( bandName.find( "Temperature [K]" ) != bandName.npos ){ gc = poBand->GetMetadataItem( "GRIB_SHORT_NAME" ); std::string bandName( gc ); if( bandName.find( "2-HTGL" ) != bandName.npos ){ bandList.push_back( j ); // 2t break; } } } for(unsigned int j = 1; j < srcDS->GetRasterCount(); j++) { poBand = srcDS->GetRasterBand( j ); gc = poBand->GetMetadataItem( "GRIB_COMMENT" ); std::string bandName( gc ); if( bandName.find( "v-component of wind [m/s]" ) != bandName.npos ){ gc = poBand->GetMetadataItem( "GRIB_SHORT_NAME" ); std::string bandName( gc ); if( bandName.find( "10-HTGL" ) != bandName.npos ){ bandList.push_back( j ); // 10v break; } } } for(unsigned int j = 1; j < srcDS->GetRasterCount(); j++) { poBand = srcDS->GetRasterBand( j ); gc = poBand->GetMetadataItem( "GRIB_COMMENT" ); std::string bandName( gc ); if( bandName.find( "u-component of wind [m/s]" ) != bandName.npos ){ gc = poBand->GetMetadataItem( "GRIB_SHORT_NAME" ); std::string bandName( gc ); if( bandName.find( "10-HTGL" ) != bandName.npos ){ bandList.push_back( j ); // 10u break; } } } for(unsigned int j = 1; j < srcDS->GetRasterCount(); j++) { poBand = srcDS->GetRasterBand( j ); gc = poBand->GetMetadataItem( "GRIB_COMMENT" ); std::string bandName( gc ); if( bandName.find( "Total cloud cover [%]" ) != bandName.npos ){ gc = poBand->GetMetadataItem( "GRIB_SHORT_NAME" ); std::string bandName( gc ); if( bandName.find( "0-RESERVED" ) != bandName.npos ){ bandList.push_back( j ); // Total cloud cover in % break; } } } } } CPLDebug("HRRR", "2t: bandList[0] = %d", bandList[0]); CPLDebug("HRRR", "10v: bandList[1] = %d", bandList[1]); CPLDebug("HRRR", "10u: bandList[2] = %d", bandList[2]); CPLDebug("HRRR", "tcc: bandList[3] = %d", bandList[3]); if(bandList.size() < 4) throw std::runtime_error("Could not match ninjaTime with a band number in the forecast file."); std::string dstWkt; dstWkt = input.dem.prjString; GDALDataset *wrpDS; std::string temp; std::string srcWkt; GDALWarpOptions* psWarpOptions; srcWkt = srcDS->GetProjectionRef(); poBand = srcDS->GetRasterBand( 9 ); int pbSuccess; double dfNoData = poBand->GetNoDataValue( &pbSuccess ); psWarpOptions = GDALCreateWarpOptions(); int nBandCount = bandList.size(); psWarpOptions->nBandCount = nBandCount; psWarpOptions->panSrcBands = (int*) CPLMalloc( sizeof( int ) * nBandCount ); psWarpOptions->panDstBands = (int*) CPLMalloc( sizeof( int ) * nBandCount ); psWarpOptions->padfDstNoDataReal = (double*) CPLMalloc( sizeof( double ) * nBandCount ); psWarpOptions->padfDstNoDataImag = (double*) CPLMalloc( sizeof( double ) * nBandCount ); psWarpOptions->padfDstNoDataReal = (double*) CPLMalloc( sizeof( double ) * nBandCount ); psWarpOptions->padfDstNoDataImag = (double*) CPLMalloc( sizeof( double ) * nBandCount ); if( pbSuccess == false ) dfNoData = -9999.0; psWarpOptions->panSrcBands = (int *) CPLMalloc(sizeof(int) * psWarpOptions->nBandCount ); psWarpOptions->panSrcBands[0] = bandList[0]; psWarpOptions->panSrcBands[1] = bandList[1]; psWarpOptions->panSrcBands[2] = bandList[2]; psWarpOptions->panSrcBands[3] = bandList[3]; psWarpOptions->panDstBands = (int *) CPLMalloc(sizeof(int) * psWarpOptions->nBandCount ); psWarpOptions->panDstBands[0] = 1; psWarpOptions->panDstBands[1] = 2; psWarpOptions->panDstBands[2] = 3; psWarpOptions->panDstBands[3] = 4; wrpDS = (GDALDataset*) GDALAutoCreateWarpedVRT( srcDS, srcWkt.c_str(), dstWkt.c_str(), GRA_NearestNeighbour, 1.0, psWarpOptions ); std::vector<std::string> varList = getVariableList(); for( unsigned int i = 0; i < varList.size(); i++ ) { if( varList[i] == "2t" ) { GDAL2AsciiGrid( wrpDS, i+1, airGrid ); if( CPLIsNan( dfNoData ) ) { airGrid.set_noDataValue( -9999.0 ); airGrid.replaceNan( -9999.0 ); } } else if( varList[i] == "10v" ) { GDAL2AsciiGrid( wrpDS, i+1, vGrid ); if( CPLIsNan( dfNoData ) ) { vGrid.set_noDataValue( -9999.0 ); vGrid.replaceNan( -9999.0 ); } } else if( varList[i] == "10u" ) { GDAL2AsciiGrid( wrpDS, i+1, uGrid ); if( CPLIsNan( dfNoData ) ) { uGrid.set_noDataValue( -9999.0 ); uGrid.replaceNan( -9999.0 ); } } else if( varList[i] == "tcc" ) { GDAL2AsciiGrid( wrpDS, i+1, cloudGrid ); if( CPLIsNan( dfNoData ) ) { cloudGrid.set_noDataValue( -9999.0 ); cloudGrid.replaceNan( -9999.0 ); } } } //if there are any clouds set cloud fraction to 1, otherwise set to 0. for(int i = 0; i < cloudGrid.get_nRows(); i++){ for(int j = 0; j < cloudGrid.get_nCols(); j++){ if(cloudGrid(i,j) < 0.0){ cloudGrid(i,j) = 0.0; } else{ cloudGrid(i,j) = 1.0; } } } wGrid.set_headerData( uGrid ); wGrid = 0.0; airGrid += 273.15; GDALDestroyWarpOptions( psWarpOptions ); GDALClose((GDALDatasetH) srcDS ); GDALClose((GDALDatasetH) wrpDS ); }
// build out_ds static ERL_NIF_TERM gdal_nif_create_warped_vrtimg(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { ErlNifBinary filenameBin; if (!enif_inspect_iolist_as_binary(env, argv[0], &filenameBin) || (filenameBin.size >= FILENAME_LEN)) { return make_error_msg(env, "filename error, maybe too long"); } char imgfilename[FILENAME_LEN] = ""; size_t name_sz = filenameBin.size; memcpy(imgfilename, filenameBin.data, filenameBin.size); DEBUG("img filename: %s\r\n", imgfilename); int epsg_code; if (!enif_get_int(env, argv[1], &epsg_code)) { return enif_make_badarg(env); } GDALDatasetH in_ds = GDALOpenShared(imgfilename, GA_ReadOnly); if (in_ds == NULL) { const char* msg = "It is not possible to open the input file '%s'."; char errstr[name_sz + strlen(msg) + 1]; sprintf(errstr, msg, imgfilename); return make_error_msg(env, errstr); } gdal_img_handle* handle = enif_alloc_resource( gdal_img_RESOURCE, sizeof(gdal_img_handle)); memset(handle, '\0', sizeof(*handle)); handle->in_ds = in_ds; handle->options_resampling = "average"; handle->querysize = 256 * 4; handle->tilesize = 256; int rasterCount = GDALGetRasterCount(in_ds); if (rasterCount == 0) { const char* msg = "Input file '%s' has no raster band"; char errstr[name_sz + strlen(msg) + 1]; sprintf(errstr, msg, imgfilename); destroy_img_handle(handle); return make_error_msg(env, errstr); } GDALRasterBandH hBand = GDALGetRasterBand(in_ds, 1); if (GDALGetRasterColorTable(hBand) != NULL) { const char* msg = "Please convert this file to RGB/RGBA and run gdal2tiles on the result.\n" "From paletted file you can create RGBA file (temp.vrt) by:\n" "gdal_translate -of vrt -expand rgba %s temp.vrt\n" "then run this program: gdal2tiles temp.vrt"; char errstr[name_sz + strlen(msg) + 1]; sprintf(errstr, msg, imgfilename); destroy_img_handle(handle); return make_error_msg(env, errstr); } double padfTransform[6]; double errTransform[6] = {0.0, 1.0, 0.0, 0.0, 0.0, 1.0}; GDALGetGeoTransform(in_ds, padfTransform); if (0 == memcmp(padfTransform, errTransform, sizeof(errTransform)) && GDALGetGCPCount(in_ds) == 0) { destroy_img_handle(handle); return make_error_msg(env, "There is no georeference - " "neither affine transformation (worldfile) nor GCPs"); } const char* in_srs_wkt = GDALGetProjectionRef(in_ds); if (in_srs_wkt == NULL && GDALGetGCPCount(in_ds) != 0) { in_srs_wkt = GDALGetGCPProjection(in_ds); } char* out_srs_wkt = get_wkt_of(epsg_code); GDALDatasetH out_ds = GDALAutoCreateWarpedVRT(in_ds, in_srs_wkt, out_srs_wkt, GRA_NearestNeighbour, 0.0, NULL); handle->out_ds = out_ds; OGRFree(out_srs_wkt); handle->alphaBand = GDALGetMaskBand(GDALGetRasterBand(handle->out_ds, 1)); rasterCount = GDALGetRasterCount(handle->out_ds); unsigned int dataBandsCount; if (GDALGetMaskFlags(handle->alphaBand) & GMF_ALPHA || rasterCount == 4 || rasterCount == 2) { dataBandsCount = rasterCount - 1; } else { dataBandsCount = rasterCount; } handle->dataBandsCount = dataBandsCount; handle->tilebands = dataBandsCount + 1; ERL_NIF_TERM imginfo = get_imginfo(env, out_ds); if (enif_compare(ATOM_ERROR, imginfo) == 0) { destroy_img_handle(handle); return make_error_msg(env, "Georeference of the raster contains rotation or skew. " "Such raster is not supported. " "Please use gdalwarp first"); } ERL_NIF_TERM imgref = enif_make_resource(env, handle); enif_release_resource(handle); return enif_make_tuple3(env, ATOM_OK, imgref, imginfo); }
/** * Sets the surface grids based on a ncep HRRR (surface only!) forecast. * @param input The WindNinjaInputs for misc. info. * @param airGrid The air temperature grid to be filled. * @param cloudGrid The cloud cover grid to be filled. * @param uGrid The u velocity grid to be filled. * @param vGrid The v velocity grid to be filled. * @param wGrid The w velocity grid to be filled (filled with zeros here?). */ void ncepHrrrSurfInitialization::setSurfaceGrids( WindNinjaInputs &input, AsciiGrid<double> &airGrid, AsciiGrid<double> &cloudGrid, AsciiGrid<double> &uGrid, AsciiGrid<double> &vGrid, AsciiGrid<double> &wGrid ) { int bandNum = -1; GDALDataset *srcDS; srcDS = (GDALDataset*)GDALOpenShared( input.forecastFilename.c_str(), GA_ReadOnly ); if( srcDS == NULL ) { CPLDebug( "ncepHRRRSurfaceInitialization::identify()", "Bad forecast file" ); } GDALRasterBand *poBand = srcDS->GetRasterBand( 49 ); const char *gc; gc = poBand->GetMetadataItem( "GRIB_COMMENT" ); std::string bandName( gc ); //get time list std::vector<boost::local_time::local_date_time> timeList( getTimeList( input.ninjaTimeZone ) ); //Search time list for our time to identify our band number for cloud/speed/dir //Right now, just one time step per file std::vector<int> bandList; for(unsigned int i = 0; i < timeList.size(); i++) { if(input.ninjaTime == timeList[i]) { //check which HRRR format we have if( bandName.find( "u-component of wind [m/s]" ) == bandName.npos ){ //if band 49 isn't u10, it's either 2010 or 2012 format GDALRasterBand *poBand = srcDS->GetRasterBand( 50 ); const char *gc; gc = poBand->GetMetadataItem( "GRIB_COMMENT" ); std::string bandName( gc ); if( bandName.find( "u-component of wind [m/s]" ) == bandName.npos ){ //if band 50 isn't u10, it's the 2010 format bandList.push_back( 29 ); // 2t bandList.push_back( 34 ); // 10v bandList.push_back( 33 ); // 10u bandList.push_back( 52 ); // geopotential height at cloud top } else{ bandList.push_back( 45 ); // 2t bandList.push_back( 51 ); // 10v bandList.push_back( 50 ); // 10u bandList.push_back( 78 ); // geopotential height at cloud top } } else{ //otherwise, should be 2011 format, but check for u10 band to be sure poBand = srcDS->GetRasterBand( 44 ); gc = poBand->GetMetadataItem( "GRIB_COMMENT" ); bandName = gc; if( bandName.find( "u-component of wind [m/s]" ) == bandName.npos ){ CPLDebug( "ncepHRRRSurfaceInitialization::identify()", "Can't find the u-10 band in the forecast file." ); } bandList.push_back( 44 ); // 2t bandList.push_back( 50 ); // 10v bandList.push_back( 49 ); // 10u bandList.push_back( 73 ); // geopotential height at cloud top } break; } } if(bandList.size() < 4) throw std::runtime_error("Could not match ninjaTime with a band number in the forecast file."); std::string dstWkt; dstWkt = input.dem.prjString; GDALDataset *wrpDS; std::string temp; std::string srcWkt; GDALWarpOptions* psWarpOptions; srcWkt = srcDS->GetProjectionRef(); poBand = srcDS->GetRasterBand( 9 ); int pbSuccess; double dfNoData = poBand->GetNoDataValue( &pbSuccess ); psWarpOptions = GDALCreateWarpOptions(); int nBandCount = bandList.size(); psWarpOptions->nBandCount = nBandCount; psWarpOptions->panSrcBands = (int*) CPLMalloc( sizeof( int ) * nBandCount ); psWarpOptions->panDstBands = (int*) CPLMalloc( sizeof( int ) * nBandCount ); psWarpOptions->padfDstNoDataReal = (double*) CPLMalloc( sizeof( double ) * nBandCount ); psWarpOptions->padfDstNoDataImag = (double*) CPLMalloc( sizeof( double ) * nBandCount ); psWarpOptions->padfDstNoDataReal = (double*) CPLMalloc( sizeof( double ) * nBandCount ); psWarpOptions->padfDstNoDataImag = (double*) CPLMalloc( sizeof( double ) * nBandCount ); if( pbSuccess == false ) dfNoData = -9999.0; psWarpOptions->panSrcBands = (int *) CPLMalloc(sizeof(int) * psWarpOptions->nBandCount ); psWarpOptions->panSrcBands[0] = bandList[0]; psWarpOptions->panSrcBands[1] = bandList[1]; psWarpOptions->panSrcBands[2] = bandList[2]; psWarpOptions->panSrcBands[3] = bandList[3]; psWarpOptions->panDstBands = (int *) CPLMalloc(sizeof(int) * psWarpOptions->nBandCount ); psWarpOptions->panDstBands[0] = 1; psWarpOptions->panDstBands[1] = 2; psWarpOptions->panDstBands[2] = 3; psWarpOptions->panDstBands[3] = 4; wrpDS = (GDALDataset*) GDALAutoCreateWarpedVRT( srcDS, srcWkt.c_str(), dstWkt.c_str(), GRA_NearestNeighbour, 1.0, psWarpOptions ); std::vector<std::string> varList = getVariableList(); for( unsigned int i = 0; i < varList.size(); i++ ) { if( varList[i] == "2t" ) { GDAL2AsciiGrid( wrpDS, i+1, airGrid ); if( CPLIsNan( dfNoData ) ) { airGrid.set_noDataValue( -9999.0 ); airGrid.replaceNan( -9999.0 ); } } else if( varList[i] == "10v" ) { GDAL2AsciiGrid( wrpDS, i+1, vGrid ); if( CPLIsNan( dfNoData ) ) { vGrid.set_noDataValue( -9999.0 ); vGrid.replaceNan( -9999.0 ); } } else if( varList[i] == "10u" ) { GDAL2AsciiGrid( wrpDS, i+1, uGrid ); if( CPLIsNan( dfNoData ) ) { uGrid.set_noDataValue( -9999.0 ); uGrid.replaceNan( -9999.0 ); } } else if( varList[i] == "gh" ) { GDAL2AsciiGrid( wrpDS, i+1, cloudGrid ); if( CPLIsNan( dfNoData ) ) { cloudGrid.set_noDataValue( -9999.0 ); cloudGrid.replaceNan( -9999.0 ); } } } //if there are any clouds set cloud fraction to 1, otherwise set to 0. for(int i = 0; i < cloudGrid.get_nRows(); i++){ for(int j = 0; j < cloudGrid.get_nCols(); j++){ if(cloudGrid(i,j) < 0.0){ cloudGrid(i,j) = 0.0; } else{ cloudGrid(i,j) = 1.0; } } } wGrid.set_headerData( uGrid ); wGrid = 0.0; airGrid += 273.15; GDALDestroyWarpOptions( psWarpOptions ); GDALClose((GDALDatasetH) srcDS ); GDALClose((GDALDatasetH) wrpDS ); }