示例#1
0
class Weather:

    def __init__(self):
        
        self.cal = Calibration()
        self.last_integration_mjd_timestamp = None
        self.last_requested_freq_hz = None
        self.last_zenith_opacity = None
        self.number_of_opacity_files = None
        self.opacity_coeffs = None
        self.L_BAND_ZENITH_TAU = .008
        
    def _retrieve_opacity_coefficients(self, opacity_coefficients_filename):
        """Return opacities (taus) derived from a list of coeffients
        
        These coefficients are produced from Ron Madalenna's getForecastValues script
        
        Keywords:
        infilename -- input file name needed for project name
        mjd -- date for data
        freq -- list of frequencies for which we seek an opacity
        
        Returns:
        a list of opacity coefficients for the time range of the dataset
        
        """
        opacity_file = open(opacity_coefficients_filename, 'r')
    
        coeffs = []
        if opacity_file:
            for line in opacity_file:
                # find the most recent forecast and parse out the coefficients for 
                # each band
                # coeffs[0] is the mjd timestamp
                # coeffs[1] are the coefficients for 2-22 GHz
                # coeffs[2] are the coefficients for 22-50 GHz
                # coeffs[3] are the coefficients for 70-116 GHz
                coeffs.append((float(line.split('{{')[0]), \
                    [float(xx) for xx in line.split('{{')[1].split('}')[0].split(' ')], \
                    [float(xx) for xx in line.split('{{')[2].split('}')[0].split(' ')], \
                    [float(xx) for xx in line.split('{{')[3].split('}')[0].split(' ')]))
                   
        else:
            print "WARNING: Could not read coefficients for Tau in", opacity_coefficients_filename
            return False
    
        return coeffs

    def retrieve_zenith_opacity(self, integration_mjd_timestamp, freq_hz):

        freq_ghz = freq_hz/1e9
        
        # if less than 2 GHz, opacity coefficients are not available
        if freq_ghz < 2:
            return self.L_BAND_ZENITH_TAU

        # if the frequency is the same as the last requested and
        #  this time is within the same record (1 hr window) of the last
        #  recorded opacity coefficients, then just reuse the last
        #  zenith opacity value requested

        if self.last_requested_freq_hz and self.last_requested_freq_hz == freq_hz and \
                integration_mjd_timestamp >= self.last_integration_mjd_timestamp and \
                integration_mjd_timestamp < self.last_integration_mjd_timestamp + .04167:
            
            return self.last_zenith_opacity
        
        self.last_integration_mjd_timestamp = integration_mjd_timestamp
        self.last_requested_freq_hz = freq_hz
                
        # retrieve a list of opacity coefficients files, based on a given directory
        # and filename structure
        opacity_coefficients_filename = False
        opacity_files = glob.glob(\
          '/users/rmaddale/Weather/ArchiveCoeffs/CoeffsOpacityFreqList_avrg_*.txt')
        self.number_of_opacity_files = len(opacity_files)
        
        if 0 == self.number_of_opacity_files:
            #doMessage(logger, msg.WARN, 'WARNING: No opacity coefficients file')
            print 'WARNING: No opacity coefficients file'
            return False
            
        # sort the list of files so they are in chronological order
        opacity_files.sort()
        
        # the following will become True if integration_mjd_timestamp is older than available ranges
        # provided in the opacity coefficients files
        tooearly = False
        # check the date of each opacity coefficients file
        for idx, opacity_candidate_file in enumerate(opacity_files):
            dates = opacity_candidate_file.split('_')[-2:]
            opacity_file_timestamp = []
            for date in dates:
                opacity_file_timestamp.append(int(date.split('.')[0]))
            opacity_file_starttime = opacity_file_timestamp[0]
            opacity_file_stoptime = opacity_file_timestamp[1]

            # set tooearly = True when integration_mjd_timestamp is older than available ranges
            if idx == 0 and integration_mjd_timestamp < opacity_file_starttime:
                tooearly = True
                break
        
            if integration_mjd_timestamp >= opacity_file_starttime \
            and integration_mjd_timestamp < opacity_file_stoptime:
                opacity_coefficients_filename = opacity_candidate_file
                break

        if not opacity_coefficients_filename:
            if tooearly:
                #doMessage(logger, msg.ERR, 'ERROR: Date is too early for opacities.')
                #doMessage(logger, msg.ERR, '  Try setting zenith tau at command line.')
                sys.exit(9)
            else:
                # if the mjd in the index file comes after the date string in all of the
                # opacity coefficients files, then we can assume the current opacity
                # coefficients file will apply.  a date string is only added to the opacity
                # coefficients file when it is no longer the most current.
                opacity_coefficients_filename = \
                  '/users/rmaddale/Weather/ArchiveCoeffs/CoeffsOpacityFreqList_avrg.txt'
        
        # opacities coefficients filename
        if opacity_coefficients_filename and os.path.exists(opacity_coefficients_filename):
            #doMessage(logger, msg.DBG, 'Using coefficients from', opacity_coefficients_filename)
            self.opacity_coeffs = self._retrieve_opacity_coefficients(opacity_coefficients_filename)
        else:
            #doMessage(logger, msg.WARN, 'WARNING: No opacity coefficients file')
            print 'WARNING: No opacity coefficients file'
            return False

        for coeffs_line in self.opacity_coeffs:

            if integration_mjd_timestamp >= coeffs_line[0]:
                prev_time = coeffs_line[0]
                if (freq_ghz >= 2 and freq_ghz <= 22):
                    prev_coeffs = coeffs_line[1]
                elif (freq_ghz > 22 and freq_ghz <= 50):
                    prev_coeffs = coeffs_line[2]
                elif (freq_ghz > 50 and freq_ghz <= 116):
                    prev_coeffs = coeffs_line[3]
            elif integration_mjd_timestamp < coeffs_line[0]:
                next_time = coeffs_line[0]
                if (freq_ghz >= 2 and freq_ghz <= 22):
                    next_coeffs = coeffs_line[1]
                elif (freq_ghz > 22 and freq_ghz <= 50):
                    next_coeffs = coeffs_line[2]
                elif (freq_ghz > 50 and freq_ghz <= 116):
                    next_coeffs = coeffs_line[3]
                break

        time_corrected_coeffs = []
        for coeff in zip(prev_coeffs, next_coeffs):
            new_coeff = self.cal.interpolate_by_time(coeff[0], coeff[1],
                                                     prev_time, next_time,
                                                     integration_mjd_timestamp)
            time_corrected_coeffs.append(new_coeff)
        
        zenith_opacity = self.cal.zenith_opacity(time_corrected_coeffs, freq_ghz)
        self.last_zenith_opacity = zenith_opacity
        
        return zenith_opacity
示例#2
0
class test_Calibration:

    def __init__(self):
        self.cal = None

    def setup(self):
        self.cal = Calibration()

    def test_total_power(self):
        array1 = np.ones(10)
        array2 = np.ones(10) * 2
        result = self.cal.total_power(array1, array2)
        expected_result = np.ones(10) * 1.5
        np.testing.assert_equal(result, expected_result)

    def test_tsky(self):
        ambient_temp_k = 310.1
        freq_hz = 18.458
        tau = .05
        tsky = self.cal.tsky(ambient_temp_k, freq_hz, tau)
        expected_result = 13.432242475061472
        ntest.assert_almost_equal(tsky, expected_result)

    def test_tsky_correction(self):
        array_size = 128
        tsky_sig = np.ones(array_size) * 2
        tsky_ref = np.ones(array_size)
        spillover = .123
        tsky_correction = self.cal.tsky_correction(tsky_sig, tsky_ref, spillover)
        expected_result = np.ones(array_size) * .123
        np.testing.assert_equal(tsky_correction, expected_result)

    def test_aperture_efficiency(self):
        reference_eta_a = .71
        freq_hz = 23e9
        efficiency = self.cal.aperture_efficiency(reference_eta_a, freq_hz)
        expected_result = 0.64748265789117276
        ntest.assert_almost_equal(efficiency, expected_result)

    def test_main_beam_efficiency(self):
        reference_eta_a = .7
        freq_hz = 23.7e9
        efficiency = self.cal.main_beam_efficiency(reference_eta_a, freq_hz)
        expected_result = 0.6347374630868166
        ntest.assert_almost_equal(efficiency, expected_result)

    def test_elevation_adjusted_opacity(self):
        zenith_opacity = .1
        elevation = 45.
        adjusted_opacity = self.cal.elevation_adjusted_opacity(.1, 45.)
        expected_result = 0.07071067811865475
        ntest.assert_almost_equal(adjusted_opacity, expected_result)

    def test__tatm(self):
        freq_hz = 23e9
        temp_c = 40.
        atmospheric_effective_temp = self.cal._tatm(freq_hz, temp_c)
        expected_result = 298.88517422006998
        ntest.assert_almost_equal(atmospheric_effective_temp, expected_result)

    def test_zenith_opacity(self):
        opacity_coefficients = [2, 1, 0]
        freq_ghz = 16.79
        zenith_opacity = self.cal.zenith_opacity(opacity_coefficients, freq_ghz)
        expected_result = 18.79
        ntest.assert_equal(zenith_opacity, expected_result)

    def test_tsys(self):
        tcal = 1.
        cal_off = np.ones(128)
        cal_on = np.ones(128)*3
        tsys = self.cal.tsys(tcal, cal_on, cal_off)
        expected = 1.
        ntest.assert_equal(tsys, expected)

    def test_antenna_temp(self):
        tsys = .5
        sig = np.ones(128) * 2
        ref = np.ones(128)
        antenna_temp = self.cal.antenna_temp(tsys, sig, ref)
        expected_result = np.ones(128) * .5
        np.testing.assert_equal(antenna_temp, expected_result)

    def test__ta_fs_one_state(self):
        sigref_state = [{'cal_on': None, 'cal_off': None, 'TP': None},
                        {'cal_on': None, 'cal_off': None, 'TP': None}]

        sigref_state[0]['cal_on'] = np.ones(128)
        sigref_state[0]['cal_off'] = np.ones(128)

        sigref_state[1]['cal_on'] = np.ones(128)
        sigref_state[1]['cal_off'] = np.ones(128)

        sigid = 0
        refid = 1

        assert False

    def test_ta_fs(self):
        assert False

    def test_ta_star(self):
        antenna_temp = np.ones(128)
        beam_scaling = 1.
        opacity = 0
        spillover = 2.
        ta_star = self.cal.ta_star(antenna_temp, beam_scaling, opacity, spillover)
        expected = np.ones(128) * .5
        np.testing.assert_equal(ta_star, expected)

    def test_jansky(self):
        ta_star = np.ones(128)
        aperture_efficiency = .1
        jansky = self.cal.jansky(ta_star, aperture_efficiency)
        expected = np.ones(128) / .285
        np.testing.assert_almost_equal(jansky, expected)

    def test_interpolate_by_time(self):
        reference1 = 0.
        reference1_time = 10000.
        reference2 = 100.
        reference2_time = 20000.
        result_time = 15000.
        result_value = self.cal.interpolate_by_time(reference1, reference2,
                                                    reference1_time, reference2_time,
                                                    result_time)
        expected = 50.
        ntest.assert_equal(result_value, expected)
示例#3
0
class test_Calibration:
    def __init__(self):
        self.cal = None

    def setup(self):
        self.cal = Calibration()

    @unittest.skip("Ignoring test per email from Joe Masters, 2017-10-26")
    def test_total_power(self):
        array1 = np.ones(10)
        array2 = np.ones(10) * 2
        result = self.cal.total_power(array1, array2)
        expected_result = np.ones(10) * 1.5
        np.testing.assert_equal(result, expected_result)

    def test_tsky(self):
        ambient_temp_k = 310.1
        freq_hz = 18.458
        tau = .05
        tsky = self.cal.tsky(ambient_temp_k, freq_hz, tau)
        expected_result = 13.432242475061472
        ntest.assert_almost_equal(tsky, expected_result)

    def test_tsky_correction(self):
        array_size = 128
        tsky_sig = np.ones(array_size) * 2
        tsky_ref = np.ones(array_size)
        spillover = .123
        tsky_correction = self.cal.tsky_correction(tsky_sig, tsky_ref,
                                                   spillover)
        expected_result = np.ones(array_size) * .123
        np.testing.assert_equal(tsky_correction, expected_result)

    def test_aperture_efficiency(self):
        reference_eta_a = .71
        freq_hz = 23e9
        efficiency = self.cal.aperture_efficiency(reference_eta_a, freq_hz)
        expected_result = 0.64748265789117276
        ntest.assert_almost_equal(efficiency, expected_result)

    def test_main_beam_efficiency(self):
        reference_eta_a = .7
        freq_hz = 23.7e9
        efficiency = self.cal.main_beam_efficiency(reference_eta_a, freq_hz)
        expected_result = 0.6347374630868166
        ntest.assert_almost_equal(efficiency, expected_result)

    @unittest.skip(
        "This test is outdated, and should be revisited in the future.")
    def test_elevation_adjusted_opacity(self):
        zenith_opacity = .1
        elevation = 45.
        adjusted_opacity = self.cal.elevation_adjusted_opacity(.1, 45.)
        expected_result = 0.07071067811865475
        ntest.assert_almost_equal(adjusted_opacity, expected_result)

    def test__tatm(self):
        freq_hz = 23e9
        temp_c = 40.
        atmospheric_effective_temp = self.cal._tatm(freq_hz, temp_c)
        expected_result = 298.88517422006998
        ntest.assert_almost_equal(atmospheric_effective_temp, expected_result)

    def test_zenith_opacity(self):
        opacity_coefficients = [2, 1, 0]
        freq_ghz = 16.79
        zenith_opacity = self.cal.zenith_opacity(opacity_coefficients,
                                                 freq_ghz)
        expected_result = 18.79
        ntest.assert_equal(zenith_opacity, expected_result)

    def test_tsys(self):
        tcal = 1.
        cal_off = np.ones(128)
        cal_on = np.ones(128) * 3
        tsys = self.cal.tsys(tcal, cal_on, cal_off)
        expected = 1.
        ntest.assert_equal(tsys, expected)

    @unittest.skip("Ignoring test per email from Joe Masters, 2017-10-26")
    def test_antenna_temp(self):
        tsys = .5
        sig = np.ones(128) * 2
        ref = np.ones(128)
        antenna_temp = self.cal.antenna_temp(tsys, sig, ref)
        expected_result = np.ones(128) * .5
        np.testing.assert_equal(antenna_temp, expected_result)

    @unittest.skip(
        "This is a stub test that we would like to expand in the future.")
    def test__ta_fs_one_state(self):
        sigref_state = [{
            'cal_on': None,
            'cal_off': None,
            'TP': None
        }, {
            'cal_on': None,
            'cal_off': None,
            'TP': None
        }]

        sigref_state[0]['cal_on'] = np.ones(128)
        sigref_state[0]['cal_off'] = np.ones(128)

        sigref_state[1]['cal_on'] = np.ones(128)
        sigref_state[1]['cal_off'] = np.ones(128)

        sigid = 0
        refid = 1

        assert False

    @unittest.skip(
        "This is a stub test that we would like to expand in the future.")
    def test_ta_fs(self):
        assert False

    @unittest.skip("Ignoring test per email from Joe Masters, 2017-10-26")
    def test_ta_star(self):
        antenna_temp = np.ones(128)
        beam_scaling = 1.
        opacity = 0
        spillover = 2.
        ta_star = self.cal.ta_star(antenna_temp, beam_scaling, opacity,
                                   spillover)
        expected = np.ones(128) * .5
        np.testing.assert_equal(ta_star, expected)

    def test_jansky(self):
        ta_star = np.ones(128)
        aperture_efficiency = .1
        jansky = self.cal.jansky(ta_star, aperture_efficiency)
        expected = np.ones(128) / .285
        np.testing.assert_almost_equal(jansky, expected)

    def test_interpolate_by_time(self):
        reference1 = 0.
        reference1_time = 10000.
        reference2 = 100.
        reference2_time = 20000.
        result_time = 15000.
        result_value = self.cal.interpolate_by_time(reference1, reference2,
                                                    reference1_time,
                                                    reference2_time,
                                                    result_time)
        expected = 50.
        ntest.assert_equal(result_value, expected)
示例#4
0
class Weather:
    def __init__(self):

        self.cal = Calibration()
        self.last_integration_mjd_timestamp = None
        self.last_requested_freq_ghz = None
        self.zenith_opacity = None
        self.opacity_coeffs = None
        self.L_BAND_ZENITH_TAU = .008
        self.frequency_range = None
        self.time_range = None
        self.db_time_range = None
        self.log = None

    def _opacity_database(self, timestamp):
        # retrieve a list of opacity coefficients files, based on a given directory
        # and filename structure
        opacity_coefficients_filename = False
        opacity_files = glob.glob(
            '/home/gbtpipeline/weather/CoeffsOpacityFreqList_avrg_*.txt')

        if 0 == len(opacity_files):
            return False, False

        # sort the list of files so they are in chronological order
        opacity_files.sort()

        # check the date of each opacity coefficients file
        for idx, opacity_candidate_file in enumerate(opacity_files):
            dates = opacity_candidate_file.split('_')[-2:]
            opacity_file_timestamp = []
            for date in dates:
                opacity_file_timestamp.append(int(date.split('.')[0]))
            opacity_file_starttime = opacity_file_timestamp[0]
            opacity_file_stoptime = opacity_file_timestamp[1]

            # when timestamp is older than available ranges
            if idx == 0 and timestamp < opacity_file_starttime:
                if self.log:
                    self.log.doMessage(
                        'ERR', 'ERROR: Date is too early for opacities.')
                    self.log.doMessage(
                        'ERR', '  Try setting zenith tau at command line.')
                    self.log.doMessage('ERR', timestamp, '<',
                                       opacity_file_starttime)
                else:
                    print 'ERROR: Date is too early for opacities.'
                    print '  Try setting zenith tau at command line.'
                    print timestamp, '<', opacity_file_starttime
                sys.exit(9)
                break

            if (opacity_file_starttime <= timestamp < opacity_file_stoptime):
                opacity_coefficients_filename = opacity_candidate_file
                opacity_db_range = (opacity_file_starttime,
                                    opacity_file_stoptime)
                break

        # uses most recent info
        if not opacity_coefficients_filename:
            # if the mjd in the index file comes after the date string in all of the
            # opacity coefficients files, then we can assume the current opacity
            # coefficients file will apply.  a date string is only added to the opacity
            # coefficients file when it is no longer the most current.
            opacity_coefficients_filename = '/home/gbtpipeline/weather/CoeffsOpacityFreqList_avrg.txt'
            opacity_db_range = 'LATEST'

        # opacities coefficients filename
        if opacity_coefficients_filename and os.path.exists(
                opacity_coefficients_filename):
            if self.log:
                self.log.doMessage('DBG', 'Using coefficients from',
                                   opacity_coefficients_filename)
            else:
                print 'Using coefficients from', opacity_coefficients_filename
            coeffs = self._retrieve_opacity_coefficients(
                opacity_coefficients_filename)
            return coeffs, opacity_db_range
        else:
            if self.log:
                self.log.doMessage('ERR', 'No opacity coefficients file')
            else:
                print 'ERROR: No opacity coefficients file'
            return False, False

    def _retrieve_opacity_coefficients(self, opacity_coefficients_filename):
        """Return opacities (taus) derived from a list of coeffients

        These coefficients are produced from Ron Madalenna's getForecastValues script

        Keywords:
        infilename -- input file name needed for project name
        mjd -- date for data
        freq -- list of frequencies for which we seek an opacity

        Returns:
        a list of opacity coefficients for the time range of the dataset

        """
        opacity_file = open(opacity_coefficients_filename, 'r')

        coeffs = []
        if opacity_file:
            for line in opacity_file:
                # find the most recent forecast and parse out the coefficients for
                # each band
                # coeffs[0] is the mjd timestamp
                # coeffs[1] are the coefficients for 2-22 GHz
                # coeffs[2] are the coefficients for 22-50 GHz
                # coeffs[3] are the coefficients for 70-116 GHz
                coeffs.append((float(line.split('{{')[0]), [
                    float(xx)
                    for xx in line.split('{{')[1].split('}')[0].split(' ')
                ], [
                    float(xx)
                    for xx in line.split('{{')[2].split('}')[0].split(' ')
                ], [
                    float(xx)
                    for xx in line.split('{{')[3].split('}')[0].split(' ')
                ]))

        else:
            print "WARNING: Could not read coefficients for Tau in", opacity_coefficients_filename
            return False

        return coeffs

    def retrieve_zenith_opacity(self,
                                integration_mjd_timestamp,
                                freq_hz,
                                log=None):

        self.log = log

        freq_ghz = freq_hz / 1e9

        # if less than 2 GHz, opacity coefficients are not available
        if freq_ghz < 2:
            return self.L_BAND_ZENITH_TAU

        # if the frequency is in the same range and
        # the time is within the same record (1 hr window) of the last
        # recorded opacity coefficients, then just reuse the last
        # zenith opacity value requested
        if ((self.frequency_range and
             (self.frequency_range[0] <= freq_ghz <= self.frequency_range[1]))
                and (self.time_range and
                     (self.time_range[0] <= integration_mjd_timestamp <=
                      self.time_range[1]))):

            return self.zenith_opacity

        self.last_integration_mjd_timestamp = integration_mjd_timestamp
        self.last_requested_freq_ghz = freq_ghz

        # if we don't have a db time range OR
        # we do have a time range AND
        #   the range is 'LATEST' AND
        #      timestamp is not w/in the same hour as the last set of coeffs, OR
        #   the range has values AND
        #      our new timestamp is not in the range
        # THEN
        # get another set of coefficients from a different file
        if ((not self.db_time_range)
                or (self.db_time_range == 'LATEST'
                    and not (self.time_range[0] <= integration_mjd_timestamp <
                             self.time_range[1]))
                or (self.db_time_range
                    and not (self.db_time_range[0] <= integration_mjd_timestamp
                             < self.db_time_range[1]))):

            log.doMessage(
                'DBG', '-----------------------------------------------------')
            log.doMessage(
                'DBG', 'Time or Frequency out of range. Determine new opacity')
            log.doMessage(
                'DBG', '-----------------------------------------------------')
            log.doMessage('DBG', 'opacity', self.zenith_opacity)
            log.doMessage('DBG', 'timestamp', integration_mjd_timestamp,
                          'prev.', self.last_integration_mjd_timestamp)
            log.doMessage('DBG', 'freq', freq_ghz, 'prev.',
                          self.last_requested_freq_ghz)
            log.doMessage('DBG', 'freq range', self.frequency_range)
            if bool(self.frequency_range):
                log.doMessage(
                    'DBG', '   freq in range == ',
                    bool(self.frequency_range[0] <= freq_ghz <=
                         self.frequency_range[1]))
            log.doMessage('DBG', 'time range', self.time_range)
            if bool(self.time_range):
                log.doMessage(
                    'DBG', '   time in range ==',
                    bool(self.time_range
                         and (self.time_range[0] <= integration_mjd_timestamp
                              <= self.time_range[1])))
            log.doMessage('DBG', 'DB time range', self.db_time_range)
            if bool(self.db_time_range):
                log.doMessage(
                    'DBG', '   time in DB range ==',
                    bool(self.db_time_range and
                         (self.db_time_range[0] <= integration_mjd_timestamp <=
                          self.db_time_range[1])))

            self.opacity_coeffs, self.db_time_range = self._opacity_database(
                integration_mjd_timestamp)
            if (not self.opacity_coeffs) or (not self.db_time_range):
                return False

            log.doMessage('DBG', 'DB time range:', self.db_time_range)

        for coeffs_line in self.opacity_coeffs:
            if (2 <= freq_ghz <= 22):
                self.frequency_range = (2, 22)
                coefficients_index = 1

            elif (22 < freq_ghz <= 50):
                self.frequency_range = (22, 50)
                coefficients_index = 2

            elif (50 < freq_ghz <= 116):
                self.frequency_range = (50, 116)
                coefficients_index = 3

            if integration_mjd_timestamp >= coeffs_line[0]:
                prev_time = coeffs_line[0]
                prev_coeffs = coeffs_line[coefficients_index]

            elif integration_mjd_timestamp < coeffs_line[0]:
                next_time = coeffs_line[0]
                next_coeffs = coeffs_line[coefficients_index]
                break

        self.time_range = (prev_time, next_time)
        log.doMessage('DBG', 'Coefficient entry time range:', self.time_range)

        time_corrected_coeffs = []
        for coeff in zip(prev_coeffs, next_coeffs):
            new_coeff = self.cal.interpolate_by_time(
                coeff[0], coeff[1], prev_time, next_time,
                integration_mjd_timestamp)
            time_corrected_coeffs.append(new_coeff)

        self.zenith_opacity = self.cal.zenith_opacity(time_corrected_coeffs,
                                                      freq_ghz)
        log.doMessage('DBG', 'Zenith opacity:', self.zenith_opacity)

        return self.zenith_opacity
示例#5
0
class Weather:

    def __init__(self):

        self.cal = Calibration()
        self.last_integration_mjd_timestamp = None
        self.last_requested_freq_ghz = None
        self.zenith_opacity = None
        self.opacity_coeffs = None
        self.L_BAND_ZENITH_TAU = .008
        self.frequency_range = None
        self.time_range = None
        self.db_time_range = None
        self.log = None

    def _opacity_database(self, timestamp):
        # retrieve a list of opacity coefficients files, based on a given directory
        # and filename structure
        opacity_coefficients_filename = False
        opacity_files = glob.glob('/home/gbtpipeline/weather/CoeffsOpacityFreqList_avrg_*.txt')

        if 0 == len(opacity_files):
            return False, False

        # sort the list of files so they are in chronological order
        opacity_files.sort()

        # check the date of each opacity coefficients file
        for idx, opacity_candidate_file in enumerate(opacity_files):
            dates = opacity_candidate_file.split('_')[-2:]
            opacity_file_timestamp = []
            for date in dates:
                opacity_file_timestamp.append(int(date.split('.')[0]))
            opacity_file_starttime = opacity_file_timestamp[0]
            opacity_file_stoptime = opacity_file_timestamp[1]

            # when timestamp is older than available ranges
            if idx == 0 and timestamp < opacity_file_starttime:
                if self.log:
                    self.log.doMessage('ERR', 'ERROR: Date is too early for opacities.')
                    self.log.doMessage('ERR', '  Try setting zenith tau at command line.')
                    self.log.doMessage('ERR', timestamp, '<', opacity_file_starttime)
                else:
                    print 'ERROR: Date is too early for opacities.'
                    print '  Try setting zenith tau at command line.'
                    print timestamp, '<', opacity_file_starttime
                sys.exit(9)
                break

            if (opacity_file_starttime <= timestamp < opacity_file_stoptime):
                opacity_coefficients_filename = opacity_candidate_file
                opacity_db_range = (opacity_file_starttime, opacity_file_stoptime)
                break

        # uses most recent info
        if not opacity_coefficients_filename:
            # if the mjd in the index file comes after the date string in all of the
            # opacity coefficients files, then we can assume the current opacity
            # coefficients file will apply.  a date string is only added to the opacity
            # coefficients file when it is no longer the most current.
            opacity_coefficients_filename = '/home/gbtpipeline/weather/CoeffsOpacityFreqList_avrg.txt'
            opacity_db_range = 'LATEST'

        # opacities coefficients filename
        if opacity_coefficients_filename and os.path.exists(opacity_coefficients_filename):
            if self.log:
                self.log.doMessage('DBG', 'Using coefficients from', opacity_coefficients_filename)
            else:
                print 'Using coefficients from', opacity_coefficients_filename
            coeffs = self._retrieve_opacity_coefficients(opacity_coefficients_filename)
            return coeffs, opacity_db_range
        else:
            if self.log:
                self.log.doMessage('ERR', 'No opacity coefficients file')
            else:
                print 'ERROR: No opacity coefficients file'
            return False, False

    def _retrieve_opacity_coefficients(self, opacity_coefficients_filename):
        """Return opacities (taus) derived from a list of coeffients

        These coefficients are produced from Ron Madalenna's getForecastValues script

        Keywords:
        infilename -- input file name needed for project name
        mjd -- date for data
        freq -- list of frequencies for which we seek an opacity

        Returns:
        a list of opacity coefficients for the time range of the dataset

        """
        opacity_file = open(opacity_coefficients_filename, 'r')

        coeffs = []
        if opacity_file:
            for line in opacity_file:
                # find the most recent forecast and parse out the coefficients for
                # each band
                # coeffs[0] is the mjd timestamp
                # coeffs[1] are the coefficients for 2-22 GHz
                # coeffs[2] are the coefficients for 22-50 GHz
                # coeffs[3] are the coefficients for 70-116 GHz
                coeffs.append((float(line.split('{{')[0]),
                               [float(xx) for xx in line.split('{{')[1].split('}')[0].split(' ')],
                               [float(xx) for xx in line.split('{{')[2].split('}')[0].split(' ')],
                               [float(xx) for xx in line.split('{{')[3].split('}')[0].split(' ')]))

        else:
            print "WARNING: Could not read coefficients for Tau in", opacity_coefficients_filename
            return False

        return coeffs

    def retrieve_zenith_opacity(self, integration_mjd_timestamp, freq_hz, log=None):

        self.log = log

        freq_ghz = freq_hz/1e9

        # if less than 2 GHz, opacity coefficients are not available
        if freq_ghz < 2:
            return self.L_BAND_ZENITH_TAU

        # if the frequency is in the same range and
        # the time is within the same record (1 hr window) of the last
        # recorded opacity coefficients, then just reuse the last
        # zenith opacity value requested
        if ((self.frequency_range and
            (self.frequency_range[0] <= freq_ghz <= self.frequency_range[1])) and
            (self.time_range and
             (self.time_range[0] <= integration_mjd_timestamp <= self.time_range[1]))):

            return self.zenith_opacity

        self.last_integration_mjd_timestamp = integration_mjd_timestamp
        self.last_requested_freq_ghz = freq_ghz

        # if we don't have a db time range OR
        # we do have a time range AND
        #   the range is 'LATEST' AND
        #      timestamp is not w/in the same hour as the last set of coeffs, OR
        #   the range has values AND
        #      our new timestamp is not in the range
        # THEN
        # get another set of coefficients from a different file
        if ((not self.db_time_range) or
            (self.db_time_range == 'LATEST' and
             not (self.time_range[0] <= integration_mjd_timestamp < self.time_range[1])) or
            (self.db_time_range and
             not (self.db_time_range[0] <= integration_mjd_timestamp < self.db_time_range[1]))):

            log.doMessage('DBG', '-----------------------------------------------------')
            log.doMessage('DBG', 'Time or Frequency out of range. Determine new opacity')
            log.doMessage('DBG', '-----------------------------------------------------')
            log.doMessage('DBG', 'opacity', self.zenith_opacity)
            log.doMessage('DBG', 'timestamp', integration_mjd_timestamp, 'prev.', self.last_integration_mjd_timestamp)
            log.doMessage('DBG', 'freq', freq_ghz, 'prev.', self.last_requested_freq_ghz)
            log.doMessage('DBG', 'freq range', self.frequency_range)
            if bool(self.frequency_range):
                log.doMessage('DBG', '   freq in range == ', bool(self.frequency_range[0] <= freq_ghz <= self.frequency_range[1]))
            log.doMessage('DBG', 'time range', self.time_range)
            if bool(self.time_range):
                log.doMessage('DBG', '   time in range ==', bool(self.time_range and (self.time_range[0] <= integration_mjd_timestamp <= self.time_range[1])))
            log.doMessage('DBG', 'DB time range', self.db_time_range)
            if bool(self.db_time_range):
                log.doMessage('DBG', '   time in DB range ==', bool(self.db_time_range and (self.db_time_range[0] <= integration_mjd_timestamp <= self.db_time_range[1])))

            self.opacity_coeffs, self.db_time_range = self._opacity_database(integration_mjd_timestamp)
            if (not self.opacity_coeffs) or (not self.db_time_range):
                return False

            log.doMessage('DBG', 'DB time range:', self.db_time_range)

        for coeffs_line in self.opacity_coeffs:
            if (2 <= freq_ghz <= 22):
                self.frequency_range = (2, 22)
                coefficients_index = 1

            elif (22 < freq_ghz <= 50):
                self.frequency_range = (22, 50)
                coefficients_index = 2

            elif (50 < freq_ghz <= 116):
                self.frequency_range = (50, 116)
                coefficients_index = 3

            if integration_mjd_timestamp >= coeffs_line[0]:
                prev_time = coeffs_line[0]
                prev_coeffs = coeffs_line[coefficients_index]

            elif integration_mjd_timestamp < coeffs_line[0]:
                next_time = coeffs_line[0]
                next_coeffs = coeffs_line[coefficients_index]
                break

        self.time_range = (prev_time, next_time)
        log.doMessage('DBG', 'Coefficient entry time range:', self.time_range)

        time_corrected_coeffs = []
        for coeff in zip(prev_coeffs, next_coeffs):
            new_coeff = self.cal.interpolate_by_time(coeff[0], coeff[1],
                                                     prev_time, next_time,
                                                     integration_mjd_timestamp)
            time_corrected_coeffs.append(new_coeff)

        self.zenith_opacity = self.cal.zenith_opacity(time_corrected_coeffs, freq_ghz)
        log.doMessage('DBG', 'Zenith opacity:', self.zenith_opacity)

        return self.zenith_opacity