Exemple #1
0
# Set directory paths
metDataDirBase = drive + "era_interim_nc_daily_merged/"
figureDir = '../Figures/GFED_era_interm_analysis/' # always relativ to /Python

# Get emissions, use this to get dimensions
ncFile  = drive + "rebuild/GFED4.1s_METGrid_C_NA_2003_2016.nc"
nc = Dataset(ncFile, 'r')
latitude = nc.variables['latitude'][:]
longitude = nc.variables['longitude'][:]
time = nc.variables['time'][:]
C = nc.variables['C'][:]
nc.close()

# Make time into datetime arrays
time, month, year = cnm.get_era_interim_time(time)

# Spatially subset the data
C, ynew, xnew = cnm.mask2dims(C, longitude, latitude, 0, minLon, maxLon, minLat, maxLat)

################################################################################
# Show emissions time series for the domain
################################################################################
C_daily_total = np.sum(C,axis=(1,2)) # sums daily value for all lon lat
C_cumulative = np.cumsum(C_daily_total)

fig = plt.figure(figsize=(12,8))
ax = plt.subplot(111)
plt.plot(time, C_daily_total)
ax.spines['top'].set_visible(False)
ax.spines['right'].set_visible(False)
# The 6-hourly data to load
ncFile = dataDir  + 'z_all.nc'

nc = Dataset(ncFile, 'r')
allTime = nc.variables['time'][:]
VAR         = nc.variables['z']
time        = nc.variables['time']
time_hour   = np.array(time[:], dtype=int)
lon         = nc.variables['longitude']
lat         = nc.variables['latitude']
lonUnits    = lon.units
latUnits    = lat.units


# get unique year sequence
t, months, years = cnm.get_era_interim_time(time)
uniqueYears = np.unique(years)

# want just boring old date though, for looping
dates = []
for i in range(len(t)):
	d = datetime.datetime(t[i].year, t[i].month, t[i].day)
	dates.append(d)
dates = np.array(dates)

unique_dates = np.unique(dates)
nDays = len(unique_dates)
nLat = len(lat)
nLon = len(lon)

###############################################################################
def find_blocking_days(sdFactor=0.5,
                       startDate="2003-01-01",
                       endDate="2016-12-31",
                       minDays=3,
                       plotBlocks=False,
                       minBlobSize=15.):
    """
	This function finds blocking days based on a very simple definition.
	Blocking days are defined as days when the 500 mb geopotential height
	is one standard deviation above the jDay mean (1979-2016) for at least
	five days. This function takes one argument.
		Arguments:
			sdFactor:  Number multiplied by monthly std when setting
					    the threshold.
			startDate: The first date to create blocking event mask for.
			endDate:   The last date to create blocking event mask for.
			minDays:   The minimum number of consecutive days required for high z
					    values to be considered a block.
			plotBlocks: True or False. If true the z climatology, daily value, and
			            identified area of blocking are plotted and saved. SLOW.
			minBlobSize: The minimum size of a blob in terms of degrees. Value
						   is squared.


		return:
			blocking days: An array of 1 and 0 indicating if blocking
					exists (where equal to 1).
	"""

    # get the start and end times
    startDate = datetime.datetime.strptime(startDate, '%Y-%m-%d')
    endDate = datetime.datetime.strptime(endDate, '%Y-%m-%d')

    # NOTE: File with all 6 hourly z500 files downloaded with get_all_era_interim_z.py
    # NOTE: These 6 hourly data were made daily using make_all_z500_annual.py
    all_Z500_dir = drive + 'era_interim_nc_daily/'
    z_nc = Dataset(all_Z500_dir + 'z_all_daily.nc', 'r')
    z = z_nc.variables['z500']
    lat = z_nc.variables['latitude'][:]
    lon = z_nc.variables['longitude'][:]
    time = z_nc.variables['time']

    # These are for measuring feature size
    dx = np.abs(np.mean(np.diff(lon)))
    dy = np.abs(np.mean(np.diff(lat)))

    # Translates minBlobSpan degree argument to indecies needed to make this many
    # degrees in our latitude x longitude gridded data.
    blobSpan = np.round(minBlobSize / dx)

    #	# For test plotting make bounds
    #	minLat     = lat.min()
    #	maxLat     = lat.max()
    #	minLon     = lon[241]
    #	maxLon     = lon[479]

    #	map = Basemap(projection='robin',llcrnrlat=minLat, urcrnrlat=maxLat,\
    #                 llcrnrlon=minLon, urcrnrlon=maxLon,resolution='c',\
    #	    	       lon_0=0, lat_0=90)

    map = Basemap(projection='ortho', lon_0=-105, lat_0=60, resolution='l')

    # grid coords for mesh plotting of values.
    lons, lats = np.meshgrid(lon, lat)
    x, y = map(lons, lats)

    # Make a nice month and time array for masking
    t, month, year = cnm.get_era_interim_time(time)
    nTime = len(t)

    day = []
    for i in range(len(t)):
        day.append(t[i].day)
    day = np.array(day)

    #	# Now sinces they are annoying, lets ignore Feb 29 all the time. Meaning
    #	# we are getting rid of it in the time and z arrays.
    #	notLeapDayMask = (month != 2) & (day != 29)
    #
    #	t = t[notLeapDayMask]
    #	month = month[notLeapDayMask]
    #	year  = year[notLeapDayMask]
    #	day   = day[notLeapDayMask]
    #	nTime = len(t)
    #
    #	if np.sum((month == 2) & (day == 29)) > 0:
    #		raise ValueError('There is still a February 29th in the time series.')

    # Create Julian day specific threshold values based on that JDay
    # mean and sd for the ~39 years of reanalysis I am working with
    # the z_thresh will be equal spatial same shape as z but with
    # Julian day time axis.
    jDays = np.arange(1, 367)
    nJDays = len(jDays)

    # Create an array of the Julian dates associated with the time
    # axis of the Z data.
    t_jDay = []
    for i in range(len(t)):
        thisJDay = t[i].timetuple().tm_yday
        t_jDay.append(thisJDay)
    t_jDay = np.array(t_jDay)

    # Create the threshold mask.
    # NOTE: If we save the spatial_mean and spatial_std, masks could be created
    # NOTE: later on much easier.
    # NOTE: Some years June 1 has a different julain day because of leap year.
    # NOTE: so these methods will smooth things out a bit.
    spatial_mean = np.zeros((nJDays, z.shape[1], z.shape[2]))
    spatial_std = np.zeros((nJDays, z.shape[1], z.shape[2]))
    z_thresh = np.zeros((nJDays, z.shape[1], z.shape[2]))

    # Sample statistics summary.
    # To see if JDay 366 has way bigger std. Turns out it is smaller. Probably
    # not getting the true variability properly represented.
    julianDaySD = np.zeros((nJDays))
    nSamples = np.zeros(nJDays)

    for i in range(nJDays):
        # Find mask for this jDay days in the record, should be ~40
        dayMask = jDays[i] == t_jDay
        nSamples[i] = np.sum(dayMask)

        spatial_mean[i, :, :] = np.mean(z[dayMask, :, :], axis=0)
        spatial_std[i, :, :] = np.std(z[dayMask, :, :], axis=0)
        julianDaySD[i] = np.mean(spatial_std[i, :, :])
        z_thresh[i, :, :] = spatial_mean[i, :, :] + (spatial_std[i, :, :] *
                                                     sdFactor)

    # Only create a blocking even mask for dates between the date arguments
    analysisDateIndex = np.where((t >= startDate) & (t <= endDate))[0]
    nAnalaysisDays = len(analysisDateIndex)

    # Create an array where each days blocking mask summary can be saved.
    blocking_mask = np.zeros(shape=(nAnalaysisDays, z.shape[1], z.shape[2]),
                             dtype=bool)

    for i in range(nAnalaysisDays):

        # for this analysis date (i), where does that put us on jDays?
        print 'working on: ' + str(t[analysisDateIndex[i]])
        jDayIndex = np.where(t_jDay[analysisDateIndex[i]] == jDays)[0][0]

        # Here, the numbers are in reference to days in the past from
        # day we are tying to make a mask for
        high_z_masks = np.zeros((minDays, z.shape[1], z.shape[2]))
        for d in range(minDays):
            high_z_masks[d, :, :] = z[analysisDateIndex[i] -
                                      d, :, :] >= z_thresh[jDayIndex - d, :, :]

        # Figure out where these 2D arrays are all true, sum over days dimension
        block_count = np.sum(high_z_masks, axis=0)

        # Turn the boolean into a numeric 1 or 0 array
        ridgeMask = np.array(block_count == minDays, dtype=int)
        blocking_mask[i, :, :] = ridgeMask

        # For plotting, mask out where there are no blocks, easy to plot blocks
        ridgeMask_ma = np.ma.masked_where(ridgeMask == 0, ridgeMask)
        ridge_z_values_ma = np.ma.masked_where(ridgeMask == 0,
                                               z[analysisDateIndex[i], :, :])

        # Show this dates Z for plotting, divide by 100 m to show decameters
        # the way they do at: http://weather.rap.ucar.edu/upper/upaCNTR_500.gif
        todays_z = z[analysisDateIndex[i], :, :] / 100.
        todays_climo_z = spatial_mean[jDayIndex, :, :] / 100.

        #########################################################################
        # Set a minimum size requirement for block 'features'.
        # This of course means features have to be identified.
        # http://www.scipy-lectures.org/packages/scikit-image/auto_examples/plot_labels.html
        #########################################################################
        # TODO: Try 15 x 15 deg min size to dfine a block. This means we have to
        # TODO: check the blobs. I think we should do this from the centriod.
        im = ridgeMask
        blobs = im == 1  # Bool condition of blobs is where ridgemask == 1 by def

        all_labels = measure.label(blobs)
        blobs_labels = measure.label(blobs, background=0, connectivity=2)
        uniqueBobIDs = np.unique(blobs_labels)

        # Check each blob for minimum size requirement
        for b in uniqueBobIDs:
            if b != 0:  # 0 is background so skip
                blobMask = b == blobs_labels
                blobArea = np.sum(blobMask)
                if blobArea < blobSpan**2:
                    # I do not want this to remain a blob
                    blobs_labels[blobMask] = 0

        # Mask non-blobs for plotting
        blobs_labels_ma = np.ma.masked_where(blobs_labels == 0, blobs_labels)

        # TODO: !!!!!!!!!
        # Go through unique blob labels. The sum of the blog label met is the
        # total area. Use that as a cuttoff and get rid of blobs that are too
        # small.

        if plotBlocks:

            # Plot the mean field for this day also.

            #			# plotting subset indicies
            #			lon_g, lat_g = np.meshgrid(lon, lat)
            lat_i = (lat > 20)
            #			m = (lon_g > 180.) & (lon_g < 360.) & (lat_g > 8.) & (lat_g < 80.)

            fig = plt.figure(figsize=(12, 12))
            map.drawcoastlines()
            map.drawstates()
            map.drawcountries()

            # Plot the julain day climatology in pcolor shaded.
            c_z_climotology = map.pcolor(x[lat_i, :], y[lat_i, :],
                                         todays_climo_z[lat_i, :])
            bar = plt.colorbar(c_z_climotology)

            # Show the identified features
            c_peaks = map.pcolor(x[lat_i, :],
                                 y[lat_i, :],
                                 blobs_labels_ma[lat_i, :],
                                 cmap="spectral")

            # Plot the daily heights as contours using the same colorbar
            c_height = map.contour(x[lat_i, :],
                                   y[lat_i, :],
                                   todays_z[lat_i, :],
                                   linewidths=4)
            plt.clabel(c_height, inline=1, fontsize=10)

            # shade out the area where we define a block using semi-transparent
            # shading.
            c_ridge = map.pcolor(x[lat_i, :],
                                 y[lat_i, :],
                                 ridgeMask_ma[lat_i, :],
                                 hatch="/.",
                                 alpha=0.)

            dateString = str(t[analysisDateIndex[i]])[0:10]
            plt.title('Date: ' + dateString + \
                      ' Julain day = ' + str(jDays[jDayIndex]))
            plt.savefig('../Figures/block_test/z_show_' + dateString\
                        + '_sd='+str(sdFactor)+\
               '_days='+str(minDays)+'_minBlobSize='+str(minBlobSize)+\
               '.png')
            plt.close(fig)

    # Finally close the very large nc file connection.
    z_nc.close()

    return blocking_mask
Exemple #4
0
        species = 'monthly_burned_area'

    else:
        emissions = fire_nc.variables[species[si:sf]][:]
        emissions_units = fire_nc.variables[species[si:sf]].units
        # The for loop has gotten rid of the area component so we need to remove
        # from the units
        emissions_units = re.sub('m\*\*-2 ', '', emissions_units)

    for n in range(len(fire_time)):
        emissions[n, :, :] = emissions[n, :, :] * grid_area

else:

    # When daily data subset the arrays?
    t_temp, month_temp, year_temp = cnm.get_era_interim_time(fire_time)
    timeIndex = np.where(year_temp == int(year))[0]

    # Now subset the time array to the year of interest only
    fire_time = fire_time[timeIndex]

    # Remove variables that are no longer needed.
    del t_temp, month_temp, year_temp

    # Get daily emissions data
    emissions_units = fire_nc.variables[species].units
    emissions = fire_nc.variables[species][timeIndex, :, :]

dt = (timer.time() - timeStart) / 60.
print '----------------------------------------------------------------------'
print 'It took ' + str(dt) + ' minutes to load emissions array into workspace'