/** * 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 ); }
/** * 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; }
/** * 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 ); }