def navigate(timecodes, satellite): orb = Orbital(satellite) first_time = timecode(timecodes[0]) first_time = datetime(first_time.year, first_time.month, first_time.day) hrpttimes = [timecode(x) - first_time for x in timecodes] hrpttimes = np.array([x.seconds + x.microseconds / 1000000.0 for x in hrpttimes]) scan_points = np.arange(2048) if satellite == "noaa 16": scan_angle = 55.25 else: scan_angle = 55.37 scans_nb = len(hrpttimes) avhrr_inst = np.vstack(((scan_points / 1023.5 - 1) * np.deg2rad(-scan_angle), np.zeros((len(scan_points),)))).T avhrr_inst = np.tile(avhrr_inst, [scans_nb, 1]) offset = hrpttimes times = (np.tile(scan_points * 0.000025, [scans_nb, 1]) + np.expand_dims(offset, 1)) sgeom = ScanGeometry(avhrr_inst, times.ravel()) s_times = sgeom.times(first_time) rpy = (0, 0, 0) pixels_pos = compute_pixels((orb.tle._line1, orb.tle._line2), sgeom, s_times, rpy) pos_time = get_lonlatalt(pixels_pos, s_times) return pos_time
def navigate(timecodes, satellite): orb = Orbital(satellite) first_time = timecode(timecodes[0]) first_time = datetime(first_time.year, first_time.month, first_time.day) hrpttimes = [timecode(x) - first_time for x in timecodes] hrpttimes = np.array( [x.seconds + x.microseconds / 1000000.0 for x in hrpttimes]) scan_points = np.arange(2048) if satellite == "noaa 16": scan_angle = 55.25 else: scan_angle = 55.37 scans_nb = len(hrpttimes) avhrr_inst = np.vstack( ((scan_points / 1023.5 - 1) * np.deg2rad(-scan_angle), np.zeros((len(scan_points), )))).T avhrr_inst = np.tile(avhrr_inst, [scans_nb, 1]) offset = hrpttimes times = (np.tile(scan_points * 0.000025, [scans_nb, 1]) + np.expand_dims(offset, 1)) sgeom = ScanGeometry(avhrr_inst, times.ravel()) s_times = sgeom.times(first_time) rpy = (0, 0, 0) pixels_pos = compute_pixels((orb.tle._line1, orb.tle._line2), sgeom, s_times, rpy) pos_time = get_lonlatalt(pixels_pos, s_times) return pos_time
def test_scan_geometry(self): """Test the ScanGeometry object. """ scans_nb = 1 xy = np.vstack((np.deg2rad(np.array([10, 0, -10])), np.array([0, 0, 0]))) xy = np.tile(xy[:, np.newaxis, :], [1, np.int(scans_nb), 1]) times = np.tile([-0.1, 0, 0.1], [np.int(scans_nb), 1]) instrument = ScanGeometry(xy, times) self.assertTrue( np.allclose(np.rad2deg(instrument.fovs[0]), np.array([[10, 0, -10]]))) # Test vectors pos = np.rollaxis(np.tile(np.array([0, 0, 7000]), [3, 1, 1]), 2) vel = np.rollaxis(np.tile(np.array([1, 0, 0]), [3, 1, 1]), 2) pos = np.stack([np.array([0, 0, 7000])] * 3, 1)[:, np.newaxis, :] vel = np.stack([np.array([1, 0, 0])] * 3, 1)[:, np.newaxis, :] vec = instrument.vectors(pos, vel) self.assertTrue(np.allclose(np.array([[0, 0, -1]]), vec[:, 0, 1])) # minus sin because we use trigonometrical direction of angles self.assertTrue( np.allclose( np.array( [[0, -np.sin(np.deg2rad(10)), -np.cos(np.deg2rad(10))]]), vec[:, 0, 0])) self.assertTrue( np.allclose( np.array( [[0, -np.sin(np.deg2rad(-10)), -np.cos(np.deg2rad(-10))]]), vec[:, 0, 2])) # Test times start_of_scan = np.datetime64(datetime(2014, 1, 8, 11, 30)) times = instrument.times(start_of_scan) self.assertEqual(times[0, 1], start_of_scan) self.assertEqual(times[0, 0], start_of_scan - np.timedelta64(100, 'ms')) self.assertEqual(times[0, 2], start_of_scan + np.timedelta64(100, 'ms'))
def test_scan_geometry(self): """Test the ScanGeometry object. """ scans_nb = 1 xy = np.vstack((np.deg2rad(np.array([10, 0, -10])), np.array([0, 0, 0]))) xy = np.tile(xy[:, np.newaxis, :], [1, np.int(scans_nb), 1]) times = np.tile([-0.1, 0, 0.1], [np.int(scans_nb), 1]) instrument = ScanGeometry(xy, times) self.assertTrue(np.allclose(np.rad2deg(instrument.fovs[0]), np.array([[10, 0, -10]]))) # Test vectors pos = np.rollaxis(np.tile(np.array([0, 0, 7000]), [3, 1, 1]), 2) vel = np.rollaxis(np.tile(np.array([1, 0, 0]), [3, 1, 1]), 2) pos = np.stack([np.array([0, 0, 7000])] * 3, 1)[:, np.newaxis, :] vel = np.stack([np.array([1, 0, 0])] * 3, 1)[:, np.newaxis, :] vec = instrument.vectors(pos, vel) self.assertTrue(np.allclose(np.array([[0, 0, -1]]), vec[:, 0, 1])) # minus sin because we use trigonometrical direction of angles self.assertTrue(np.allclose(np.array([[0, -np.sin(np.deg2rad(10)), -np.cos(np.deg2rad(10))]]), vec[:, 0, 0])) self.assertTrue(np.allclose(np.array([[0, -np.sin(np.deg2rad(-10)), -np.cos(np.deg2rad(-10))]]), vec[:, 0, 2])) # Test times start_of_scan = np.datetime64(datetime(2014, 1, 8, 11, 30)) times = instrument.times(start_of_scan) self.assertEquals(times[0, 1], start_of_scan) self.assertEquals(times[0, 0], start_of_scan - np.timedelta64(100, 'ms')) self.assertEquals(times[0, 2], start_of_scan + np.timedelta64(100, 'ms'))
def olci(scans_nb, scan_points=None): """Definition of the OLCI instrument. Source: Sentinel-3 OLCI Coverage https://sentinel.esa.int/web/sentinel/user-guides/sentinel-3-olci/coverage """ if scan_points is None: scan_len = 4000 # samples per scan scan_points = np.arange(4000) else: scan_len = len(scan_points) # scan_rate = 0.044 # single scan, seconds scan_angle_west = 46.5 # swath, degrees scan_angle_east = -22.1 # swath, degrees # sampling_interval = 18e-3 # single view, seconds # build the olci instrument scan line angles scanline_angles = np.linspace(np.deg2rad(scan_angle_west), np.deg2rad(scan_angle_east), scan_len) inst = np.vstack((scanline_angles, np.zeros(scan_len, ))) inst = np.tile(inst[:, np.newaxis, :], [1, np.int(scans_nb), 1]) # building the corresponding times array # times = (np.tile(scan_points * 0.000025 + 0.0025415, [scans_nb, 1]) # + np.expand_dims(offset, 1)) times = np.tile(np.zeros_like(scanline_angles), [np.int(scans_nb), 1]) # if apply_offset: # offset = np.arange(np.int(scans_nb)) * frequency # times += np.expand_dims(offset, 1) return ScanGeometry(inst, times)
def avhrr(scans_nb, scan_points, scan_angle=55.37, frequency=1 / 6.0, apply_offset=True): """Definition of the avhrr instrument. Source: NOAA KLM User's Guide, Appendix J http://www.ncdc.noaa.gov/oa/pod-guide/ncdc/docs/klm/html/j/app-j.htm """ # build the avhrr instrument (scan angles) avhrr_inst = np.vstack( ((scan_points / 1023.5 - 1) * np.deg2rad(-scan_angle), np.zeros((len(scan_points), )))) avhrr_inst = np.tile(avhrr_inst[:, np.newaxis, :], [1, np.int(scans_nb), 1]) # building the corresponding times array # times = (np.tile(scan_points * 0.000025 + 0.0025415, [scans_nb, 1]) # + np.expand_dims(offset, 1)) times = np.tile(scan_points * 0.000025, [np.int(scans_nb), 1]) if apply_offset: offset = np.arange(np.int(scans_nb)) * frequency times += np.expand_dims(offset, 1) return ScanGeometry(avhrr_inst, times)
def viirs(scans_nb, scan_indices=slice(0, None), chn_pixels=6400, scan_lines=32, scan_step=1): """Describe VIIRS instrument geometry, I-band by default. VIIRS scans several lines simultaneously (there are 16 detectors for each M-band, 32 detectors for each I-band) so the scan angles (and times) are two-dimensional arrays, contrary to AVHRR for example. scan_step: The increment in number of scans. E.g. if scan_step is 100 and the number of scans (scans_nb) is 10 then these 10 scans are distributed over the swath so that between each scan there are 99 emtpy (excluded) scans """ entire_width = np.arange(chn_pixels) scan_points = entire_width[scan_indices.astype('int')] scan_pixels = len(scan_points) # Initial angle 55.84 deg replaced with 56.28 deg found in # VIIRS User's Guide from NESDIS, version 1.2 (09/10/2013). # Ref : NOAA Technical Report NESDIS 142. # Seems to be better (not quantified). across_track = \ (scan_points / (chn_pixels / 2. - 0.5) - 1) * np.deg2rad(-56.28) y_max_angle = np.arctan2(11.87 / 2, 824.0) along_track = \ -(np.arange(scan_lines) / (scan_lines / 2. - 0.5) - 1) * \ y_max_angle scan = np.dstack( (np.tile(across_track, (scan_lines, 1)).T, np.tile(along_track, (scan_pixels, 1)))) npp = np.tile(scan, [scans_nb, 1]).T # from the timestamp in the filenames, a granule takes 1:25.400 to record # (85.4 seconds) so 1.779166667 would be the duration of 1 scanline (48 # scans per granule) dividing the duration of a single scan by a width of # 6400 pixels results in 0.0002779947917 seconds for each column of 32 # pixels in the scanline # the individual times per pixel are probably wrong, unless the scanning # behaves the same as for AVHRR, The VIIRS sensor rotates to allow internal # calibration before each scanline. This would imply that the scanline # always moves in the same direction. more info @ # http://www.eoportal.org/directory/pres_NPOESSNationalPolarorbitingOperationalEnvironmentalSatelliteSystem.html SEC_EACH_SCANCOLUMN = 0.0002779947917 sec_scan_duration = 1.779166667 times = np.tile(scan_points * SEC_EACH_SCANCOLUMN, [np.int32(scans_nb * scan_lines), 1]) offset = np.repeat( np.arange(scans_nb) * sec_scan_duration * scan_step, scan_lines) times += np.expand_dims(offset, 1) # build the scan geometry object return ScanGeometry(npp, times)
def mwhs2(scans_nb, scan_points=None): """Describe MWHS-2 instrument geometry The scanning period is 2.667 s. Main beams of the antenna scan over the ob- serving swath (±53.35◦ from nadir) in the cross-track direction at a constant time of 1.71 s. There are 98 pixels sampled per scan during 1.71s, and each sample has the same integration period. See: http://english.nssc.cas.cn/rh/rp/201501/W020150122580098790190.pdf Parameters: scans_nb | int - number of scan lines Keywords: * scan_points - FIXME! Returns: pyorbital.geoloc.ScanGeometry object """ scan_len = 98 # 98 samples per scan scan_rate = 8 / 3. # single scan, seconds scan_angle = -53.35 # swath, degrees sampling_interval = (8 / 3. - 1) / 98. # single view, seconds # sampling_interval = 17.449e-3 # single view, seconds sync_time = 0.0 # delay before the actual scan starts - don't know! FIXME! if scan_points is None: scan_points = np.arange(0, scan_len) # build the instrument (scan angles) samples = np.vstack( ((scan_points / (scan_len * 0.5 - 0.5) - 1) * np.deg2rad(scan_angle), np.zeros((len(scan_points), )))) samples = np.tile(samples[:, np.newaxis, :], [1, np.int32(scans_nb), 1]) # building the corresponding times array offset = np.arange(scans_nb) * scan_rate times = (np.tile(scan_points * sampling_interval + sync_time, [np.int32(scans_nb), 1]) + np.expand_dims(offset, 1)) # # build the instrument (scan angles) # scan_angles = np.linspace(-np.deg2rad(scan_angle), np.deg2rad(scan_angle), scan_len)[scan_points] # samples = np.vstack((scan_angles, np.zeros(len(scan_points) * 1,))) # samples = np.tile(samples[:, np.newaxis, :], [1, np.int(scans_nb), 1]) # # building the corresponding times array # offset = np.arange(scans_nb) * scan_rate # times = (np.tile(scan_points * sampling_interval, [np.int(scans_nb), 1]) # + np.expand_dims(offset, 1)) # build the scan geometry object return ScanGeometry(samples, times)
def mhs(scans_nb, scan_points=None): """ Describe MHS instrument geometry See: - https://www.eumetsat.int/website/home/Satellites/CurrentSatellites/Metop/MetopDesign/MHS/index.html - https://www1.ncdc.noaa.gov/pub/data/satellite/publications/podguides/ N-15%20thru%20N-19/pdf/0.0%20NOAA%20KLM%20Users%20Guide.pdf (NOAA KLM Users Guide –August 2014 Revision) Parameters: scans_nb | int - number of scan lines Keywords: * scan_points - FIXME! Returns: pyorbital.geoloc.ScanGeometry object """ scan_len = 90 # 90 samples per scan scan_rate = 8 / 3. # single scan, seconds scan_angle = -49.444 # swath, degrees sampling_interval = (8 / 3. - 1) / 90. # single view, seconds sync_time = 0.0 # delay before the actual scan starts - don't know! FIXME! if scan_points is None: scan_points = np.arange(0, scan_len) # build the instrument (scan angles) samples = np.vstack( ((scan_points / (scan_len * 0.5 - 0.5) - 1) * np.deg2rad(scan_angle), np.zeros((len(scan_points), )))) samples = np.tile(samples[:, np.newaxis, :], [1, np.int32(scans_nb), 1]) # building the corresponding times array offset = np.arange(scans_nb) * scan_rate times = (np.tile(scan_points * sampling_interval + sync_time, [np.int32(scans_nb), 1]) + np.expand_dims(offset, 1)) # scan_angles = np.linspace(-np.deg2rad(scan_angle), np.deg2rad(scan_angle), scan_len)[scan_points] # samples = np.vstack((scan_angles, np.zeros(len(scan_points) * 1,))) # samples = np.tile(samples[:, np.newaxis, :], [1, np.int(scans_nb), 1]) # # building the corresponding times array # offset = np.arange(scans_nb) * scan_rate # times = (np.tile(scan_points * sampling_interval, [np.int(scans_nb), 1]) # + np.expand_dims(offset, 1)) # build the scan geometry object return ScanGeometry(samples, times)
def test_scan_geometry(self): """Test the ScanGeometry object. """ instrument = ScanGeometry( np.deg2rad(np.array([[10, 0], [0, 0], [-10, 0]])), np.array([-0.1, 0, 0.1])) self.assertTrue( np.allclose(np.rad2deg(instrument.fovs[:, 0]), np.array([10, 0, -10]))) # Test vectors pos = np.array([[0, 0, 7000]]).T vel = np.array([[1, 0, 0]]).T vec = instrument.vectors(pos, vel) self.assertTrue(np.allclose(np.array([[0, 0, -1]]), vec[:, 1])) # minus sin because we use trigonometrical direction of angles self.assertTrue( np.allclose( np.array( [[0, -np.sin(np.deg2rad(10)), -np.cos(np.deg2rad(10))]]), vec[:, 0])) self.assertTrue( np.allclose( np.array( [[0, -np.sin(np.deg2rad(-10)), -np.cos(np.deg2rad(-10))]]), vec[:, 2])) # Test times start_of_scan = datetime(2014, 1, 8, 11, 30) times = instrument.times(start_of_scan) self.assertEqual(times[1], start_of_scan) self.assertEqual(times[0], start_of_scan - timedelta(seconds=0.1)) self.assertEqual(times[2], start_of_scan + timedelta(seconds=0.1))
def test_scan_geometry(self): """Test the ScanGeometry object. """ instrument = ScanGeometry(np.deg2rad(np.array([[10, 0], [0, 0], [-10, 0]])), np.array([-0.1, 0, 0.1])) self.assertTrue(np.allclose(np.rad2deg(instrument.fovs[:, 0]), np.array([10, 0, -10]))) # Test vectors pos = np.array([[0, 0, 7000]]).T vel = np.array([[1, 0, 0]]).T vec = instrument.vectors(pos, vel) self.assertTrue(np.allclose(np.array([[0, 0, -1]]), vec[:, 1])) # minus sin because we use trigonometrical direction of angles self.assertTrue(np.allclose(np.array([[0, -np.sin(np.deg2rad(10)), -np.cos(np.deg2rad(10))]]), vec[:, 0])) self.assertTrue(np.allclose(np.array([[0, -np.sin(np.deg2rad(-10)), -np.cos(np.deg2rad(-10))]]), vec[:, 2])) # Test times start_of_scan = datetime(2014, 1, 8, 11, 30) times = instrument.times(start_of_scan) self.assertEquals(times[1], start_of_scan) self.assertEquals(times[0], start_of_scan - timedelta(seconds=0.1)) self.assertEquals(times[2], start_of_scan + timedelta(seconds=0.1))
def viirs(scans_nb, scan_indices=slice(0, None), chn_pixels=6400, scan_lines=32): """Describe VIIRS instrument geometry, I-band by default. VIIRS scans several lines simultaneously (there are 16 detectors for each M-band, 32 detectors for each I-band) so the scan angles (and times) are two-dimensional arrays, contrary to AVHRR for example. """ entire_width = np.arange(chn_pixels) scan_points = entire_width[scan_indices] scan_pixels = len(scan_points) ''' initial angle 55.84 deg replaced with 56.28 deg found in VIIRS User's Guide from NESDIS, version 1.2 (09/10/2013). Ref : NOAA Technical Report NESDIS 142. Seems to be better (not quantified)''' across_track = \ (scan_points / (chn_pixels / 2. - 0.5) - 1) * np.deg2rad(-56.28) y_max_angle = np.arctan2(11.87 / 2, 824.0) along_track = \ -(np.arange(scan_lines) / (scan_lines / 2. - 0.5) - 1) * \ y_max_angle scan = np.dstack( (np.tile(across_track, (scan_lines, 1)).T, np.tile(along_track, (scan_pixels, 1)))) npp = np.tile(scan, [scans_nb, 1]).T # from the timestamp in the filenames, a granule takes 1:25.400 to record # (85.4 seconds) so 1.779166667 would be the duration of 1 scanline # dividing the duration of a single scan by a width of 6400 pixels results # in 0.0002779947917 seconds for each column of 32 pixels in the scanline # the individual times per pixel are probably wrong, unless the scanning # behaves the same as for AVHRR, The VIIRS sensor rotates to allow internal # calibration before each scanline. This would imply that the scanline # always moves in the same direction. more info @ # http://www.eoportal.org/directory/pres_NPOESSNationalPolarorbitingOperationalEnvironmentalSatelliteSystem.html offset = np.arange(scans_nb) * 1.779166667 times = (np.tile(scan_points * 0.0002779947917, [np.int(scan_lines), np.int(scans_nb)]) + np.expand_dims(offset, 1)) # build the scan geometry object return ScanGeometry(npp, times)
def atms(scans_nb, edges_only=False): """ Describe MHS instrument geometry See: - https://dtcenter.org/com-GSI/users/docs/presentations/2013_workshop/ Garrett_GSI_2013.pdf (Assimilation of Suomi-NPP ATMS, Kevin Garrett et al., August 8, 2013) - https://www.star.nesdis.noaa.gov/star/documents/meetings/2016JPSSAnnual/ S4/S4_13_JPSSScience2016_session4Part2_ATMS_Scan_Reversal_HYANG.pdf (Suomi NPP ATMS Scan Reversal Study, Hu (Tiger) Yang, NOAA/STAR ATMS SDR Working Group) Parameters: scans_nb | int - number of scan lines Keywords: * edges_only - use only edge pixels Returns: pyorbital.geoloc.ScanGeometry object """ scan_len = 96 # 96 samples per scan scan_rate = 8 / 3. # single scan, seconds scan_angle = -52.7 # swath, degrees sampling_interval = 18e-3 # single view, seconds if edges_only: scan_points = np.array([0, scan_len - 1]) else: scan_points = np.arange(0, scan_len) # build the instrument (scan angles) samples = np.vstack( ((scan_points / (scan_len * 0.5 - 0.5) - 1) * np.deg2rad(scan_angle), np.zeros((len(scan_points), )))) samples = np.tile(samples[:, np.newaxis, :], [1, np.int(scans_nb), 1]) # building the corresponding times array offset = np.arange(scans_nb) * scan_rate times = (np.tile(scan_points * sampling_interval, [np.int(scans_nb), 1]) + np.expand_dims(offset, 1)) # build the scan geometry object return ScanGeometry(samples, times)
def mhs(scans_nb, edges_only=False): """ Describe MHS instrument geometry See: - https://www.eumetsat.int/website/home/Satellites/CurrentSatellites/Metop/MetopDesign/MHS/index.html - https://www1.ncdc.noaa.gov/pub/data/satellite/publications/podguides/ N-15%20thru%20N-19/pdf/0.0%20NOAA%20KLM%20Users%20Guide.pdf (NOAA KLM Users Guide –August 2014 Revision) Parameters: scans_nb | int - number of scan lines Keywords: * edges_only - use only edge pixels Returns: pyorbital.geoloc.ScanGeometry object """ scan_len = 90 # 90 samples per scan scan_rate = 8 / 3. # single scan, seconds scan_angle = -49.444 # swath, degrees sampling_interval = (8 / 3. - 1) / 90. # single view, seconds if edges_only: scan_points = np.array([0, scan_len - 1]) else: scan_points = np.arange(0, scan_len) # build the instrument (scan angles) samples = np.vstack( ((scan_points / (scan_len * 0.5 - 0.5) - 1) * np.deg2rad(scan_angle), np.zeros((len(scan_points), )))) samples = np.tile(samples[:, np.newaxis, :], [1, np.int(scans_nb), 1]) # building the corresponding times array offset = np.arange(scans_nb) * scan_rate times = (np.tile(scan_points * sampling_interval, [np.int(scans_nb), 1]) + np.expand_dims(offset, 1)) # build the scan geometry object return ScanGeometry(samples, times)
def hirs4(scans_nb, scan_points=None): """Describe HIRS/4 instrument geometry. See: - https://www.eumetsat.int/website/home/Satellites/CurrentSatellites/Metop/MetopDesign/HIRS/index.html - https://www1.ncdc.noaa.gov/pub/data/satellite/publications/podguides/ N-15%20thru%20N-19/pdf/0.0%20NOAA%20KLM%20Users%20Guide.pdf (NOAA KLM Users Guide –August 2014 Revision) Parameters: scans_nb | int - number of scan lines Keywords: * scan_points - FIXME! Returns: pyorbital.geoloc.ScanGeometry object """ scan_len = 56 # 56 samples per scan scan_rate = 6.4 # single scan, seconds scan_angle = -49.5 # swath, degrees sampling_interval = abs(scan_rate) / scan_len # single view, seconds if scan_points is None: scan_points = np.arange(0, scan_len) # build the instrument (scan angles) samples = np.vstack( ((scan_points / (scan_len * 0.5 - 0.5) - 1) * np.deg2rad(scan_angle), np.zeros((len(scan_points), )))) samples = np.tile(samples[:, np.newaxis, :], [1, np.int32(scans_nb), 1]) # building the corresponding times array offset = np.arange(scans_nb) * scan_rate times = ( np.tile(scan_points * sampling_interval, [np.int32(scans_nb), 1]) + np.expand_dims(offset, 1)) # build the scan geometry object return ScanGeometry(samples, times)
def avhrr(scans_nb, scan_points, scan_angle=55.37, decimate=1): """Definition of the avhrr instrument. Source: NOAA KLM User's Guide, Appendix J http://www.ncdc.noaa.gov/oa/pod-guide/ncdc/docs/klm/html/j/app-j.htm """ # build the avhrr instrument (scan angles) avhrr_inst = np.vstack( ((scan_points / 1023.5 - 1) * np.deg2rad(-scan_angle), np.zeros((len(scan_points), )))).transpose() avhrr_inst = np.tile(avhrr_inst, [scans_nb, 1]) # building the corresponding times array offset = np.arange(scans_nb) * decimate / 6.0 #times = (np.tile(scan_points * 0.000025 + 0.0025415, [scans_nb, 1]) # + np.expand_dims(offset, 1)) times = (np.tile(scan_points * 0.000025, [scans_nb, 1]) + np.expand_dims(offset, 1)) return ScanGeometry(avhrr_inst, times.ravel())
def ascat(scan_nb, scan_points=None): """ASCAT make two scans one to the left and one to the right of the sub-satellite track. """ if scan_points is None: scan_len = 42 # samples per scan scan_points = np.arange(42) else: scan_len = len(scan_points) scan_angle_inner = -25.0 # swath, degrees scan_angle_outer = -53.0 # swath, degrees scan_rate = 3.74747474747 # single scan, seconds if scan_len < 2: raise ValueError("Need at least two scan points!") sampling_interval = scan_rate / float(np.max(scan_points) + 1) # build the Metop/ascat instrument scan line angles scanline_angles_one = np.linspace(-np.deg2rad(scan_angle_outer), -np.deg2rad(scan_angle_inner), 21) scanline_angles_two = np.linspace(np.deg2rad(scan_angle_inner), np.deg2rad(scan_angle_outer), 21) scan_angles = np.concatenate([scanline_angles_one, scanline_angles_two])[scan_points] inst = np.vstack((scan_angles, np.zeros(scan_len * 1, ))) inst = np.tile(inst[:, np.newaxis, :], [1, np.int(scan_nb), 1]) # building the corresponding times array offset = np.arange(scan_nb) * scan_rate times = (np.tile(scan_points * sampling_interval, [np.int(scan_nb), 1]) + np.expand_dims(offset, 1)) return ScanGeometry(inst, times)
def amsua(scans_nb, edges_only=False): """ Describe AMSU-A instrument geometry Parameters: scans_nb | int - number of scan lines Keywords: * edges_only - use only edge pixels Returns: pyorbital.geoloc.ScanGeometry object """ scan_len = 30 # 30 samples per scan scan_rate = 8 # single scan, seconds scan_angle = -48.3 # swath, degrees sampling_interval = 0.2 # single view, seconds sync_time = 0.00355 # delay before the actual scan starts if edges_only: scan_points = np.array([0, scan_len - 1]) else: scan_points = np.arange(0, scan_len) # build the instrument (scan angles) samples = np.vstack( ((scan_points / (scan_len * 0.5 - 0.5) - 1) * np.deg2rad(scan_angle), np.zeros((len(scan_points), )))).transpose() samples = np.tile(samples, [scans_nb, 1]) # building the corresponding times array offset = np.arange(scans_nb) * scan_rate times = ( np.tile(scan_points * sampling_interval + sync_time, [scans_nb, 1]) + np.expand_dims(offset, 1)) # build the scan geometry object return ScanGeometry(samples, times.ravel())
def avhrr_gac(scan_times, scan_points, scan_angle=55.37, frequency=0.5): """Definition of the avhrr instrument, gac version Source: NOAA KLM User's Guide, Appendix J http://www.ncdc.noaa.gov/oa/pod-guide/ncdc/docs/klm/html/j/app-j.htm """ try: offset = np.array([(t - scan_times[0]).seconds + (t - scan_times[0]).microseconds / 1000000.0 for t in scan_times]) except TypeError: offset = np.arange(scan_times) * frequency scans_nb = len(offset) # build the avhrr instrument (scan angles) avhrr_inst = np.vstack(((scan_points / 1023.5 - 1) * np.deg2rad(-scan_angle), np.zeros((len(scan_points),)))).transpose() avhrr_inst = np.tile(avhrr_inst, [scans_nb, 1]) # building the corresponding times array times = (np.tile(scan_points * 0.000025, [scans_nb, 1]) + np.expand_dims(offset, 1)) return ScanGeometry(avhrr_inst, times.ravel())
def amsua(scans_nb, scan_points=None): """ Describe AMSU-A instrument geometry Parameters: scans_nb | int - number of scan lines Keywords: * scan_points - FIXME! Returns: pyorbital.geoloc.ScanGeometry object """ scan_len = 30 # 30 samples per scan scan_rate = 8 # single scan, seconds scan_angle = -48.3 # swath, degrees sampling_interval = 0.2 # single view, seconds sync_time = 0.00355 # delay before the actual scan starts if scan_points is None: scan_points = np.arange(0, scan_len) # build the instrument (scan angles) samples = np.vstack( ((scan_points / (scan_len * 0.5 - 0.5) - 1) * np.deg2rad(scan_angle), np.zeros((len(scan_points), )))) samples = np.tile(samples[:, np.newaxis, :], [1, np.int32(scans_nb), 1]) # building the corresponding times array offset = np.arange(scans_nb) * scan_rate times = (np.tile(scan_points * sampling_interval + sync_time, [np.int32(scans_nb), 1]) + np.expand_dims(offset, 1)) # build the scan geometry object return ScanGeometry(samples, times)
def viirs(scans_nb, scan_indices=slice(0, None)): """Describe VIIRS instrument geometry, I-band. """ entire_width = np.arange(6400) scan_points = entire_width[scan_indices] across_track = (scan_points / 3199.5 - 1) * np.deg2rad(-55.84) y_max_angle = np.arctan2(11.87 / 2, 824.0) along_track = np.array([-y_max_angle, 0, y_max_angle]) scan_pixels = len(scan_points) scan = np.vstack((np.tile(across_track, scan_pixels), np.repeat(along_track, 6400))).T npp = np.tile(scan, [scans_nb, 1]) # from the timestamp in the filenames, a granule takes 1:25.400 to record # (85.4 seconds) so 1.779166667 would be the duration of 1 scanline # dividing the duration of a single scan by a width of 6400 pixels results # in 0.0002779947917 seconds for each column of 32 pixels in the scanline # the individual times per pixel are probably wrong, unless the scanning # behaves the same as for AVHRR, The VIIRS sensor rotates to allow internal # calibration before each scanline. This would imply that the scanline # always moves in the same direction. more info @ # http://www.eoportal.org/directory/pres_NPOESSNationalPolarorbitingOperationalEnvironmentalSatelliteSystem.html offset = np.arange(scans_nb) * 1.779166667 times = (np.tile(scan_points * 0.0002779947917, [scans_nb, scan_pixels]) + np.expand_dims(offset, 1)) # build the scan geometry object return ScanGeometry(npp, times.ravel())
# we take only every 40th point for plotting clarity scan_points = np.arange(24, 2048, 40) # build the avhrr instrument (scan angles) avhrr = np.vstack(((scan_points - 1023.5) / 1024 * np.deg2rad(-55.37), np.zeros((len(scan_points),)))).transpose() avhrr = np.tile(avhrr, [scanline_nb, 1]) # building the corresponding times array offset = np.arange(scanline_nb) * 0.1666667 times = (np.tile(scan_points * 0.000025 + 0.0025415, [scanline_nb, 1]) + np.expand_dims(offset, 1)) # build the scan geometry object sgeom = ScanGeometry(avhrr, times.ravel()) # roll, pitch, yaw in radians rpy = (0, 0, 0) # print the lonlats for the pixel positions s_times = sgeom.times(t) pixels_pos = compute_pixels((tle1, tle2), sgeom, s_times, rpy) pos_time = get_lonlatalt(pixels_pos, s_times) print pos_time # Plot the result from mpl_toolkits.basemap import Basemap import matplotlib.pyplot as plt
# we take only every 40th point for plotting clarity scan_points = np.arange(24, 2048, 40) # build the avhrr instrument (scan angles) avhrr = np.vstack(((scan_points - 1023.5) / 1024 * np.deg2rad(-55.37), np.zeros((len(scan_points), )))).transpose() avhrr = np.tile(avhrr, [scanline_nb, 1]) # building the corresponding times array offset = np.arange(scanline_nb) * 0.1666667 times = (np.tile(scan_points * 0.000025 + 0.0025415, [scanline_nb, 1]) + np.expand_dims(offset, 1)) # build the scan geometry object sgeom = ScanGeometry(avhrr, times.ravel()) # roll, pitch, yaw in radians rpy = (0, 0, 0) # print the lonlats for the pixel positions s_times = sgeom.times(t) pixels_pos = compute_pixels((tle1, tle2), sgeom, s_times, rpy) pos_time = get_lonlatalt(pixels_pos, s_times) print(pos_time) # Plot the result m = Basemap(projection='stere', llcrnrlat=24, urcrnrlat=70,