def main():

    ds_ofs = dsofs_latest()

    indexfile = f'docs/index.html'
    if not os.path.exists('./docs'):
        os.makedirs('./docs')

    bucket = 'ioos-cloud-www'

    storageService = S3Storage()

    rho_vars = ['temp', "zeta", "salt"]

    imagelist = []

    for var in rho_vars:
        imagename = plot_rho(ds_ofs, var, s3upload=True)
        imagelist.append(imagename)

    make_indexhtml(indexfile, imagelist)
    storageService.uploadFile(indexfile,
                              bucket,
                              'index.html',
                              public=True,
                              text=True)

    print('Finished ...')
Beispiel #2
0
def plot_rho(ds, variable, s3upload=False) -> str:
    
    if variable == 'zeta':
        da = ds[variable].isel(ocean_time=0)
        cmap = cmocean.cm.phase
    if variable == 'temp':
        da = ds[variable].isel(ocean_time=0, s_rho=0)
        cmap = cmocean.cm.thermal
    if variable == 'salt':
        da = ds[variable].isel(ocean_time=0, s_rho=0)
        cmap = cmocean.cm.haline
    if variable == 'oxygen':
        da = ds[variable].isel(ocean_time=0, s_rho=0)
        cmap = cmocean.cm.oxy
    if variable == 'Pair':
        da = ds[variable].isel(ocean_time=0)
        cmap = cmocean.cm.diff
      
    fig = plt.figure(figsize=(12,5))
    ax = fig.add_axes([0,0,1,1], projection=ccrs.PlateCarree())
    im = ax.contourf(da.lon_rho, da.lat_rho, da.values,
                     transform=ccrs.PlateCarree(), 
                     cmap=cmap)
    
    coast_10m = cfeature.NaturalEarthFeature(
        'physical', 'land', '10m',
        edgecolor='k', facecolor='0.8'
    )
    ax.add_feature(coast_10m);
    
    title = ds.attrs['title']
    history = ds.history
    now = datetime.now().strftime("%m/%d/%Y, %H:%M:%S")
    ax.set_title(f"Image generated on {now}\n\n{title}\n{history}");
    
    cbar = fig.colorbar(im, ax=ax)
    long_name = da.attrs['long_name']
    if variable != 'salt':
        units = da.attrs['units']
        cbar.set_label(f'{long_name} ({units})')
    else:
        cbar.set_label(f'{long_name}')
    
    indexfile = f'docs/index.html'
    outfile = f'docs/{variable}.png'
    
    if not os.path.exists('./docs'):
        os.makedirs('./docs')

    imagename = outfile.split('/')[-1]

    plt.savefig(outfile, bbox_inches='tight')
                 
    if s3upload:
        s3 = S3Storage()
        bucket = 'ioos-cloud-www'
        s3.uploadFile(outfile, bucket, f'{variable}.png', public = True)

    return imagename
def main():

    print('... About to load dataset ds_ofs ...')
    ds_ofs = dsofs_curr_fcst()
    print('... ds_ofs is loaded ...')

    model = get_model_type(ds_ofs)
    print(f'... model type is: {model}')

    indexfile = f'docs/index.html'
    if not os.path.exists('./docs'):
        os.makedirs('./docs')

    bucket = 'ioos-cloud-www'
    bucket_folder = 'sandbot/'

    storageService = S3Storage()

    # TODO: vectors not working for LEOFS - hangs. NGOFS works fine.
    plot_vars = ['temp', 'zeta', 'salt', 'wind', 'currents']

    print(f'... Plotting these variables: {plot_vars}')
    imagelist = []

    for var in plot_vars:
        print(f'... calling plot routine for {model}:{var} ...')
        #imagename = plot_runner(ds_ofs, var, s3upload=upload)
        if model == 'roms':
            imagename = plot_roms(ds_ofs, var, s3upload=upload)
        elif model == 'fvcom':
            imagename = plot_fvcom(ds_ofs, var, s3upload=upload)
        else:
            print('ERROR: model not supported')
            raise Exception(e)

        if imagename:
            imagelist.append(imagename)

    ds_ofs.close()

    if upload:
        make_indexhtml(indexfile, imagelist)
        storageService.uploadFile(indexfile,
                                  bucket,
                                  f'{bucket_folder}index.html',
                                  public=True,
                                  text=True)

    print('Finished ...')
Beispiel #4
0
def inject(pyfile, platform: str = 'AWS'):
    ''' Uploads the notebook to S3 '''

    #from cloudflow.services.StorageService import StorageService
    from cloudflow.services.S3Storage import S3Storage

    #FIX: Make this cloud agnostic, need a way to set the current platform at runtime
    #FIX: Make this configurable at runtime, maybe from a config file on the machine

    user = os.getenv("JUPYTERHUB_USER")
    bucket = 'ioos-cloud-sandbox'
    bcktfolder = f'cloudflow/inject/{user}'

    filename = pyfile.split('/')[-1]
    #print(f"filename: {filename}")
    ss = S3Storage()
    #def uploadFile(self, filename: str, bucket: str, key: str, public: bool = False):
    ss.uploadFile(pyfile, bucket, f"{bcktfolder}/{filename}")
    return
def main(job: Plotting):

    COMDIR = job.INDIR
    OFS = job.OFS
    HH = job.HH
    rho_vars = job.VARS

    print(f'COMDIR is: {COMDIR}')
    print(f'OFS is: {OFS}')
    print(f'HH is: {HH}')
    print('Running ...')

    # could check that this is a roms model
    # if ofs in utils.roms_models then do roms
    # else if ofs in utils.fvcom_models then do fvcom

    ds_roms = roms_nosofs(COMDIR, OFS, HH)
    indexfile = f'docs/index.html'
    if not os.path.exists('./docs'):
        os.makedirs('./docs')

    bucket = 'ioos-cloud-www'

    storageService = S3Storage()

    #rho_vars = ['temp',"zeta", "salt" ]

    imagelist = []

    for var in rho_vars:
        imagename = plot_rho(ds_roms, var, s3upload=True)
        imagelist.append(imagename)

    make_indexhtml(indexfile, imagelist)
    storageService.uploadFile(indexfile,
                              bucket,
                              'index.html',
                              public=True,
                              text=True)

    print('Finished ...')
Beispiel #6
0
def storage_init(provider: str) -> StorageService:
    """Class factory that returns an implementation of StorageService.

    StorageService is the abstract base class that provides a generic interface for
    multiple cloud platforms.

    Parameters
    ----------
    provider : str
      Name of an implemented provider.

    Returns
    -------
    service : StorageService
      Returns a specific implementation of the StorageService interface.

    Raises
    ------
    signals.FAIL
      Triggers and exception if `provider` is not supported.

    Notes
    -----
    The following providers are implemented:
      AWS S3 - S3Storage

    """

    if provider == 'AWS':
        service = S3Storage()

    elif provider == 'Local':
        log.error('Coming soon ...')
        raise signals.FAIL()
    else:
        log.error('Unsupported provider')
        raise signals.FAIL()

    return service
def plot_fvcom(ds, variable, s3upload=False) -> str:

    time = 2
    siglay = 0
    dims = 2
    clevs = 15
    vector = False

    vmin = None
    vmax = None

    print(f'.... Plotting FVCOM - {variable} ....')

    if variable == 'zeta':
        #zeta(time, node)
        dims = 2
        da = ds[variable]
        #cmap = cmocean.cm.phase
        #cmap=plt.get_cmap('jet')
        cmap = plt.get_cmap('turbo')
        #vmax=5.0
        #vmin=-3.0
    if variable == 'temp':
        #temp(time, siglay, node)
        dims = 3
        #da = ds[variable][:][siglay]
        da = ds.variables[variable]
        cmap = cmocean.cm.thermal
    if variable == 'salt':
        #salinity(time, siglay, node)
        dims = 3
        da = ds['salinity']
        cmap = cmocean.cm.haline
    if variable == 'Pair':
        #atmos_press(time, node)
        dims = 2
        da = ds['atmos_press']
        cmap = cmocean.cm.diff
    if variable == 'oxygen':
        print('oxygen is not supported in this model')
        return
    if variable == 'wind':
        vector = True
        dims = 2

        cmap = plt.get_cmap('OrRd')

        #uwind_speed(time, nele)
        #vwind_speed(time, nele)
        data_u = ds['uwind_speed']
        data_v = ds['vwind_speed']
        da = data_u
        long_name = 'Wind Speed'

        print('.... computing wind magnitude .... ')
        mag = np.sqrt(np.square(data_u[time]) + np.square(data_v[time]))

    if variable == 'currents':
        vector = True
        dims = 3
        cmap = plt.get_cmap('YlOrBr')

        #u(time, siglay, nele)
        #v(time, siglay, nele)
        data_u = ds['u'][siglay]
        data_v = ds['v'][siglay]
        da = ds['u']

        mag = np.sqrt(np.square(data_u[time]) + np.square(data_v[time]))
        long_name = 'Water Velocity'

    fig = plt.figure(figsize=(12, 5), dpi=72)
    #fig = plt.figure(figsize=(12,5), facecolor='black')

    ax = fig.add_axes([0, .085, 1, 1], projection=ccrs.PlateCarree())

    if dims == 2:
        plot_da = da[time]
    elif dims == 3:
        plot_da = da[time][siglay]
    else:
        plot_da = None

    if debug: print(f"{variable} dims: {dims}")

    if vector == False:

        lon = ds['lon'][:]
        lon = np.where(lon > 180., lon - 360., lon)
        lat = ds['lat'][:]

        nv = ds.variables['nv'][:].T
        nv = nv - 1
        im = ax.tricontourf(lon,
                            lat,
                            nv,
                            plot_da,
                            transform=ccrs.PlateCarree(),
                            levels=clevs,
                            vmin=vmin,
                            vmax=vmax,
                            cmap=cmap)

        long_name = da.long_name
    else:

        # Plot the magnitude
        lon = ds['lonc'][:]
        lon = np.where(lon > 180., lon - 360., lon)
        lat = ds['latc'][:]

        #nbe(three, nele) ;
        #nbe:long_name = "elements surrounding each element" ;
        nbe = ds.variables['nbe'][:].T
        nbe = nbe - 1

        # Think of it as a circular array, need to keep vertices together
        np.place(nbe, nbe < 0, len(nbe) - 1)

        im = ax.tricontourf(lon,
                            lat,
                            nbe,
                            mag,
                            transform=ccrs.PlateCarree(),
                            levels=clevs,
                            vmin=vmin,
                            vmax=vmax,
                            cmap=cmap)

        # Plot the vectors
        im = ax.quiver(lon,
                       lat,
                       data_u[time],
                       data_v[time],
                       cmap=cmap,
                       regrid_shape=18)
    # end if vector

    print('.... adding map features and labels ....')
    # Don't add the land mask if it is a Lake forecast
    if not (re.search("LEOFS", ds.title) or re.search("LMHOFS", ds.title)):
        # if not re.search("Lake", ds.title):
        # Obscures data
        #if variable == 'temp':
        land = cfeature.NaturalEarthFeature('physical',
                                            'land',
                                            '10m',
                                            edgecolor='black',
                                            facecolor='0.75')
        ax.add_feature(land)
    else:
        # We currently aren't running any saltwater lakes
        if variable == "salt":
            print('INFO: Not plotting salinity for freshwater lakes ....')
            plt.close(fig)
            return ""

        lakes = cfeature.NaturalEarthFeature('physical',
                                             'lakes',
                                             '10m',
                                             edgecolor='black',
                                             facecolor='none')
        ax.add_feature(lakes)

    # Does not have lake contour
    # ax.coastlines(resolution='10m')

    # OSM data example
    #shp = shapereader.Reader('./data/OSM_land/BTS')
    #for record, geometry in zip(shp.records(), shp.geometries()):
    #    ax.add_geometries([geometry], ccrs.PlateCarree(), facecolor='lightgray',
    #                       edgecolor='black')

    title = ds.title
    time_array = ds.variables['time']
    init = time_array[0]

    #init=ds.dstart.isel(ocean_time=otime) # init is: <xarray.DataArray 'dstart' (ocean_time: 2)>
    #init_datetime = num2date(init, init.units) + datetime.timedelta(hours=6)
    #init_str = f"INIT: {init_datetime} UTC"

    init_str = f"INIT: {num2date(init, time_array.units)} UTC"
    valid = time_array[time]
    valid_str = f"VALID: {num2date(valid, time_array.units)} UTC"

    ax.set_title(f'{title}\n{init_str}    {valid_str}')

    # COLOR BAR
    if vmin:
        cm = plt.cm.ScalarMappable(cmap=cmap)
        cm.set_clim(vmin, vmax)
        cbar = fig.colorbar(cm, ax=ax, pad=0.02)
    else:
        cbar = fig.colorbar(im, ax=ax, pad=0.02)

    if variable != 'salt':
        units = da.units
        cbar.set_label(f'{long_name} ({units})')
    else:
        cbar.set_label(f'{long_name}')

    # Not easy to get the local system timezone info using python
    # https://stackoverflow.com/questions/35057968/get-system-local-timezone-in-python/35058346

    dst = timelib.localtime().tm_isdst > 0
    if dst: tz = 'EDT'
    else: tz = 'EST'

    datestrfmt = '%b %d, %Y %H:%M %Z'  #'%Y-%m-%d %H:%M:%S'
    now_str = f"FVCOM plotted at {datetime.datetime.now().strftime(datestrfmt)} {tz}"

    fig.text(0.65, 0.02, f'{now_str}')

    print('.... adding logos ....')

    bbox = ax.get_position().bounds
    #img = image.imread('rps_small.png')
    logo1 = io.BytesIO(base64.b64decode(rps_logo))
    logo1 = image.imread(logo1, format='PNG')
    logo1_axis = fig.add_axes([bbox[0], 0.0, 0.1, 0.08])
    logo1_axis.imshow(logo1, interpolation='hanning')
    logo1_axis.axis('off')

    logo2 = io.BytesIO(base64.b64decode(ioos_logo))
    logo2 = image.imread(logo2, format='PNG')
    logo2_axis = fig.add_axes([bbox[0], 0.0, 0.325, 0.08])
    logo2_axis.imshow(logo2, interpolation='hanning')
    logo2_axis.axis('off')

    # Add the forecast date and time to the filename
    init_datetime = num2date(init, time_array.units)
    fmt = '%Y%m%d_%HZ'  #'%Y-%m-%d %H:%M:%S'
    ini_str = f"{init_datetime.strftime(fmt)}"

    indexfile = f'docs/index.html'
    outfile = f'docs/{ini_str}_{variable}.png'

    if not os.path.exists('./docs'):
        os.makedirs('./docs')

    imagename = outfile.split('/')[-1]

    print(f'.... saving image - {outfile} ....')
    plt.savefig(outfile, bbox_inches='tight')

    if s3upload:
        print(f'.... uploading image to S3 - {variable} ....')

        s3 = S3Storage()
        bucket = 'ioos-cloud-www'
        bucket_folder = 'sandbot/'

        key = f'{bucket_folder}{imagename}'
        s3.uploadFile(outfile, bucket, key, public=True)

    return imagename
def plot_roms(ds, variable, s3upload=False) -> str:

    otime = 1
    srho = len(ds.s_rho) - 1
    # print(f"DEBUG: srho is {srho}")
    vmin = None
    vmax = None

    if variable == 'zeta':
        da = ds[variable].isel(ocean_time=otime)
        #cmap = cmocean.cm.balance
        cmap = plt.get_cmap('jet')
        vector = False
        vmin = -20.0
        vmax = 20.0

    if variable == 'temp':
        da = ds[variable].isel(ocean_time=otime,
                               s_rho=srho)  #s_rho=0 = surface
        cmap = cmocean.cm.thermal
        vector = False

    if variable == 'salt':
        #salt(ocean_time, s_rho, eta_rho, xi_rho)
        da = ds[variable].isel(ocean_time=otime, s_rho=srho)
        cmap = cmocean.cm.haline
        vector = False
    if variable == 'oxygen':
        da = ds[variable].isel(ocean_time=otime, s_rho=srho)
        cmap = cmocean.cm.oxy
        vector = False
    if variable == 'Pair':
        # Pair(ocean_time, eta_rho, xi_rho)
        da = ds[variable].isel(ocean_time=otime)
        cmap = cmocean.cm.diff
        vector = False
    if variable == 'wind':
        cmap = plt.get_cmap('OrRd')

        # Uwind(ocean_time, eta_rho, xi_rho) ;
        # Vwind(ocean_time, eta_rho, xi_rho)
        data_u = ds['Uwind'].isel(ocean_time=otime)
        data_v = ds['Vwind'].isel(ocean_time=otime)

        lons = ds['lon_rho'].values
        lats = ds['lat_rho'].values
        da = data_u

        u = ma.masked_invalid(data_u.values)
        v = ma.masked_invalid(data_v.values)

        mag = np.sqrt(np.square(u) + np.square(v))
        vector = True
    if variable == 'currents':
        cmap = plt.get_cmap('YlOrBr')

        # Select only the ocean time needed.
        # Select u/v data at layer srho (last index = water surface)
        u = ds.u.values[otime, srho, :, :]
        v = ds.v.values[otime, srho, :, :]
        #print(f'u before (ds.u.shape): {u.shape}')
        #print(f'v before (ds.v.shape): {v.shape}')

        # Interpolate u/v to rho coordinates
        ds['u_rho'] = (('eta_rho', 'xi_rho'),
                       np.ma.masked_values(
                           np.zeros_like(ds.zeta.isel(ocean_time=otime)), 0.0))
        ds['v_rho'] = (('eta_rho', 'xi_rho'),
                       np.ma.masked_values(
                           np.zeros_like(ds.zeta.isel(ocean_time=otime)), 0.0))
        ds.u_rho[1:, 1:] = (u[0:-1, :] + u[1:, :]) * 0.5
        ds.v_rho[1:, 1:] = (v[:, 0:-1] + v[:, 1:]) * 0.5
        #print(f'u after (ds.u_rho.shape): {ds.u_rho.shape}')
        #print(f'v after (ds.v_rho.shape): {ds.v_rho.shape}')

        data_u = ds['u_rho']
        data_v = ds['v_rho']

        da = ds['u'].isel(ocean_time=otime)[srho, :, :]
        u = data_u.values
        v = data_v.values
        lons = ds['lon_rho'].values
        lats = ds['lat_rho'].values
        mag = np.sqrt(np.square(u) + np.square(v))
        vector = True
    # end if currents

    fig = plt.figure(figsize=(12, 5), dpi=72)
    ax = fig.add_axes([0, 0.1, 1, 1], projection=ccrs.PlateCarree())

    maskrho = ds['mask_rho'].isel(ocean_time=otime)

    if not vector:
        # Normal plot

        vari = da.values

        vari[np.where(maskrho == 0)] = np.nan

        im = ax.contourf(da.lon_rho,
                         da.lat_rho,
                         vari,
                         transform=ccrs.PlateCarree(),
                         levels=12,
                         vmin=vmin,
                         vmax=vmax,
                         cmap=cmap)
    ## VECTORS!
    else:
        # Plot the magnitude

        vari = mag

        vari[np.where(maskrho == 0)] = np.nan
        u[np.where(maskrho == 0)] = np.nan
        v[np.where(maskrho == 0)] = np.nan

        im = ax.contourf(lons,
                         lats,
                         vari,
                         transform=ccrs.PlateCarree(),
                         levels=12,
                         cmap=cmap)

        # Plot the quivers
        im = ax.quiver(lons,
                       lats,
                       u,
                       v,
                       cmap=cmap,
                       transform=ccrs.PlateCarree(),
                       regrid_shape=32)

    coast_10m = cfeature.NaturalEarthFeature('physical',
                                             'land',
                                             '10m',
                                             edgecolor='k',
                                             facecolor='0.8')
    ax.add_feature(coast_10m)

    #init = ds.ocean_time.isel(ocean_time=0) - Not always right
    init = ds.dstart.isel(
        ocean_time=otime
    )  # init is: <xarray.DataArray 'dstart' (ocean_time: 2)>
    init_datetime = num2date(init, init.units) + datetime.timedelta(hours=6)
    init_str = f"INIT: {init_datetime} UTC"

    valid = da.ocean_time
    valid_str = f"VALID: {num2date(valid, valid.units)} UTC"

    title = ds.title
    ax.set_title(f'{title}\n{init_str}    {valid_str}')

    if vmin:
        cm = plt.cm.ScalarMappable(cmap=cmap)
        cm.set_clim(vmin, vmax)
        cbar = fig.colorbar(cm, ax=ax, pad=0.02)
    else:
        cbar = fig.colorbar(im, ax=ax, pad=0.02)

    if vector == False:
        long_name = da.attrs['long_name']
    else:
        long_name = variable

    if variable != 'salt':
        units = da.attrs['units']
        cbar.set_label(f'{long_name} ({units})')
    else:
        cbar.set_label(f'{long_name}')

    # Add the forecast date and time to the filename
    fmt = '%Y%m%d_%HZ'  #'%Y-%m-%d %H:%M:%S'
    ini_str = f"{init_datetime.strftime(fmt)}"

    indexfile = f'docs/index.html'
    outfile = f'docs/{ini_str}_{variable}.png'

    bbox = ax.get_position().bounds

    #img = image.imread('rps_small.png')
    logo1 = io.BytesIO(base64.b64decode(rps_logo))
    logo1 = image.imread(logo1, format='PNG')
    logo1_axis = fig.add_axes([bbox[0], 0.0, 0.1, 0.08])
    logo1_axis.imshow(logo1, interpolation='hanning')
    logo1_axis.axis('off')

    logo2 = io.BytesIO(base64.b64decode(ioos_logo))
    logo2 = image.imread(logo2, format='PNG')
    logo2_axis = fig.add_axes([bbox[0], 0.0, 0.325, 0.08])
    logo2_axis.imshow(logo2, interpolation='hanning')
    logo2_axis.axis('off')

    dst = timelib.localtime().tm_isdst > 0
    if dst: tz = 'EDT'
    else: tz = 'EST'

    datestrfmt = '%b %d, %Y %H:%M %Z'  #'%Y-%m-%d %H:%M:%S'
    #https://docs.python.org/3/library/datetime.html#aware-and-naive-objects
    now_str = f"ROMS plotted at {datetime.datetime.now().strftime(datestrfmt)} {tz}"
    fig.text(0.65, 0.02, f'{now_str}')

    if not os.path.exists('./docs'):
        os.makedirs('./docs')

    imagename = outfile.split('/')[-1]

    plt.savefig(outfile, bbox_inches='tight')
    #plt.close()

    if s3upload:
        s3 = S3Storage()
        bucket = 'ioos-cloud-www'
        bucket_folder = 'sandbot/'

        key = f'{bucket_folder}{imagename}'
        s3.uploadFile(outfile, bucket, key, public=True)

    return imagename