def setup_and_check(self):  # {{{
        """
        Perform steps to set up the analysis and check for errors in the setup.
        """
        # Authors
        # -------
        # Xylar Asay-Davis

        # first, call setup_and_check from the base class (AnalysisTask),
        # which will perform some common setup, including storing:
        #     self.runDirectory , self.historyDirectory, self.plotsDirectory,
        #     self.namelist, self.runStreams, self.historyStreams,
        #     self.calendar
        super(ComputeAnomalySubtask, self).setup_and_check()

        startDate = self.config.get('timeSeries', 'startDate')
        endDate = self.config.get('timeSeries', 'endDate')

        delta = MpasRelativeDelta(string_to_datetime(endDate),
                                  string_to_datetime(startDate),
                                  calendar=self.calendar)

        months = delta.months + 12*delta.years

        if months <= self.movingAveragePoints:
            raise ValueError('Cannot meaninfully perform a rolling mean '
                             'because the time series is too short.')

        self.mpasTimeSeriesTask.add_variables(variableList=self.variableList)

        self.inputFile = self.mpasTimeSeriesTask.outputFile
Example #2
0
def string_to_relative_delta(dateString, calendar='gregorian'):  # {{{
    """
    Given a date string and a calendar, returns an instance of
    ``MpasRelativeDelta``

    Parameters
    ----------
    dateString : str
        A date and time in one of the following formats::

            YYYY-MM-DD hh:mm:ss
            YYYY-MM-DD hh.mm.ss
            YYYY-MM-DD SSSSS
            DDD hh:mm:ss
            DDD hh.mm.ss
            DDD SSSSS
            hh.mm.ss
            hh:mm:ss
            YYYY-MM-DD
            YYYY-MM
            SSSSS

        Note: either underscores or spaces can be used to separate the date
        from the time portion of the string.

    calendar: {'gregorian', 'gregorian_noleap'}, optional
        The name of one of the calendars supported by MPAS cores

    Returns
    -------
    relativedelta : An ``MpasRelativeDelta`` object

    Raises
    ------
    ValueError
        If an invalid ``dateString`` is supplied.
    """
    # Authors
    # -------
    # Xylar Asay-Davis

    (years, months, days, hours, minutes, seconds) = \
        _parse_date_string(dateString, isInterval=True)

    return MpasRelativeDelta(years=years,
                             months=months,
                             days=days,
                             hours=hours,
                             minutes=minutes,
                             seconds=seconds,
                             calendar=calendar)
Example #3
0
    def setup_and_check(self):  # {{{
        '''
        Perform steps to set up the analysis and check for errors in the setup.
        '''
        # Authors
        # -------
        # Xylar Asay-Davis

        # first, call setup_and_check from the base class (AnalysisTask),
        # which will perform some common setup, including storing:
        #     self.runDirectory , self.historyDirectory, self.plotsDirectory,
        #     self.namelist, self.runStreams, self.historyStreams,
        #     self.calendar
        super(IndexNino34, self).setup_and_check()

        startDate = self.config.get('index', 'startDate')
        endDate = self.config.get('index', 'endDate')

        delta = MpasRelativeDelta(string_to_datetime(endDate),
                                  string_to_datetime(startDate),
                                  calendar=self.calendar)

        months = delta.months + 12 * delta.years

        if months <= 12:
            raise ValueError('Cannot meaninfully analyze El Nino climate '
                             'index because the time series is too short.')

        self.variableList = \
            ['timeMonthly_avg_avgValueWithinOceanRegion_avgSurfaceTemperature']
        self.mpasTimeSeriesTask.add_variables(variableList=self.variableList)

        self.inputFile = self.mpasTimeSeriesTask.outputFile

        mainRunName = self.config.get('runs', 'mainRunName')

        config = self.config
        regionToPlot = config.get('indexNino34', 'region')

        if regionToPlot not in ['nino3.4', 'nino3', 'nino4']:
            raise ValueError(
                'Unexpectes El Nino Index region {}'.format(regionToPlot))
        ninoIndexNumber = regionToPlot[4:]

        self.xmlFileNames = []
        for filePrefix in [
                'nino{}_{}'.format(ninoIndexNumber, mainRunName),
                'nino{}_spectra_{}'.format(ninoIndexNumber, mainRunName)
        ]:
            self.xmlFileNames.append('{}/{}.xml'.format(
                self.plotsDirectory, filePrefix))
    def test_timekeeping(self):

        # test each possible format:
        # YYYY-MM-DD_hh:mm:ss
        # YYYY-MM-DD_hh.mm.ss
        # YYYY-MM-DD_SSSSS
        # DDD_hh:mm:ss
        # DDD_hh.mm.ss
        # DDD_SSSSS
        # hh.mm.ss
        # hh:mm:ss
        # YYYY-MM-DD
        # SSSSS

        for calendar in ['gregorian', 'gregorian_noleap']:
            # test datetime.datetime
            # YYYY-MM-DD_hh:mm:ss
            date1 = string_to_datetime('0001-01-01_00:00:00')
            date2 = datetime.datetime(year=1, month=1, day=1, hour=0, minute=0,
                                      second=0)
            self.assertEqual(date1, date2)

            delta1 = string_to_relative_delta('0001-00-00_00:00:00',
                                              calendar=calendar)
            delta2 = MpasRelativeDelta(years=1, months=0, days=0, hours=0,
                                       minutes=0, seconds=0, calendar=calendar)
            self.assertEqual(delta1, delta2)

            # YYYY-MM-DD_hh.mm.ss
            date1 = string_to_datetime('0001-01-01_00.00.00')
            date2 = datetime.datetime(year=1, month=1, day=1, hour=0, minute=0,
                                      second=0)
            self.assertEqual(date1, date2)

            # YYYY-MM-DD_SSSSS
            date1 = string_to_datetime('0001-01-01_00002')
            date2 = datetime.datetime(year=1, month=1, day=1, hour=0, minute=0,
                                      second=2)
            self.assertEqual(date1, date2)

            # DDD_hh:mm:ss
            delta1 = string_to_relative_delta('0001_00:00:01',
                                              calendar=calendar)
            delta2 = MpasRelativeDelta(years=0, months=0, days=1, hours=0,
                                       minutes=0, seconds=1, calendar=calendar)
            self.assertEqual(delta1, delta2)

            # DDD_hh.mm.ss
            delta1 = string_to_relative_delta('0002_01.00.01',
                                              calendar=calendar)
            delta2 = MpasRelativeDelta(years=0, months=0, days=2, hours=1,
                                       minutes=0, seconds=1, calendar=calendar)
            self.assertEqual(delta1, delta2)

            # DDD_SSSSS
            delta1 = string_to_relative_delta('0002_00003',
                                              calendar=calendar)
            delta2 = MpasRelativeDelta(years=0, months=0, days=2, hours=0,
                                       minutes=0, seconds=3, calendar=calendar)
            self.assertEqual(delta1, delta2)

            # hh:mm:ss
            date1 = string_to_datetime('00:00:01')
            date2 = datetime.datetime(year=1, month=1, day=1, hour=0, minute=0,
                                      second=1)
            self.assertEqual(date1, date2)

            # hh.mm.ss
            delta1 = string_to_relative_delta('00.00.01',
                                              calendar=calendar)
            delta2 = MpasRelativeDelta(years=0, months=0, days=0, hours=0,
                                       minutes=0, seconds=1, calendar=calendar)
            self.assertEqual(delta1, delta2)

            # YYYY-MM-DD
            date1 = string_to_datetime('0001-01-01')
            date2 = datetime.datetime(year=1, month=1, day=1, hour=0, minute=0,
                                      second=0)
            self.assertEqual(date1, date2)

            # SSSSS
            delta1 = string_to_relative_delta('00005',
                                              calendar=calendar)
            delta2 = MpasRelativeDelta(years=0, months=0, days=0, hours=0,
                                       minutes=0, seconds=5, calendar=calendar)
            self.assertEqual(delta1, delta2)

            date1 = string_to_datetime('1996-01-15')
            delta = string_to_relative_delta('0005-00-00',
                                             calendar=calendar)
            date2 = date1-delta
            self.assertEqual(date2, string_to_datetime('1991-01-15'))

            date1 = string_to_datetime('1996-01-15')
            delta = string_to_relative_delta('0000-02-00',
                                             calendar=calendar)
            date2 = date1-delta
            self.assertEqual(date2, string_to_datetime('1995-11-15'))

            date1 = string_to_datetime('1996-01-15')
            delta = string_to_relative_delta('0000-00-20',
                                             calendar=calendar)
            date2 = date1-delta
            self.assertEqual(date2, string_to_datetime('1995-12-26'))
    def test_MpasRelativeDeltaOps(self):
        # test if the calendars behave as they should close to leap day
        # also, test addition and subtraction of the form
        # datetime.datetime +/- MpasRelativeDelta above
        # both calendars with adding one day
        for calendar, expected in zip(['gregorian', 'gregorian_noleap'],
                                      ['2016-02-29', '2016-03-01']):
            self.assertEqual(string_to_datetime('2016-02-28') +
                             string_to_relative_delta('0000-00-01',
                                                      calendar=calendar),
                             string_to_datetime(expected))

        # both calendars with subtracting one day
        for calendar, expected in zip(['gregorian', 'gregorian_noleap'],
                                      ['2016-02-29', '2016-02-28']):
            self.assertEqual(string_to_datetime('2016-03-01') -
                             string_to_relative_delta('0000-00-01',
                                                      calendar=calendar),
                             string_to_datetime(expected))

        # both calendars with adding one month
        for calendar, expected in zip(['gregorian', 'gregorian_noleap'],
                                      ['2016-02-29', '2016-02-28']):
            self.assertEqual(string_to_datetime('2016-01-31') +
                             string_to_relative_delta('0000-01-00',
                                                      calendar=calendar),
                             string_to_datetime(expected))

        # both calendars with subtracting one month
        for calendar, expected in zip(['gregorian', 'gregorian_noleap'],
                                      ['2016-02-29', '2016-02-28']):
            self.assertEqual(string_to_datetime('2016-03-31') -
                             string_to_relative_delta('0000-01-00',
                                                      calendar=calendar),
                             string_to_datetime(expected))

        for calendar in ['gregorian', 'gregorian_noleap']:

            delta1 = string_to_relative_delta('0000-01-00',  calendar=calendar)
            delta2 = string_to_relative_delta('0000-00-01',  calendar=calendar)
            deltaSum = string_to_relative_delta('0000-01-01',
                                                calendar=calendar)
            # test MpasRelativeDelta + MpasRelativeDelta
            self.assertEqual(delta1 + delta2, deltaSum)
            # test MpasRelativeDelta - MpasRelativeDelta
            self.assertEqual(deltaSum - delta2, delta1)

            # test MpasRelativeDelta(date1, date2)
            date1 = string_to_datetime('0002-02-02')
            date2 = string_to_datetime('0001-01-01')
            delta = string_to_relative_delta('0001-01-01',  calendar=calendar)
            self.assertEqual(MpasRelativeDelta(dt1=date1, dt2=date2,
                                               calendar=calendar),
                             delta)

            # test MpasRelativeDelta + datetime.datetime (an odd order but
            # it's allowed...)
            date1 = string_to_datetime('0001-01-01')
            delta = string_to_relative_delta('0001-01-01',  calendar=calendar)
            date2 = string_to_datetime('0002-02-02')
            self.assertEqual(delta + date1, date2)

            # test multiplication/division by scalars
            delta1 = string_to_relative_delta('0001-01-01',  calendar=calendar)
            delta2 = string_to_relative_delta('0002-02-02',  calendar=calendar)
            self.assertEqual(2*delta1, delta2)
            self.assertEqual(delta2/2, delta1)

        # make sure there's an error when we try to add MpasRelativeDeltas
        # with different calendars
        with self.assertRaisesRegexp(ValueError,
                                     'MpasRelativeDelta objects can only be '
                                     'added if their calendars match.'):
            delta1 = string_to_relative_delta('0000-01-00',
                                              calendar='gregorian')
            delta2 = string_to_relative_delta('0000-00-01',
                                              calendar='gregorian_noleap')
            deltaSum = delta1 + delta2
Example #6
0
    def _replicate_cycle(self, ds, dsToReplicate, calendar):  # {{{
        """
        Replicates a periodic time series `dsToReplicate` to cover the
        timeframe of the dataset `ds`.

        Parameters
        ----------
        ds : dataset used to find the start and end time of the replicated
            cycle

        dsToReplicate : dataset to replicate.  The period of the cycle is the
            length of dsToReplicate plus the time between the first two time
            values (typically one year total).

        calendar : {'gregorian', 'gregorian_noleap'}
            The name of one of the calendars supported by MPAS cores

        Returns:
        --------
        dsShift : a cyclicly repeated version of `dsToReplicte` covering the
            range of time of `ds`.
        """
        # Authors
        # -------
        # Xylar Asay-Davis, Milena Veneziani

        dsStartTime = days_to_datetime(ds.Time.min(), calendar=calendar)
        dsEndTime = days_to_datetime(ds.Time.max(), calendar=calendar)
        repStartTime = days_to_datetime(dsToReplicate.Time.min(),
                                        calendar=calendar)
        repEndTime = days_to_datetime(dsToReplicate.Time.max(),
                                      calendar=calendar)

        repSecondTime = days_to_datetime(dsToReplicate.Time.isel(Time=1),
                                         calendar=calendar)

        period = (MpasRelativeDelta(repEndTime, repStartTime) +
                  MpasRelativeDelta(repSecondTime, repStartTime))

        startIndex = 0
        while(dsStartTime > repStartTime + (startIndex + 1) * period):
            startIndex += 1

        endIndex = 0
        while(dsEndTime > repEndTime + endIndex * period):
            endIndex += 1

        dsShift = dsToReplicate.copy()

        times = days_to_datetime(dsShift.Time, calendar=calendar)
        dsShift.coords['Time'] = ('Time',
                                  datetime_to_days(times + startIndex * period,
                                                   calendar=calendar))
        # replicate cycle:
        for cycleIndex in range(startIndex, endIndex):
            dsNew = dsToReplicate.copy()
            dsNew.coords['Time'] = \
                ('Time', datetime_to_days(times + (cycleIndex + 1) * period,
                                          calendar=calendar))
            dsShift = xr.concat([dsShift, dsNew], dim='Time')

        # clip dsShift to the range of ds
        dsStartTime = dsShift.Time.sel(Time=ds.Time.min(),
                                       method=str('nearest')).values
        dsEndTime = dsShift.Time.sel(Time=ds.Time.max(),
                                     method=str('nearest')).values
        dsShift = dsShift.sel(Time=slice(dsStartTime, dsEndTime))

        return dsShift  # }}}