Example #1
0
void coverUnits::fromBaseUnits(AsciiGrid<double>& grid, std::string units)
{
    if(units == "fraction")
        //grid = grid;
    	return;
    else if(units == "percent")
        grid = grid * 100.0;
    else if(units == "canopy_categories")
    {

        for(int i=0; i<grid.get_nRows(); i++)
        {
            for(int j=0; j<grid.get_nCols(); j++)
            {
                if(grid(i,j) <= 0.0)
                    grid(i,j) = 0.0;
                else if(grid(i,j) <= 0.20)
                    grid(i,j) = 1.0;
                else if(grid(i,j) <= 0.50)
                    grid(i,j) = 2.0;
                else if(grid(i,j) <= 0.80)
                    grid(i,j) = 3.0;
                else if(grid(i,j) <= 1.0)
                    grid(i,j) = 4.0;
                else
                    throw std::domain_error("Cloud cover units in coverUnits::toBaseUnits() cannot be greater than 100 percent.");
            }
        }
    }else
        throw std::domain_error("Cloud cover units problem in coverUnits::fromBaseUnits().");
}
Example #2
0
void Dust::ComputePM10(AsciiGrid<double> &grid_ustar, AsciiGrid<double> &grid_dust)
{
    int i, j;
    const double ustar_threshold = 0.22;  //0.22 paper; //0.20 fall value //0.55 spring value //threshold friction velocity for burned soil
    const double K = 0.0007; //0.0066 fall value; //0.0003 spring value //PM10 release factor for burned soil, units are 1/m (0.004)
    const double rho_ = 1.164*1000000; //convert units from kg/m^3 to mg/m^3
    const double g = 9.81; //acceleration of gravity (m/s2)
    
    for(i=0;i<grid_dust.get_nRows();i++)
    {
        for(j=0;j<grid_dust.get_nCols();j++)
        {
            if(grid_dust(i,j) != grid_dust.get_noDataValue() && grid_ustar(i,j) > ustar_threshold)
            {
                grid_dust(i,j) = K*rho_/g*grid_ustar(i,j)*(grid_ustar(i,j)*grid_ustar(i,j) - ustar_threshold*ustar_threshold);
            }
            else if(grid_dust(i,j) != grid_dust.get_noDataValue() && grid_ustar(i,j) < ustar_threshold)
            {
                grid_dust(i,j) = 0.0;
            }
            else if(grid_dust(i,j) == grid_dust.get_noDataValue())
            {
                continue;
            }
            else
            {
                throw std::out_of_range("Range error in Dust::ComputePM10()");
            }
        }
    }
    //grid_dust.write_Grid("dustFileOut_", 2);
}
Example #3
0
void coverUnits::toBaseUnits(AsciiGrid<double>& grid, std::string units)
{
    if(units == "fraction")
        //grid = grid;
    	return;
    else if(units == "percent")
        grid = grid / 100.0;
    else if(units == "canopy_categories")
    {
        for(int i=0; i<grid.get_nRows(); i++)
        {
            for(int j=0; j<grid.get_nCols(); j++)
            {
                if(grid(i,j) == 1.0)
                    grid(i,j) = 0.1;
                else if(grid(i,j) == 2.0)
                    grid(i,j) = 0.35;
                else if(grid(i,j) == 3.0)
                    grid(i,j) = 0.65;
                else if(grid(i,j) == 4.0)
                    grid(i,j) = 0.90;
                else if(grid(i,j) == 0.0)
                    grid(i,j) = 0.0;
                else if(grid(i,j) == 99.0)
                    grid(i,j) = 0.0;
                else
                    throw std::domain_error("Cloud cover units problem in coverUnits::toBaseUnits().");
            }
        }


    }else
        throw std::domain_error("Cloud cover units problem in coverUnits::toBaseUnits().");
}
Example #4
0
void Dust::MakeGrid(WindNinjaInputs &input, AsciiGrid<double> &grid)
{
    /*------------------------------------------*/
    /* Open grid as a GDAL dataset              */
    /*------------------------------------------*/
    int nXSize = grid.get_nCols();
    int nYSize = grid.get_nRows();
    
    GDALDriverH hDriver = GDALGetDriverByName( "MEM" );
        
    GDALDatasetH hMemDS = GDALCreate(hDriver, "", nXSize, nYSize, 1, GDT_Float64, NULL);
    
    double *padfScanline;
    padfScanline = new double[nXSize];
    
    double adfGeoTransform[6];
    adfGeoTransform[0] = grid.get_xllCorner();
    adfGeoTransform[1] = grid.get_cellSize();
    adfGeoTransform[2] = 0;
    adfGeoTransform[3] = grid.get_yllCorner()+(grid.get_nRows()*grid.get_cellSize());
    adfGeoTransform[4] = 0;
    adfGeoTransform[5] = -grid.get_cellSize();
        
    char* pszDstWKT = (char*)grid.prjString.c_str();
    GDALSetProjection(hMemDS, pszDstWKT);
    GDALSetGeoTransform(hMemDS, adfGeoTransform);
        
    GDALRasterBandH hBand = GDALGetRasterBand( hMemDS, 1 );
        
    GDALSetRasterNoDataValue(hBand, -9999.0);        

    for(int i=nYSize-1; i>=0; i--)
    {
        for(int j=0; j<nXSize; j++)
        {  
            padfScanline[j] = grid.get_cellValue(nYSize-1-i, j);
        }
        GDALRasterIO(hBand, GF_Write, 0, i, nXSize, 1, padfScanline, nXSize,
                     1, GDT_Float64, 0, 0);
    }
    
    /*------------------------------------------*/
    /* Get the geometry info                    */
    /*------------------------------------------*/
    
    OGRDataSourceH hOGRDS = 0;
    hOGRDS = OGROpen(input.dustFilename.c_str(), FALSE, 0);
    if(hOGRDS == NULL)
    {
        throw std::runtime_error("Could not open the fire perimeter file '" +
              input.dustFilename + "' for reading.");
    }
    OGRLayer *poLayer;
    OGRFeature *poFeature;
    OGRGeometry *poGeo;
    
    poLayer = (OGRLayer*)OGR_DS_GetLayer(hOGRDS, 0);
    poLayer->ResetReading();
    poFeature = poLayer->GetNextFeature();
    poGeo = poFeature->GetGeometryRef();
    OGRGeometryH hPolygon = (OGRGeometryH) poGeo;


    /* -------------------------------------------------------------------- */
    /*  Check for same CRS in fire perimeter and DEM files                  */
    /* -------------------------------------------------------------------- */

    char *pszSrcWKT;
    OGRSpatialReference *poSrcSRS, oDstSRS;
    poSrcSRS = poLayer->GetSpatialRef(); //shapefile CRS
    poSrcSRS->exportToWkt( &pszSrcWKT );

    //printf("CRS of DEM is:\n %s\n", pszDstWKT);
    //printf("WKT CRS of .shp is:\n %s\n", pszSrcWKT);
    
    oDstSRS.importFromWkt( &pszDstWKT );
    
    char *pszDstProj4, *pszSrcProj4;
    oDstSRS.exportToProj4( &pszDstProj4 );
    poSrcSRS->exportToProj4( &pszSrcProj4 );
    
    //printf("proj4 of .shp is:\n %s\n", pszSrcProj4);
    //printf("proj4 of dem is:\n %s\n", pszDstProj4);
    
    /* -------------------------------------------------------------------- */
    /*  If the CRSs are not equal, convert shapefile CRS to DEM CRS         */
    /* -------------------------------------------------------------------- */

    GDALTransformerFunc pfnTransformer = NULL;
    if( !EQUAL( pszSrcProj4, pszDstProj4 ) ){ //tranform shp CRS to DEM CRS
        poGeo->transformTo(&oDstSRS);
    }
     
    /* -------------------------------------------------------------------- */
    /*  Rasterize the shapefile                                             */
    /* -------------------------------------------------------------------- */
    
    int nTargetBand = 1;
    double BurnValue = 1.0;
    CPLErr eErr;
    
    eErr = GDALRasterizeGeometries(hMemDS, 1, &nTargetBand, 1, &hPolygon, pfnTransformer, NULL, &BurnValue, NULL, NULL, NULL);
    if(eErr != CE_None)
    {
        throw std::runtime_error("Error in GDALRasterizeGeometies in Dust:MakeGrid().");
    }
    
    GDAL2AsciiGrid((GDALDataset*)hMemDS, 1, grid);
    
    /* -------------------------------------------------------------------- */
    /*   clean up                                                           */
    /* -------------------------------------------------------------------- */
    
    if( hMemDS != NULL ){
        GDALClose( hMemDS );
        hMemDS = NULL;
    }
    
    OGR_DS_Destroy(hOGRDS);
}
/**
* 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;
}
Example #6
0
bool GDAL2AsciiGrid( GDALDataset *poDS, int band, AsciiGrid<double> &grid )
{

    if( poDS == NULL )
	return false;
    //get some info from the ds

    int nXSize = poDS->GetRasterXSize();
    int nYSize = poDS->GetRasterYSize();

    double adfGeoTransform[6];
    poDS->GetGeoTransform( adfGeoTransform );

    //find llcorner
    double adfCorner[2];
    adfCorner[0] = adfGeoTransform[0];
    adfCorner[1] = adfGeoTransform[3] + ( nYSize * adfGeoTransform[5] );

    //check for non-square cells
    /*
    if( abs( adfGeoTransform[1] ) - abs( adfGeoTransform[5] ) > 0.0001 )
	CPLDebug( "GDAL2AsciiGrid", "Non-uniform cells" );
    */

    GDALRasterBand *poBand;
    poBand = poDS->GetRasterBand( band );

    //not used yet
    //GDALDataType eDataType = poBand->GetRasterDataType();

    int pbSuccess = 0;
    double dfNoData = poBand->GetNoDataValue( &pbSuccess );
    if( pbSuccess == false )
	dfNoData = -9999.0;

    //reallocate all memory and set header info
    grid.set_headerData( nXSize, nYSize,
			 adfCorner[0], adfCorner[1],
			 adfGeoTransform[1], dfNoData, dfNoData );
    //set the data
    double *padfScanline;
    padfScanline = new double[nXSize];
    for(int i = nYSize - 1;i >= 0;i--) {

	poBand->RasterIO(GF_Read, 0, i, nXSize, 1, padfScanline, nXSize, 1,
			 GDT_Float64, 0, 0);

	for(int j = 0;j < nXSize;j++) {
	    grid.set_cellValue(nYSize - 1 - i, j, padfScanline[j]);

	}
    }

    delete [] padfScanline;

    //try to get the projection info
    std::string prj = poDS->GetProjectionRef();
    grid.set_prjString( prj );

    return true;

    /**************************************************
     *
     * AsciiGrid is templated, but we don't support all
     * types, this could be sticky, or we could just
     * ignore it and try to fill in whatever they give
     * us and throw if we can't, maybe scale?
     *
     * GDT_Unknown 	Unknown or unspecified type
     * GDT_Byte 	Eight bit unsigned integer
     * GDT_UInt16 	Sixteen bit unsigned integer
     * GDT_Int16 	Sixteen bit signed integer
     * GDT_UInt32 	Thirty two bit unsigned integer
     * GDT_Int32 	Thirty two bit signed integer
     * GDT_Float32 	Thirty two bit floating point
     * GDT_Float64 	Sixty four bit floating point
     * GDT_CInt16 	Complex Int16
     * GDT_CInt32 	Complex Int32
     * GDT_CFloat32 	Complex Float32
     * GDT_CFloat64 	Complex Float64
     *
     **************************************************/

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