def gpm_imerg_pcp_accumulation(year,
                               month,
                               day,
                               hour,
                               lon=None,
                               lat=None,
                               quiet=False):
    """Returns a map of 6-hour accumulated precipitation in mm from TRMM 3B42,
	over the 6-hour period CENTRED ON the given time in UTC.  Hour must be one
	of [3, 9, 15, 21].

	Values more than 5 degrees from the given lat/lon location set to zero (if
	lat/lon are given).

	3B42 is provided every 3 hours as a mean over the 3-hour period CENTERED on
	the given time.  Hence, if hour=9 then we sum:
		  TRMM 06UTC file x1.5
		+ TRMM 09UTC file x3.0
		+ TRMM 12UTC file x1.5
	"""

    # Check we have a valid time (same as track points)
    valid_hours = range(3, 22, 6)
    if hour not in valid_hours:
        raise ValueError('Invalid hour %s; must be one of %s' %
                         (hour, valid_hours))

    # Iterate for each time
    t = datetime.datetime(year, month, day, hour)
    dt = datetime.timedelta(hours=3)
    pcp_list = iris.cube.CubeList()
    for mult, time in itertools.izip([1.5, 3., 1.5], [t - dt, t, t + dt]):
        if not quiet:
            print '   ', time.strftime('%Y/%m/%d %H:%M'), 'x%.01f' % mult

        # Open TRMM 3B42 file for given time
        pcp = read_gpm_imerg(time.year, time.month, time.day, time.hour)

        ##################################################################
        # Set to zero outside 5 degree radius
        # Tracks use longitude values 0 -> 360 but TRMM uses -180 -> 180
        ##################################################################
        if lat is not None and lon is not None:
            lats = pcp.coord(axis='Y').points
            lons1 = pcp.coord(axis='X').points
            lons = np.where(lons1 < 0, lons1 + 360., lons1)
            lons_, lats_ = np.meshgrid(lons, lats)
            pcp.data = np.ma.where(
                np.hypot(lons_ - lon, lats_ - lat) > 5, 0., pcp.data * mult)
        else:
            pcp.data = pcp.data * mult
        pcp_list.append(pcp)

    # Return sum
    tot_pcp = pl.add_cubes(pcp_list, contributing_days=False)
    tot_pcp.units = 'mm'
    tot_pcp.standard_name = 'lwe_thickness_of_precipitation_amount'
    tot_pcp.long_name = 'accumulated precipitation'
    tot_pcp.var_name = 'pcp'
    return tot_pcp
def composite_pcp_tot_year_month(year,
                                 month,
                                 lead=None,
                                 mjo=None,
                                 y1=2006,
                                 y2=2017):
    """Computes the total precipitation from TRMM 3B42 for a particular year and month. For 2017, uses data up to 2017/07/11 00:00 (inclusive) only."""
    print "starting"
    # Check values are in valid ranges
    if lead is not None:
        if not 0 <= lead <= 6:
            raise ValueError('lead=%s; must be 0 <= lead <= 6' % lead)
    if mjo is not None:
        if not 0 <= mjo <= 8:
            raise ValueError('mjo=%s; must be 0 <= mjo <= 8' % mjo)
    # if year == 2017:
    #     if not 1 <= month <= 7:
    #         raise ValueError('Data in 2017 used up to July only')

    # Compute file names and get list of dates to exclude due to missing
    # ukmo_nwp forecasts
    if lead is None:
        if mjo is None:
            outfile = COMP_PCP_TOT_FILE % (year, month)
        else:
            outfile = COMP_PCP_TOT_FILE_MJO % (year, month, mjo)
        exclude = []
    else:
        if not 0 <= lead <= 6:
            raise ValueError('lead=%s; must be None or 0 <= lead <= 6' % lead)
        if mjo is None:
            outfile = COMP_PCP_TOT_FILE_LEAD % (lead, year, month)
        else:
            outfile = COMP_PCP_TOT_FILE_LEAD_MJO % (lead, year, month, mjo)
        exclude = pl.exclude_days(lead)
    outpath = os.path.join(COMP_PCP_TOT_DIR, str(year), outfile)
    if not os.path.exists(os.path.join(COMP_PCP_TOT_DIR, str(year))):
        os.makedirs(os.path.join(COMP_PCP_TOT_DIR, str(year)))
    if os.path.isfile(outpath):
        raise ValueError('Output file %s already exists' % outpath)

    # For a given MJO phase, get all cyclone tracks for this year and month,
    # and exclude those whose genesis was in the wrong month; then get list of
    # times for remaining track points
    if mjo is not None:
        tc_file = os.path.join(TRACK_DIR, TRACK_FILE % (1979, 2016))
        ain = np.genfromtxt(tc_file,
                            dtype=float,
                            skip_header=1,
                            usecols=[0] + range(3, 9))
        ain_y = ain[np.where(ain[:, 1] == year)]
        ain_ym = ain_y[np.where(ain_y[:, 2] == month)]
        fn = os.path.join(TRACK_DIR, TRACK_FILE_0 % (1979, 2016) + \
                          '.genesis.mjo%d_trackIDs' % mjo)
        ids_list = np.genfromtxt(fn)
        ain_use = ain_ym[np.in1d(ain_ym[:, 0], ids_list)]
        ain_dates = ain_use[:, range(1, 5)]
        dates = [datetime.datetime(*d) for d in ain_dates.astype(int)]

    # Iterate for every day available in this year and month
    t1 = datetime.datetime(year, month, 1)
    print t1
    dt = datetime.timedelta(days=1)
    if month == 12:
        t2 = datetime.datetime(year, 12, 31)
    else:
        t2 = datetime.datetime(year, month + 1, 1) - (dt * 3)
    print t2
    pcp_cubes = iris.cube.CubeList()
    count_days = 0
    if (year, month) == (2010, 3):
        pcp_cubes_res = {
            'n320': iris.cube.CubeList(),
            'n512': iris.cube.CubeList()
        }
        count_days_res = {'n320': 0.0, 'n512': 0.0}
        start_n512 = datetime.datetime(2010, 3, 9, 12)
    elif (year, month) == (2014, 7):
        pcp_cubes_res = {
            'n512': iris.cube.CubeList(),
            'n768': iris.cube.CubeList()
        }
        count_days_res = {'n512': 0.0, 'n768': 0.0}
        start_n768 = datetime.datetime(2014, 7, 15, 12)
    while t1 <= t2:

        # If on list of dates to exclude, move on
        y, m, d = [getattr(t1, a) for a in ['year', 'month', 'day']]
        if t1 in exclude:
            print t1.strftime('%Y/%m/%d'), '-- EXCLUDE'
            t1 += dt
            continue

        # Iterate for each 6 hour period in day
        # (Remember, h=3 means 00-06UTC, etc.)
        if t1.timetuple()[:3] == (2017, 7, 11):
            count_days += 0.5
        else:
            count_days += 1
        for h in xrange(3, 22, 6):
            this_t_h = t1 + datetime.timedelta(hours=h)
            #if this_t_h >= datetime.datetime(2017, 7, 11, 12):
            #t1 = t2 + dt
            #break
            if (year, month) == (2010, 3):
                if (t1 + datetime.timedelta(hours=h)) < start_n512:
                    count_days_res['n320'] += 0.25
                else:
                    count_days_res['n512'] += 0.25
            elif (year, month) == (2014, 7):
                if (t1 + datetime.timedelta(hours=h)) < start_n768:
                    count_days_res['n512'] += 0.25
                else:
                    count_days_res['n768'] += 0.25

            # For a given MJO phase, skip if this time is not on the list found
            # above (note that we are doing this AFTER counting the
            # contributing days above)
            if mjo is not None:
                if (t1 + datetime.timedelta(hours=h)) not in dates:
                    continue
            print t1.strftime('%Y/%m/%d'), '%02d:00' % h

            # Get data
            this_pcp = gpm_imerg_pcp_accumulation(y, m, d, h)
            if this_pcp is not None:
                if this_pcp.data.min() < 0:
                    raise ValueError('Found negative precip value(s)')
                pcp_cubes.append(this_pcp)

                # For months including a change of resolution, append Cube to
                # the appropriate CubeList
                if (year, month) == (2010, 3):
                    if datetime.datetime(y, m, d, h) < start_n512:
                        pcp_cubes_res['n320'].append(this_pcp)
                    else:
                        pcp_cubes_res['n512'].append(this_pcp)
                elif (year, month) == (2014, 7):
                    if datetime.datetime(y, m, d, h) < start_n768:
                        pcp_cubes_res['n512'].append(this_pcp)
                    else:
                        pcp_cubes_res['n768'].append(this_pcp)

        # Increment day
        t1 += dt

    # Sum over Cubes
    if len(pcp_cubes):
        pcp_sum = pl.add_cubes(pcp_cubes, contributing_days=False)
    else:
        print 'No data - creating dummy map'
        dummy = gpm_imerg_pcp_accumulation(1998, 1, 1, 3)
        pcp_sum = pl.add_cubes([dummy, dummy], contributing_days=False)
        pcp_sum.data = np.zeros_like(pcp_sum.data)

    # Set metadata
    pcp_sum.units = 'mm'
    pcp_sum.standard_name = 'lwe_thickness_of_precipitation_amount'
    pcp_sum.long_name = 'precipitation'
    pcp_sum.var_name = 'pcp'
    pcp_sum.attributes['contributing_days'] = float(count_days)

    # Save
    print outpath
    iris.save(pcp_sum, outpath)
Beispiel #3
0
def composite_pcp_tc_year_month(year, month, lead):
    """Computes a composite of the precipitation due to all TCs at a particular
	forecast lead time (in days) for a particular year and month

	Total is divided by 2 at the end as each day is composited from both the
	00Z and the 12Z forecast.  (Of course there may be no tracks at certain
	times, in which case that time just contributes 0 to the total.)

	**Arguments**

	*year*, *month*
		`int`s, year and month of validity times for which to calculate the
		composite

	*lead*
		`int`, length of time after forecast initialization
		
	"""

    # If no Cubes, create a dummy one with zeros

    # Check lead time is in available range
    if not 0 <= lead <= 6:
        raise ValueError('lead=%s; must be 0 <= lead <= 6' % lead)
    #if year == 2017:
    #if not 1 <= month <= 7:
    #raise ValueError('Data in 2017 used up to July only')

    # Check whether output file already exists

    #infilename = TRACK_FILE %
    infile = os.path.join(TRACK_DIR_3WAY, TRACK_FILE)
    print infile

    outdir = os.path.join(COMP_PCP_TC_DIR, str(lead), str(year))
    comp_file = COMP_PCP_TC_FILE % (lead, year, month)
    outfile = os.path.join(outdir, comp_file)

    print outfile

    if os.path.isfile(outfile):
        raise ValueError('Output file %s already exists' % outfile)
    if not os.path.isdir(outdir):
        os.makedirs(outdir)

    # Iterate for every time available in this year and month
    t1 = datetime.datetime(year, month, 4, 12)
    print "t1:", t1
    t2 = datetime.datetime(year, month, 14, 0)
    print "t2:", t2
    dt = datetime.timedelta(days=1)
    #if (year, month) == (2017, 7):
    #t2 = datetime.datetime(2017, 7, 11)
    #elif month == 12:
    #t2 = datetime.datetime(year+1, 1, 1) - dt
    #else:
    #t2 = datetime.datetime(year, month+1, 1) - dt
    pcp_cubes = iris.cube.CubeList()
    exclude = pl.exclude_days(lead)
    count_days = 0
    #if (year, month) == (2010, 3):
    #count_days_res = {'n320': 0.0, 'n512': 0.0}
    #start_n512 = datetime.datetime(2010, 3, 9, 12)
    #elif (year, month) == (2014, 7):
    #count_days_res = {'n512': 0.0, 'n768': 0.0}
    #start_n768 = datetime.datetime(2014, 7, 15, 12)
    vt_list = []
    print "EXCLUDED DATES:", exclude
    while t1 <= t2:

        # Check whether this day is on the list of those to exclude
        if t1 in exclude:
            print t1, '- EXCLUDE'
            t1 += dt
            continue
        #if t1.timetuple()[:3] == (2017, 7, 11):
        #count_days += 0.5
        #else:
        count_days += 1
        print t1.strftime('%Y/%m/%d')

        # Get list of forecast and validity times for the three forecasts to be
        # used
        ftime_deltas = np.arange(-12, 13, 12) - lead * 24
        print "ftime_deltas:", ftime_deltas
        ftimes = []
        for hh in ftime_deltas:
            ftimes.append(t1 + datetime.timedelta(hours=hh))
        #ftimes = (t1 + datetime.timedelta(hours=hh) for hh in ftime_deltas)
        print "ftimes:", ftimes
        vtimes = (np.array([15, 21]) + lead * 24,
                  np.arange(3, 22, 6) + lead * 24,
                  np.array([3, 9]) + lead * 24)
        print "vtimes:", vtimes

        # Iterate for each of the three forecasts
        for ff, vv in itertools.izip(ftimes, vtimes):
            print "vv:", vv

            # If on or after 2017/07/11 12:00, skip
            #if ff >= datetime.datetime(2017, 7, 11, 12):
            #continue

            # Get year, month, day, hour, lon, lat from file
            this_infile = ff.strftime(infile)
            with warnings.catch_warnings():
                warnings.simplefilter('ignore')
                ain = np.genfromtxt(this_infile,
                                    dtype=float,
                                    skip_header=1,
                                    usecols=range(3, 9))

            # Count days for each resolution
            #for v in vv:
            #vt = ff + datetime.timedelta(hours=v)
            #if vt not in vt_list:
            #vt_list.append(vt)
            #if (year, month) == (2010, 3):
            #if vt < start_n512:
            #count_days_res['n320'] += 0.25
            #else:
            #count_days_res['n512'] += 0.25
            #elif (year, month) == (2014, 7):
            #if vt < start_n768:
            #count_days_res['n512'] += 0.25
            #else:
            #count_days_res['n768'] += 0.25

            # If no tracks in this forecast, skip it
            if not ain.size:
                print '   ', ff, '- no tracks'
                continue

            # Iterate for every validity time required from this forecast
            for v in vv:
                print "v:", v

                # Get track(s) with point(s) this time
                gd = ff + datetime.timedelta(hours=v)
                print "gd:", gd
                aint = ain[np.where((ain[:, 0] == gd.year) &\
                     (ain[:, 1] == gd.month) &\
                     (ain[:, 2] == gd.day) &\
                     (ain[:, 3] == gd.hour))]

                if not aint.size:
                    print '   ', ff, 'T+%03d' % v, '- no tracks'
                    continue
                print '   ', ff, 'T+%03d' % v

                # Iterate for each track
                print "running nwp_pcp_accumulation function for points along track:"
                #print "ff:", ff
                #print "v:", v
                #print "aint:", aint
                for lon, lat in aint[:, [4, 5]]:
                    print aint[:, [4, 5]]
                    print "this_pcp = nwp_pcp_accumulation(", ff, v, lon, lat, ")"
                    this_pcp = nwp_pcp_accumulation(ff, v, lon, lat)
                    print "finished running nwp_pcp_accumulation"
                    if this_pcp is None:
                        print "no precip, running dummy_cube()"
                        this_pcp = iris.cube.CubeList([dummy_cube()])
                    else:
                        this_pcp.coord(axis='X').var_name = 'longitude'
                        this_pcp.coord(axis='Y').var_name = 'latitude'
                        this_pcp.coord(axis='X').attributes = {}
                        this_pcp.coord(axis='Y').attributes = {}
                        pcp_cubes.append(iris.util.squeeze(this_pcp))

        # Increment time
        t1 += dt

    def dummy_cube():
        dummy = None
        dummy_t = datetime.datetime(year, month, 1)
        while dummy is None:
            dummy = this_pcp = cf.nwp_pcp_accumulation(dummy_t, 3)
            dummy_t += dt
        dummy = iris.util.squeeze(dummy)
        dummy.data = np.zeros_like(dummy.data)
        dummy.remove_coord(dummy.coord(axis='T'))
        return dummy

    if not len(pcp_cubes):
        pcp_cubes = iris.cube.CubeList([dummy_cube()])

    if not len(pcp_cubes):
        pcp_cubes = iris.cube.CubeList([dummy_cube()])

    # Sum over Cubes and divide by 2
    pcp = pl.add_cubes(
        pcp_cubes, deal_with_masks=False, contributing_days=False) / 2.

    # Set metadata
    pcp.units = 'mm'
    pcp.standard_name = 'lwe_thickness_of_precipitation_amount'
    pcp.long_name = 'precipitation'
    pcp.var_name = 'pcp'
    pcp.attributes['contributing_days'] = count_days

    # Save
    iris.save(pcp, outfile)
    print "saved: ", outfile
def composite_pcp_tc_analysis_year_month(yyyy, month):
	"""Computes a composite of the precipitation due to (actual) TCs for a particular
	year and month - using ibtracs TCs, NOT NWP!

	Only the most basic compositing function - see other functions for including the phase of the MJO (to composite only those TCS whose genesis was in a certain phase, or to select a specific lead time, or to use 3-way matched tracks """

	print yyyy
	print month
	if month in [7, 8, 9, 10, 11, 12]:
		year = yyyy
	elif month in [1, 2, 3, 4, 5, 6]:
		year = yyyy - 1

	infile = os.path.join(IBTRACS_DIR, IBTRACS_FILE)
	print "using file: ", infile
	comp_file = COMP_PCP_TC_IBTRACS_FILE % (yyyy, month)

	outdir = COMP_PCP_TC_IBTRACS_DIR
	outfile = os.path.join(outdir, str(yyyy), comp_file)

	if os.path.isfile(outfile):
		raise ValueError('Output file %s already exists' % outfile)

	odir = os.path.split(outfile)[0]
	if not os.path.isdir(odir):
		os.makedirs(odir)

	exclude = []  # if using a lead time, would need to use the pl.exclude_days function here

	# Count number of days "included" (this includes days for which no tracks
	# exist - i.e., count how many days are not positively excluded)

	# t1 = first day of the month
	# t2 = last day of the month
	# (essentially counting the number of days in the month)
	t1 = datetime.datetime(yyyy, month, 1, 0)
	dt = datetime.timedelta(days=1)
	count_days = 0
	# not sure why we care specifically about july 2017? is this when the dataset ended?
	# if the yearmonth is 201707, set t2 to 20170711...
	# if (year, month) == (2017, 7):
	# t2 = datetime.datetime(2017, 7, 11)

	# account for December needing to use 1st Jan to find the last date
	if month == 12:
		t2 = datetime.datetime(yyyy + 1, 1, 1) - dt
	# otherwise, set t2 to the last day of the month
	else:
		t2 = datetime.datetime(yyyy, month + 1, 1) - dt

	print t2

	while t1 <= t2:
		if t1 not in exclude:
			if t1.timetuple()[:3] == (2017, 7, 11):
				count_days += 0.5
			else:
				count_days += 1

		t1 += dt

	# Get year, month, day, hour, lon, lat from file
	ain = np.genfromtxt(infile, dtype=float, skip_header=1, usecols=[0] + range(3, 9))
	print infile
	#print ain

	# Select track points in the correct year and month
	ain_y = ain[np.where(ain[:, 1] == yyyy)]
	ain_ym = ain_y[np.where(ain_y[:, 2] == month)]
	ain_use = ain_ym

	print ain_use

	# Iterate for each point
	pcp_list = iris.cube.CubeList()

	excluded = []
	for t_id, y, m, d, h, lon, lat in ain_use:
		t_id, y, m, d, h = [int(x) for x in t_id, y, m, d, h]

		this_t_h = datetime.datetime(y, m, d, h)
		this_t = datetime.datetime(y, m, d)

		if this_t in exclude:
			if this_t not in excluded:
				print '%02d/%02d/%02d -- EXCLUDE' % (y, m, d)
				excluded.append(this_t)
			continue

		print '%02d/%02d/%02d %02d:00' % (y, m, d, h)

		# Get precipitation
		this_pcp = gpm_imerg_pcp_accumulation(y, m, d, h, lon, lat)
		pcp_list.append(this_pcp)


		# Check for negative values
		if pcp_list[-1].data.min() < 0:
			raise ValueError('Precip contains negative values')

	# Save
	if len(pcp_list):
		pcp = pl.add_cubes(pcp_list, contributing_days=False)
	else:
		print 'No data - creating dummy map'
		dummy = gpm_imerg_pcp_accumulation(1998, 1, 1, 3)
		pcp = pl.add_cubes([dummy, dummy], contributing_days=False)
		pcp.data = np.zeros_like(pcp.data)
	pcp.units = 'mm'
	pcp.standard_name = 'lwe_thickness_of_precipitation_amount'
	pcp.long_name = 'accumulated precipitation'
	pcp.var_name = 'pcp'
	pcp.attributes['contributing_days'] = float(count_days)
	iris.save(pcp, outfile)
	print outfile
def composite_pcp_tc_year_month(year, month, lead):
    """Computes a composite of the precipitation due to all TCs at a particular
	forecast lead time (in days) for a particular year and month.

	Total is divided by 2 at the end as each day is composited from both the
	00Z and the 12Z forecast.  (Of course there may be no tracks at certain
	times, in which case that time just contributes 0 to the total.)

	**Arguments**

	*year*, *month*
		`int`s, year and month of validity times for which to calculate the
		composite

	*lead*
		`int`, length of time after forecast initialization
	"""

    # Check lead time is in available range
    if not 0 <= lead <= 6:
        raise ValueError('lead=%s; must be 0 <= lead <= 6' % lead)
    #if year == 2017:
    #if not 1 <= month <= 7:
    #raise ValueError('Data in 2017 used up to July only')

    # Check whether output file already exists

    #infilename = TRACK_FILE %
    infile = os.path.join(TRACK_DIR_3WAY, '%Y', TRACK_FILE)
    print infile

    outdir = os.path.join(COMP_PCP_TC_DIR, str(lead), str(year))
    comp_file = COMP_PCP_TC_FILE % (lead, year, month)
    outfile = os.path.join(outdir, comp_file)

    print outfile

    if os.path.isfile(outfile):
        raise ValueError('Output file %s already exists' % outfile)
    if not os.path.isdir(outdir):
        os.makedirs(outdir)

    # Iterate for every time available in this year and month
    t1 = datetime.datetime(year, month, 1, 0)
    dt = datetime.timedelta(days=1)
    if (year, month) == (2017, 7):
        t2 = datetime.datetime(2017, 7, 11)
    elif month == 12:
        t2 = datetime.datetime(year + 1, 1, 1) - dt
    else:
        t2 = datetime.datetime(year, month + 1, 1) - dt
    pcp_cubes = iris.cube.CubeList()
    exclude = pl.exclude_days(lead)
    count_days = 0
    if (year, month) == (2010, 3):
        count_days_res = {'n320': 0.0, 'n512': 0.0}
        start_n512 = datetime.datetime(2010, 3, 9, 12)
    elif (year, month) == (2014, 7):
        count_days_res = {'n512': 0.0, 'n768': 0.0}
        start_n768 = datetime.datetime(2014, 7, 15, 12)
    vt_list = []
    while t1 <= t2:

        # Check whether this day is on the list of those to exclude
        if t1 in exclude:
            print t1, '- EXCLUDE'
            t1 += dt
            continue
        if t1.timetuple()[:3] == (2017, 7, 11):
            count_days += 0.5
        else:
            count_days += 1
        print t1.strftime('%Y/%m/%d')

        # Get list of forecast and validity times for the three forecasts to be
        # used
        ftime_deltas = np.arange(-12, 13, 12) - lead * 24
        ftimes = (t1 + datetime.timedelta(hours=hh) for hh in ftime_deltas)
        vtimes = (np.array([15, 21]) + lead * 24,
                  np.arange(3, 22, 6) + lead * 24,
                  np.array([3, 9]) + lead * 24)

        # Iterate for each of the three forecasts
        for ff, vv in itertools.izip(ftimes, vtimes):

            # If on or after 2017/07/11 12:00, skip
            #if ff >= datetime.datetime(2017, 7, 11, 12):
            #continue

            # Get year, month, day, hour, lon, lat from file
            this_infile = ff.strftime(infile)
            with warnings.catch_warnings():
                warnings.simplefilter('ignore')
                ain = np.genfromtxt(this_infile,
                                    dtype=float,
                                    skip_header=1,
                                    usecols=range(3, 9))

            # Count days for each resolution
            for v in vv:
                vt = ff + datetime.timedelta(hours=v)
                if vt not in vt_list:
                    vt_list.append(vt)
                    if (year, month) == (2010, 3):
                        if vt < start_n512:
                            count_days_res['n320'] += 0.25
                        else:
                            count_days_res['n512'] += 0.25
                    elif (year, month) == (2014, 7):
                        if vt < start_n768:
                            count_days_res['n512'] += 0.25
                        else:
                            count_days_res['n768'] += 0.25

            # If no tracks in this forecast, skip it
            if not ain.size:
                print '   ', ff, '- no tracks'
                continue

            # Iterate for every validity time required from this forecast
            for v in vv:

                # Get track(s) with point(s) this time
                gd = ff + datetime.timedelta(hours=v)
                aint = ain[np.where((ain[:, 0] == gd.year) &\
                     (ain[:, 1] == gd.month) &\
                     (ain[:, 2] == gd.day) &\
                     (ain[:, 3] == gd.hour))]
                if not aint.size:
                    print '   ', ff, 'T+%03d' % v, '- no tracks'
                    continue
                print '   ', ff, 'T+%03d' % v

                # Iterate for each track
                for lon, lat in aint[:, [4, 5]]:
                    this_pcp = cf.nwp_pcp_accumulation(ff, v, lon, lat)
                    this_pcp.coord(axis='X').var_name = 'longitude'
                    this_pcp.coord(axis='Y').var_name = 'latitude'
                    this_pcp.coord(axis='X').attributes = {}
                    this_pcp.coord(axis='Y').attributes = {}
                    pcp_cubes.append(iris.util.squeeze(this_pcp))

        # Increment time
        t1 += dt

    # If no Cubes, create a dummy one with zeros
    def dummy_cube():
        dummy = None
        dummy_t = datetime.datetime(year, month, 1)
        while dummy is None:
            dummy = this_pcp = cf.nwp_pcp_accumulation(dummy_t, 3)
            dummy_t += dt
        dummy = iris.util.squeeze(dummy)
        dummy.data = np.zeros_like(dummy.data)
        dummy.remove_coord(dummy.coord(axis='T'))
        return dummy

    if not len(pcp_cubes):
        pcp_cubes = iris.cube.CubeList([dummy_cube()])

    # Sum over Cubes and divide by 2
    pcp = pl.add_cubes(
        pcp_cubes, deal_with_masks=False, contributing_days=False) / 2.

    # Set metadata
    pcp.units = 'mm'
    pcp.standard_name = 'lwe_thickness_of_precipitation_amount'
    pcp.long_name = 'precipitation'
    pcp.var_name = 'pcp'
    pcp.attributes['contributing_days'] = count_days

    # Save
    iris.save(pcp, outfile)
    print outfile

    # For months with more than one resolution, sum separately and divide by 2
    if (year, month) in [(2010, 3), (2014, 7)]:
        if year == 2010:
            res_list = ['n320', 'n512']
        elif year == 2014:
            res_list = ['n512', 'n768']
        #res_list = {2010: ['n320', 'n512'], 2014: ['n512', 'n768']}[year]
        pcp_sep = pl.add_cubes(pcp_cubes,
                               deal_with_masks=False,
                               separate_resolutions=True,
                               contributing_days=False)
        file_tot = os.path.join(COMP_PCP_TOT_DIR, str(lead), str(year),
                                COMP_PCP_TOT_FILE % (lead, year, month))
        for k in pcp_sep.iterkeys():
            pcp_sep_k = pcp_sep[k] / 2.

            # Set metadata
            pcp_sep_k.units = 'mm'
            pcp_sep_k.standard_name = 'lwe_thickness_of_precipitation_amount'
            pcp_sep_k.long_name = 'precipitation'
            pcp_sep_k.var_name = 'pcp'

            # Number of contributing days is difficult to count so just get the
            # value from the total pcp composites (the number should be the
            # same anyway)
            res = {640: 'n320', 1024: 'n512', 1536: 'n768'}[k[1]]
            res_list.remove(res)
            file_tot_k = file_tot.replace('.nc', '%s.nc' % res)
            cube_tot_k = iris.load_cube(file_tot_k)
            pcp_sep_k.attributes['contributing_days'] = \
             float(cube_tot_k.attributes['contributing_days'])

            # Save
            outfile_k = outfile.replace('.nc', '.%s.nc' % res)
            iris.save(pcp_sep_k, outfile_k)
            print outfile_k

        # If any resolutions are still in res_list it means there were no
        # tracks at that resolution, so save an empty Cube
        for res in res_list:
            pcp_sep_k = dummy_cube()
            pcp_sep_k.units = 'mm'
            pcp_sep_k.standard_name = 'lwe_thickness_of_precipitation_amount'
            pcp_sep_k.long_name = 'precipitation'
            pcp_sep_k.var_name = 'pcp'
            file_tot_k = file_tot.replace('.nc', '%s.nc' % res)
            cube_tot_k = iris.load_cube(file_tot_k)
            pcp_sep_k.attributes['contributing_days'] = float(
                cube_tot_k.attributes['contributing_days'])
            outfile_k = outfile.replace('.nc', '.%s.nc' % res)
            iris.save(pcp_sep_k, outfile_k)
            print outfile_k
def composite_pcp_tot_year_month(year, month, lead):
	"""Computes a composite of all precipitation at a particular forecast lead
	time (in days) for a particular year and month.

	Total is divided by 2 at the end as each day is composited from both the
	00Z and the 12Z forecast.

	**Arguments**

	*year*, *month*
		`int`s, year and month of validity times for which to calculate the
		composite

	*lead*
		`int`, length of time after forecast initialization
	"""

	# Check lead time is in available range
	if not 0 <= lead <= 6:
		raise ValueError('lead=%s; must be 0 <= lead <= 6' % lead)
	#if year == 2017:
		#if not 1 <= month <= 7:
			#raise ValueError('Data in 2017 used up to July only')

	# Check whether output directory and file already exist
	outfile = os.path.join(COMP_PCP_TOT_DIR, str(lead), str(year),
						   COMP_PCP_TOT_FILE % (lead, year, month))
	if os.path.isfile(outfile):
		raise ValueError('Output file %s already exists' % outfile)

	# Iterate for every time available in this year and month
	########################################################################################
	# MODIFIED BELOW TO TEST SCRIPT, SHOULD BE t1 = datetime.datetime(year, month, 1, 0)
	########################################################################################
	
	#t1 = datetime.datetime(year, month, 1, 0)
	
	t1 = datetime.datetime(year, month, 25, 0) #testing
	
	dt = datetime.timedelta(days=1)
	#if (year, month) == (2017, 7):
		#t2 = datetime.datetime(2017, 7, 11, 12)
	if month == 12:
		t2 = datetime.datetime(year, 12, 31, 12)
	else:
		t2 = datetime.datetime(year, month+1, 1, 12) - dt
	pcp_cubes = iris.cube.CubeList()
	exclude = pl.exclude_days(lead=lead)
	count_days = 0
	if (year, month) == (2010, 3):
		count_days_res = {'n320': 0.0, 'n512': 0.0}
		start_n512 = datetime.datetime(2010, 3, 9, 12)
	elif (year, month) == (2014, 7):
		count_days_res = {'n512': 0.0, 'n768': 0.0}
		start_n768 = datetime.datetime(2014, 7, 15, 12)
	elif (year, month) == (2017,7):
		count_days_res = {'n768': 0.0, 'n1280': 0.0}
		start_n1280 = datetime.datetime(2017, 7, 11, 12)
		
	vt_list = []
	while t1 <= t2:

		# Check whether this day is on the list of those to exclude
		if t1 in exclude:
			print t1.strftime('%Y/%m/%d'), '- EXCLUDE'
			t1 += dt
			continue
		#if t1.timetuple()[:3] == (2017, 7, 11):
			#count_days += 0.5
		else:
			count_days += 1
		print t1.strftime('%Y/%m/%d')

		# Get list of forecast and validity times for the three forecasts to be
		# used
		ftime_deltas = np.arange(-12, 13, 12) - lead*24
		ftimes = [t1 + datetime.timedelta(hours=hh) for hh in ftime_deltas]
		vtimes = (np.array([15, 21]) + lead*24, np.arange(3, 22, 6) + lead*24,
				  np.array([3, 9]) + lead*24)

		# Iterate for each of the three forecasts
		for ff, vv in itertools.izip(ftimes, vtimes):
			#if ff >= datetime.datetime(2017, 7, 11, 12):
				#continue

			# Iterate for every validity time required from this forecast
			for v in vv:
				print '   ', ff, 'T+%03d' % v

				# Count days for each resolution
				vt = ff + datetime.timedelta(hours=v)
				if vt not in vt_list:
					vt_list.append(vt)
					if (year, month) == (2010, 3):
						if vt < start_n512:
							count_days_res['n320'] += 0.25
						else:
							count_days_res['n512'] += 0.25
					elif (year, month) == (2014, 7):
						if vt < start_n768:
							count_days_res['n512'] += 0.25
						else:
							count_days_res['n768'] += 0.25
					elif (year, month) == (2017,7):
						if vt < start_n1280:
							count_days_res['n768'] += 0.25
						else:
							count_days_res['n1280'] += 0.25
							

				# Get precipitation data
				this_pcp = cf.nwp_pcp_accumulation(ff, v)
				this_pcp.coord(axis='X').var_name = 'longitude'
				this_pcp.coord(axis='Y').var_name = 'latitude'
				this_pcp.coord(axis='X').attributes = {}
				this_pcp.coord(axis='Y').attributes = {}
				pcp_cubes.append(iris.util.squeeze(this_pcp))

		# Increment time
		t1 += dt

	# Sum over Cubes and divide by 2
	pcp = pl.add_cubes(pcp_cubes, deal_with_masks=False, contributing_days=False)/2.

	# Set metadata
	pcp.units = 'mm'
	pcp.standard_name = 'lwe_thickness_of_precipitation_amount'
	pcp.long_name = 'precipitation'
	pcp.var_name = 'pcp'
	pcp.attributes['contributing_days'] = float(count_days)
	# Save
	print outfile
	iris.save(pcp, outfile)
	#print outfile
	# For months with more than one resolution, sum separately and divide by 2
	if (year, month) in [(2010, 3), (2014, 7), (2017,7)]:
		print "pcp_cubes:", pcp_cubes
		pcp_sep = pl.add_cubes_sep_res(pcp_cubes, year, deal_with_masks=False, separate_resolutions=True, contributing_days=False)

		for k in pcp_sep.iterkeys():
			print k
			print k[1]

		for k in pcp_sep.iterkeys():
			pcp_sep_k = pcp_sep[k]/2.
			#res = {640: 'n320', 1024: 'n512', 1536: 'n768'}[k[1]]
			res=str(k)

			# Set metadata
			pcp_sep_k.units = 'mm'
			pcp_sep_k.standard_name = 'lwe_thickness_of_precipitation_amount'
			pcp_sep_k.long_name = 'precipitation'
			pcp_sep_k.var_name = 'pcp'
			pcp_sep_k.attributes['contributing_days'] = count_days_res[res]

			# Save
			outfile_k = outfile.replace('.nc', str(res)+'.nc')
			iris.save(pcp_sep_k, outfile_k)
			print outfile_k