def test_get_unique_temperature_sample_times(self): sd = StationData([ StationDescription('StationOne', 18.0, 78.0, 10.0), StationDescription('StationTwo', 53.0, 22.0, 500.0) ]) sd.add_temperature_sample( StationTemperatureSample('StationOne', 60000.0001, 288.15, 0, 288.15, 0)) sd.add_temperature_sample( StationTemperatureSample('StationOne', 60003.0000, 288.15, 0, 288.15, 0)) sd.add_temperature_sample( StationTemperatureSample('StationOne', 60001.0000, 288.15, 0, 288.15, 0)) sd.add_temperature_sample( StationTemperatureSample('StationTwo', 60003.0000, 288.15, 0, 288.15, 0)) sd.add_temperature_sample( StationTemperatureSample('Stationtwo', 60000.0002, 288.15, 0, 288.15, 0)) result = sd.get_unique_temperature_sample_times() self.assertEqual([60000.0001, 60001.0000, 60003.0000], result)
def test_get_break_variable(self): sd = StationData( StationDescriptionArray([ StationDescription('StationOne', 18.0, 78.0, 10.0), StationDescription('StationTwo', 53.0, 22.0, 500.0) ])) sd.add_break( definitions.TASMAX, StationBreak('StationTwo', 3.11, [60466.5, 60511.5], [60100.5, 60800.5])) sd.add_break( definitions.TASMAX, StationBreak('StationOne', 3.33, [60511.5, 60599.5], [60400.5, 60700.5])) sd.add_break( definitions.TASMAX, StationBreak('StationTwo', 3.34, [60599.5, 61000.5], [60700.0, 61100.0])) numpy.testing.assert_array_equal( numpy.array([1, 0, 1], numpy.int32), sd.get_break_variable(definitions.TASMAX_BREAK_STATION)) numpy.testing.assert_array_equal( numpy.array([3.11, 3.33, 3.34], numpy.float32), sd.get_break_variable(definitions.TASMAX_BREAK_AMPLITUDE)) numpy.testing.assert_array_equal( numpy.array( [[60466.5, 60511.5], [60511.5, 60599.5], [60599.5, 61000.5]], numpy.float32), sd.get_break_variable(definitions.TASMAX_BREAK_TIME_BOUNDS)) numpy.testing.assert_array_equal( numpy.array( [[60100.5, 60800.5], [60400.5, 60700.5], [60700.0, 61100.0]], numpy.float32), sd.get_break_variable( definitions.TASMAX_BREAK_TIME_AFFECTED_BOUNDS)) numpy.testing.assert_array_equal( numpy.array([], numpy.int32), sd.get_break_variable(definitions.TASMIN_BREAK_STATION)) numpy.testing.assert_array_equal( numpy.array([], numpy.float32), sd.get_break_variable(definitions.TASMIN_BREAK_AMPLITUDE)) numpy.testing.assert_array_equal( numpy.array([], numpy.float32), sd.get_break_variable(definitions.TASMIN_BREAK_TIME_BOUNDS)) numpy.testing.assert_array_equal( numpy.array([], numpy.float32), sd.get_break_variable( definitions.TASMIN_BREAK_TIME_AFFECTED_BOUNDS))
def test_description_array(self): a = StationDescriptionArray([ StationDescription('OneStation', 33.3, 22.2, 88.8), StationDescription('TwoStations', -18.2, -40.0, 50.0), StationDescription('UnderTheSea', 4.0, 4.0, -3000.0) ]) self.assertEqual(3, a.get_number_of_stations()) self.assertEqual(None, a.get_station_index('Nowhere')) self.assertEqual(2, a.get_station_index('UnderTheSea')) self.assertEqual(0, a.get_station_index('OneStation'))
def test_data_init(self): sd = StationData([ StationDescription('OneStation', 33.3, 22.2, 88.8), StationDescription('TwoStations', -18.2, -40.0, 50.0), StationDescription('UnderTheSea', 4.0, 4.0, -3000.0) ]) self.assertEqual(3, len(sd.descriptions)) self.assertEqual('TwoStations', sd.descriptions[1].name) self.assertEqual(0, len(sd.temperature_samples)) self.assertEqual(0, len(sd.break_detection_quality)) self.assertEqual(0, len(sd.breaks['tasmin'])) self.assertEqual(0, len(sd.breaks['tasmax']))
def test_data_add_break_detection_period(self): sd = StationData([StationDescription('JustOne', 18, 78.0, 10.0)]) self.assertEqual(0, len(sd.break_detection_quality)) sd.add_break_detection_period( StationBreakDetectionQuality( 60591.5, StationBreakDetectionQuality.RELIABLE, StationBreakDetectionQuality.POSSIBLE_BUT_UNRELIABLE)) sd.add_break_detection_period( StationBreakDetectionQuality( 60593.5, StationBreakDetectionQuality.NOT_POSSIBLE, StationBreakDetectionQuality.POSSIBLE_BUT_UNRELIABLE)) sd.add_break_detection_period( StationBreakDetectionQuality( 60599.0, StationBreakDetectionQuality.RELIABLE, StationBreakDetectionQuality.RELIABLE)) self.assertEqual(3, len(sd.break_detection_quality)) self.assertEqual(60591.5, sd.break_detection_quality[0].detection_time) self.assertEqual(2, sd.break_detection_quality[0].tasmin_detection_qc) self.assertEqual(1, sd.break_detection_quality[0].tasmax_detection_qc) self.assertEqual(60593.5, sd.break_detection_quality[1].detection_time) self.assertEqual(0, sd.break_detection_quality[1].tasmin_detection_qc) self.assertEqual(1, sd.break_detection_quality[1].tasmax_detection_qc) self.assertEqual(60599.0, sd.break_detection_quality[2].detection_time) self.assertEqual(2, sd.break_detection_quality[2].tasmin_detection_qc) self.assertEqual(2, sd.break_detection_quality[2].tasmax_detection_qc)
def test_data_add_temperature_sample(self): sd = StationData([StationDescription('JustOne', 18, 78.0, 10.0)]) sd.add_temperature_sample( StationTemperatureSample('JustOne', 60000.0, 272.89, 22, 290.22, 43)) self.assertEqual(1, len(sd.temperature_samples)) self.assertEqual('JustOne', sd.temperature_samples[0].station_name) self.assertEqual(60000.0, sd.temperature_samples[0].time) self.assertEqual(272.89, sd.temperature_samples[0].tasmin) self.assertEqual(22, sd.temperature_samples[0].tasmin_qc) self.assertEqual(290.22, sd.temperature_samples[0].tasmax) self.assertEqual(43, sd.temperature_samples[0].tasmax_qc)
def test_data_add_break(self): sd = StationData([StationDescription('JustOne', 18, 78.0, 10.0)]) sd.add_break( definitions.TASMAX, StationBreak('JustOne', 3.22, [60466.0, 60511.0], [60100.0, 60800.0])) self.assertEqual(0, len(sd.breaks['tasmin'])) self.assertEqual(1, len(sd.breaks['tasmax'])) self.assertEqual('JustOne', sd.breaks['tasmax'][0].station_name) self.assertEqual(3.22, sd.breaks['tasmax'][0].amplitude) self.assertEqual(60800.0, sd.breaks['tasmax'][0].time_affected_bounds[1])
def test_get_temperature_samples(self): sd = StationData( StationDescriptionArray([ StationDescription('StationOne', 18.0, 78.0, 10.0), StationDescription('StationTwo', 53.0, 22.0, 500.0) ])) sd.add_temperature_sample( StationTemperatureSample('StationOne', 60000.0001, 288.15, 11, 298.15, 20)) sd.add_temperature_sample( StationTemperatureSample('StationOne', 60003.0000, 287.15, 13, 297.15, 0)) sd.add_temperature_sample( StationTemperatureSample('StationOne', 60001.0000, 286.15, 15, 296.15, 23)) sd.add_temperature_sample( StationTemperatureSample('StationTwo', 60003.0000, 299.15, 17, 301.05, 18)) sd.add_temperature_sample( StationTemperatureSample('StationTwo', 60000.0002, 300.15, 53, 302.05, 1)) tasmax = sd.get_temperature_samples([60000.0, 60001.0, 60003.0], definitions.TASMAX) tasmin_qc = sd.get_temperature_samples([60000.0, 60001.0, 60003.0], definitions.TASMIN_QC) numpy.testing.assert_array_almost_equal( [[298.15, 302.05], [296.15, 0.0], [297.15, 301.05]], tasmax, decimal=4) numpy.testing.assert_array_equal([[11, 53], [15, 255], [13, 17]], tasmin_qc)
def write_example_station_data(source, version, outputdirectory, institution): """Make an example output format for station data.""" # station descriptors for example data descriptions = StationDescriptionArray([ StationDescription('Cholet', 47.059407, -0.879787, 85.0), StationDescription('Adelaide', -34.9286212, 138.5999594, 45.0), StationDescription('Tobermory', 56.6227813, -6.0723004, 53.0), StationDescription('Orinoco', 5.4329819, -64.9895156, 628.0), StationDescription('Bungo', 35.3078828, 139.2819831, 15.0), StationDescription('Wellington', 50.977071, -3.225954, 75.0), StationDescription('Tomsk', 56.5010397, 84.9924506, 144.0), StationDescription('Sofia', 42.660993, 23.333331, 598.0), ]) # helper object to contain station data and put it onto a common time axis data = StationData(descriptions) # some sample times at which we will provide data # - measured in days since 01/01/1850 00:00 UTC simulated_times = numpy.arange(43342, 43442, 1, dtype=numpy.float32) # simulate missing data at one station wellington_missing_time_range = [43399.0, 43600.0] # simulate breaks at some stations sofia_break_time = 43360.0 sofia_break_affected_time_range = [43350.0, 43370.0] sofia_break_amplitude = 3.5 bungo_break_time = 43403.0 bungo_break_affected_time_range = [43399.0, 43439.0] bungo_break_amplitude = 5.0 # add some data # (example only, does not correspond in any way to actual temperatures) for t in simulated_times: # pylint: disable=invalid-name # simulated breaks sofia_break_offset = 0.0 if t < sofia_break_time else sofia_break_amplitude bungo_break_offset = 0.0 if t < bungo_break_time else bungo_break_amplitude data.add_temperature_sample( StationTemperatureSample( station_name='Sofia', time=t, tasmin=273.15 + 5.0 * math.sin( (t + 3) * 0.0086) + sofia_break_offset, tasmax=293.15 + 5.0 * math.sin( (t + 10) * 0.0086) + sofia_break_offset, tasmin_qc=0, tasmax_qc=0)) data.add_temperature_sample( StationTemperatureSample(station_name='Cholet', time=t, tasmin=285.15 + 4.0 * math.sin( (t + 30) * 0.0086), tasmax=288.15 + 3.0 * math.sin( (t + 32) * 0.0086), tasmin_qc=0, tasmax_qc=0)) data.add_temperature_sample( StationTemperatureSample(station_name='Adelaide', time=t, tasmin=290.15 + 3.0 * math.sin( (t + 60) * 0.0086), tasmax=299.15 + 3.0 * math.sin( (t + 59) * 0.0086), tasmin_qc=0, tasmax_qc=0)) data.add_temperature_sample( StationTemperatureSample(station_name='Tobermory', time=t, tasmin=270.15 + 5.0 * math.sin( (t + 40) * 0.0086), tasmax=282.15 + 4.5 * math.sin( (t + 39) * 0.0086), tasmin_qc=0, tasmax_qc=0)) data.add_temperature_sample( StationTemperatureSample(station_name='Orinoco', time=t, tasmin=274.15 + 4.0 * math.sin( (t + 1) * 0.0086), tasmax=288.15 + 3.0 * math.sin( (t + 2) * 0.0086), tasmin_qc=0, tasmax_qc=0)) data.add_temperature_sample( StationTemperatureSample(station_name='Tomsk', time=t, tasmin=265.15 + 8.0 * math.sin( (t + 10) * 0.0086), tasmax=299.15 + 7.0 * math.sin( (t + 11) * 0.0086), tasmin_qc=0, tasmax_qc=0)) data.add_temperature_sample( StationTemperatureSample( station_name='Bungo', time=t, tasmin=280.15 + 4.5 * math.sin((t + 5) * 0.0086), tasmax=289.15 + 4.0 * math.sin( (t + 10) * 0.0086) + bungo_break_offset, tasmin_qc=0, tasmax_qc=0)) if (t < wellington_missing_time_range[0]) or ( t >= wellington_missing_time_range[1]): data.add_temperature_sample( StationTemperatureSample(station_name='Wellington', time=t, tasmin=285.15 + 12.0 * math.sin( (t + 20) * 0.0086), tasmax=300.15 + 12.0 * math.sin( (t + 19) * 0.0086), tasmin_qc=0, tasmax_qc=0)) # add descriptions of break detection periods data.add_break_detection_period( StationBreakDetectionQuality(43098.0, StationBreakDetectionQuality.RELIABLE, StationBreakDetectionQuality.RELIABLE)) data.add_break_detection_period( StationBreakDetectionQuality(43464.0, StationBreakDetectionQuality.RELIABLE, StationBreakDetectionQuality.RELIABLE)) # add breaks that may have been detected # At station Sofia both TASMIN and TASMAX were affected # At station Bungo only TASMAX was affected data.add_break( definitions.TASMIN, StationBreak( station_name='Sofia', amplitude=sofia_break_amplitude, time_bounds=[sofia_break_time - 15.0, sofia_break_time + 15.0], time_affected_bounds=sofia_break_affected_time_range)) data.add_break( definitions.TASMAX, StationBreak( station_name='Sofia', amplitude=sofia_break_amplitude, time_bounds=[sofia_break_time - 15.0, sofia_break_time + 15.0], time_affected_bounds=sofia_break_affected_time_range)) data.add_break( definitions.TASMAX, StationBreak( station_name='Bungo', amplitude=bungo_break_amplitude, time_bounds=[bungo_break_time - 15.0, bungo_break_time + 15.0], time_affected_bounds=bungo_break_affected_time_range)) # could retrieve sample times like this if we didn't already have them # time_axis = data.get_unique_temperature_sample_times() # time axis known in advance time_axis = simulated_times.tolist() # object to build global field file at current time builder = FileBuilderStationData( outputdirectory, region='Example', source=source, version=version, institution=institution, comment='EUSTACE project example file format for station data', history='Created ' + time.strftime('%c')) # common axes for temperature variables which update daily for every # station builder.set_temperature_dimensions(descriptions, numpy.array(time_axis, numpy.float32)) # add temperature variables builder.add_temperature_variable( definitions.TASMIN, data.get_temperature_samples(time_axis, definitions.TASMIN)) builder.add_temperature_variable( definitions.TASMIN_QC, data.get_temperature_samples(time_axis, definitions.TASMIN_QC)) builder.add_temperature_variable( definitions.TASMAX, data.get_temperature_samples(time_axis, definitions.TASMAX)) builder.add_temperature_variable( definitions.TASMAX_QC, data.get_temperature_samples(time_axis, definitions.TASMAX_QC)) # dimensions for detection statistics builder.add_status_dimension(definitions.DIMENSION_NAME_DETECTION_TIME) builder.add_status_dimension(definitions.DIMENSION_NAME_TASMIN_BREAK) builder.add_status_dimension(definitions.DIMENSION_NAME_TASMAX_BREAK) # add detection statistics information builder.add_status_variable( definitions.DIMENSION_NAME_DETECTION_TIME, definitions.DETECTION_TIME, data.get_break_detection_quality_variable(definitions.DETECTION_TIME)) builder.add_status_variable( definitions.DIMENSION_NAME_DETECTION_TIME, definitions.TASMIN_DETECTION_QC, data.get_break_detection_quality_variable( definitions.TASMIN_DETECTION_QC)) builder.add_status_variable( definitions.DIMENSION_NAME_DETECTION_TIME, definitions.TASMAX_DETECTION_QC, data.get_break_detection_quality_variable( definitions.TASMAX_DETECTION_QC)) # tasmin break information builder.add_status_variable( definitions.DIMENSION_NAME_TASMIN_BREAK, definitions.TASMIN_BREAK_STATION, data.get_break_variable(definitions.TASMIN_BREAK_STATION)) builder.add_status_variable( definitions.DIMENSION_NAME_TASMIN_BREAK, definitions.TASMIN_BREAK_AMPLITUDE, data.get_break_variable(definitions.TASMIN_BREAK_AMPLITUDE)) builder.add_status_variable(definitions.DIMENSION_NAME_TASMIN_BREAK, definitions.TASMIN_BREAK_TIME_BOUNDS, data.get_break_variable( definitions.TASMIN_BREAK_TIME_BOUNDS), bounds=True) builder.add_status_variable( definitions.DIMENSION_NAME_TASMIN_BREAK, definitions.TASMIN_BREAK_TIME_AFFECTED_BOUNDS, data.get_break_variable(definitions.TASMIN_BREAK_TIME_AFFECTED_BOUNDS), bounds=True) # tasmax break information builder.add_status_variable( definitions.DIMENSION_NAME_TASMAX_BREAK, definitions.TASMAX_BREAK_STATION, data.get_break_variable(definitions.TASMAX_BREAK_STATION)) builder.add_status_variable( definitions.DIMENSION_NAME_TASMAX_BREAK, definitions.TASMAX_BREAK_AMPLITUDE, data.get_break_variable(definitions.TASMAX_BREAK_AMPLITUDE)) builder.add_status_variable(definitions.DIMENSION_NAME_TASMAX_BREAK, definitions.TASMAX_BREAK_TIME_BOUNDS, data.get_break_variable( definitions.TASMAX_BREAK_TIME_BOUNDS), bounds=True) builder.add_status_variable( definitions.DIMENSION_NAME_TASMAX_BREAK, definitions.TASMAX_BREAK_TIME_AFFECTED_BOUNDS, data.get_break_variable(definitions.TASMAX_BREAK_TIME_AFFECTED_BOUNDS), bounds=True) # store the result builder.save_and_close()
def test_description(self): d = StationDescription('Bob', 57.0, 3.2, 2000.0) self.assertEqual('Bob', d.name) self.assertEqual(57.0, d.latitude) self.assertEqual(3.2, d.longitude) self.assertEqual(2000.0, d.elevation)