def __init__(self, satellite, risetime, falltime, **kwargs): SimplePass.__init__(self, satellite, risetime, falltime) logger.debug("kwargs: %s", str(kwargs)) orb = kwargs.get('orb', None) uptime = kwargs.get('uptime', None) instrument = kwargs.get('instrument', None) tle1 = kwargs.get('tle1', None) tle2 = kwargs.get('tle2', None) logger.debug("instrument: %s", str(instrument)) if isinstance(instrument, (list, set)): if 'avhrr' in instrument: logger.warning("Instrument is a sequence! Assume avhrr...") instrument = 'avhrr' elif 'viirs' in instrument: logger.warning("Instrument is a sequence! Assume viirs...") instrument = 'viirs' elif 'modis' in instrument: logger.warning("Instrument is a sequence! Assume modis...") instrument = 'modis' elif 'mersi' in instrument: logger.warning("Instrument is a sequence! Assume mersi...") instrument = 'mersi' elif 'mersi-2' in instrument: logger.warning("Instrument is a sequence! Assume mersi-2...") instrument = 'mersi-2' else: raise TypeError( "Instrument is a sequence! Don't know which one to choose!" ) default = NUMBER_OF_FOVS.get(instrument, 2048) self.number_of_fovs = kwargs.get('number_of_fovs', default) # The frequency shouldn't actualy depend on the number of FOVS along a scanline should it!? # frequency = kwargs.get('frequency', int(self.number_of_fovs / 4)) frequency = kwargs.get('frequency', 300) self.station = None self.max_elev = None self.uptime = uptime or (risetime + (falltime - risetime) / 2) self.instrument = instrument self.frequency = frequency if orb: self.orb = orb else: try: self.orb = orbital.Orbital(satellite, line1=tle1, line2=tle2) except KeyError as err: logger.debug('Failed in PyOrbital: %s', str(err)) self.orb = orbital.Orbital(NOAA20_NAME.get( satellite, satellite), line1=tle1, line2=tle2) logger.info('Using satellite name %s instead', str(NOAA20_NAME.get(satellite, satellite))) self._boundary = None
def get_npp_orbit_number(obstime): """Get the orbit number for the Suomi NPP RDR/SDR file given the observation start time. The orbit number""" sat = orb.Orbital('SUOMI NPP') return sat.get_orbit_number(obstime)
def test_get_equatorial_crossing_time(self, get_orbit_number, utc2local): def get_orbit_number_patched(utc_time, **kwargs): utc_time = np.datetime64(utc_time) diff = (utc_time - np.datetime64('2009-07-01 12:38:12')) / np.timedelta64( 7200, 's') return 1234 + diff get_orbit_number.side_effect = get_orbit_number_patched utc2local.return_value = 'local_time' sat = orbital.Orbital("METOP-A", line1="1 29499U 06044A 13060.48822809 " ".00000017 00000-0 27793-4 0 9819", line2="2 29499 98.6639 121.6164 0001449 " "71.9056 43.3132 14.21510544330271") # Ascending node res = sat.get_equatorial_crossing_time(tstart=datetime(2009, 7, 1, 12), tend=datetime(2009, 7, 1, 13)) exp = datetime(2009, 7, 1, 12, 38, 12) self.assertTrue((res - exp) < timedelta(seconds=0.01)) # Descending node res = sat.get_equatorial_crossing_time(tstart=datetime(2009, 7, 1, 12), tend=datetime( 2009, 7, 1, 14, 0), node='descending') exp = datetime(2009, 7, 1, 13, 38, 12) self.assertTrue((res - exp) < timedelta(seconds=0.01)) # Conversion to local time res = sat.get_equatorial_crossing_time(tstart=datetime(2009, 7, 1, 12), tend=datetime(2009, 7, 1, 14), local_time=True) self.assertEqual(res, 'local_time')
def test_get_orbit_number(self): """Testing getting the orbitnumber from the tle""" sat = orbital.Orbital("NPP", line1="1 37849U 11061A 12017.90990040 -.00000112 00000-0 -32693-4 0 772", line2="2 37849 98.7026 317.8811 0001845 92.4533 267.6830 14.19582686 11574") dobj = datetime(2012, 1, 18, 8, 4, 19) orbnum = sat.get_orbit_number(dobj) self.assertEqual(orbnum, 1163)
def test_orbit_num_an(self): sat = orbital.Orbital("METOP-A", line1="1 29499U 06044A 11254.96536486 " ".00000092 00000-0 62081-4 0 5221", line2="2 29499 98.6804 312.6735 0001758 " "111.9178 248.2152 14.21501774254058") d = datetime(2011, 9, 14, 5, 30) self.assertEqual(sat.get_orbit_number(d), 25437)
def test_orbit_num_non_an(self): sat = orbital.Orbital("METOP-A", line1="1 29499U 06044A 13060.48822809 " ".00000017 00000-0 27793-4 0 9819", line2="2 29499 98.6639 121.6164 0001449 " "71.9056 43.3132 14.21510544330271") dt = np.timedelta64(98, 'm') self.assertEqual(sat.get_orbit_number(sat.tle.epoch + dt), 33028)
def test_utc2local(self, get_lonlatalt): get_lonlatalt.return_value = -45, None, None sat = orbital.Orbital("METOP-A", line1="1 29499U 06044A 13060.48822809 " ".00000017 00000-0 27793-4 0 9819", line2="2 29499 98.6639 121.6164 0001449 " "71.9056 43.3132 14.21510544330271") self.assertEqual(sat.utc2local(datetime(2009, 7, 1, 12)), datetime(2009, 7, 1, 9))
def get_npp_orbit_number(obstime): """Get the orbit number for the Suomi NPP RDR/SDR file given the observation start time. The orbit number""" deltat = timedelta(days=1) datestr = obstime.strftime('%Y%m%d') try: sat = orb.Orbital('SUOMI NPP', tle_file=os.path.join(TLEDIR, 'tle-%s.txt' % datestr)) except IOError: datestr = (obstime - deltat).strftime('%Y%m%d') sat = orb.Orbital('SUOMI NPP', tle_file=os.path.join(TLEDIR, 'tle-%s.txt' % datestr)) orbit = sat.get_orbit_number(obstime) return orbit
def test_observer_look(self): sat = orbital.Orbital("ISS (ZARYA)", line1="1 25544U 98067A 03097.78853147 .00021906 00000-0 28403-3 0 8652", line2="2 25544 51.6361 13.7980 0004256 35.6671 59.2566 15.58778559250029") d = datetime(2003, 3, 23, 0, 3, 22) az, el = sat.get_observer_look(d, -84.39733, 33.775867, 0) expected_az = 122.45169655331965 expected_el = 1.9800219611255456 self.assertTrue(np.abs(az - expected_az) < eps_deg, 'Calculation of azimut failed') self.assertTrue(np.abs(el - expected_el) < eps_deg, 'Calculation of elevation failed')
def __init__(self, path, duration): self.lat = 55.8667 self.lon = -4.4333 self.alt = 125 self.duration = duration f = open("%s" % path, 'r') sat = f.readline() line1 = f.readline() line2 = f.readline() self.orb = orbital.Orbital(sat, path, line1, line2)
def test_get_next_passes_issue_22(self): """Check that max""" line1 = '1 28654U 05018A 21083.16603416 .00000102 00000-0 79268-4 0 9999' line2 = '2 28654 99.0035 147.6583 0014816 159.4931 200.6838 14.12591533816498' orb = orbital.Orbital("NOAA 18", line1=line1, line2=line2) t = datetime(2021, 3, 9, 22) next_passes = orb.get_next_passes(t, 1, -15.6335, 27.762, 0.) rise, fall, max_elevation = next_passes[0] assert rise < max_elevation < fall print(next_passes)
def test_get_next_passes_apogee(self): """Regression test #22.""" line1 = "1 24793U 97020B 18065.48735489 .00000075 00000-0 19863-4 0 9994" line2 = "2 24793 86.3994 209.3241 0002020 89.8714 270.2713 14.34246429 90794" orb = orbital.Orbital('IRIDIUM 7 [+]', line1=line1, line2=line2) d = datetime(2018, 3, 7, 3, 30, 15) res = orb.get_next_passes(d, 1, 170.556, -43.368, 0.5, horizon=40) self.assertTrue( abs(res[0][2] - datetime(2018, 3, 7, 3, 48, 13, 178439)) < timedelta( seconds=0.01))
def test_sublonlat(self): sat = orbital.Orbital("ISS (ZARYA)", line1="1 25544U 98067A 03097.78853147 .00021906 00000-0 28403-3 0 8652", line2="2 25544 51.6361 13.7980 0004256 35.6671 59.2566 15.58778559250029") d = datetime(2003, 3, 23, 0, 3, 22) lon, lat, alt = sat.get_lonlatalt(d) expected_lon = -68.199894472013213 expected_lat = 23.159747677881075 expected_alt = 392.01953430856935 self.assertTrue(np.abs(lon - expected_lon) < eps_deg, 'Calculation of sublon failed') self.assertTrue(np.abs(lat - expected_lat) < eps_deg, 'Calculation of sublat failed') self.assertTrue(np.abs(alt - expected_alt) < eps_deg, 'Calculation of altitude failed')
def get_passes(ground_cor, alt, satellite_name, start_time, length, min_angle): satellite = orbital.Orbital(satellite_name) passes = satellite.get_next_passes(start_time + timedelta(seconds=1), length, ground_cor[1], ground_cor[0], alt) ret = [] for line in passes: angle = (satellite.get_observer_look(line[2], ground_cor[1], ground_cor[0], alt))[1] if (angle >= (float)(min_angle)): p = [line[0], line[1] - line[0]] p.append(angle) ret.append(p) return ret
def test_orbit_num_equator(self): sat = orbital.Orbital("SUOMI NPP", line1="1 37849U 11061A 13061.24611272 .00000048 00000-0 43679-4 0 4334", line2="2 37849 98.7444 1.0588 0001264 63.8791 102.8546 14.19528338 69643") t1 = datetime(2013, 3, 2, 22, 2, 25) t2 = datetime(2013, 3, 2, 22, 2, 26) on1 = sat.get_orbit_number(t1) on2 = sat.get_orbit_number(t2) self.assertEqual(on1, 6973) self.assertEqual(on2, 6974) pos1, vel1 = sat.get_position(t1, normalize=False) pos2, vel2 = sat.get_position(t2, normalize=False) del vel1, vel2 self.assertTrue(pos1[2] < 0) self.assertTrue(pos2[2] > 0)
def get_metop_orbit(satellite, timestamp): from sat_schedules import fetch_tle from pyorbital import orbital satnames = {'M01': 'METOP-B', 'M02': 'METOP-A', 'M03': 'METOP-C'} try: satname = satnames[satellite] except KeyError: print >> sys.stderr, "ERROR, This 'get_metop_orbit' only work for METOP satellites" return 0 tles = fetch_tle.get_tle(timestamp) if not tles: return 0 l1, l2 = tles.get(satname) orb = orbital.Orbital(satname, line1=l1, line2=l2) return orb.get_orbit_number(timestamp, tbus_style=True)
def __init__(self, tle, orbitOffset): self.tle = tle self.orbitOffset = orbitOffset (name, line1, line2) = tle.split("\n")[0:3] name = name.strip() line1 = line1.strip() line2 = line2.strip() self.name = name self.line1 = line1 self.line2 = line2 yyyy = "20" + line1[18:20] yday = line1[20:32] self.epoch = ephem.Date(ephem.Date(yyyy + "/1/1") + float(yday) - 1.0) # For ephem self.sat = ephem.readtle(name, line1, line2) # For pyorbital (to get orbit number) self.osat = orbital.Orbital(name, line1=line1, line2=line2)
def add_product(dcm, filename): info = filename.split('_') satname = info[0] orbit = int(info[3]) time_start = datetime.strptime(info[1] + info[2], '%Y%m%d%H%M') time_end = time_start + timedelta(minutes=3) ft = dcm.get_file_type('PPS_cloud_type_granule') ff = dcm.get_file_format('HDF5') nf = dcm.create_file(filename, file_type=ft, file_format=ff) p = dcm.get_parameter('time_start') pv = dcm.create_parameter_value(time_start.isoformat(), file_obj=nf, parameter=p) p = dcm.get_parameter('time_end') pv = dcm.create_parameter_value(time_end.isoformat(), file_obj=nf, parameter=p) p = dcm.get_parameter('orbit_number') pv = dcm.create_parameter_value(orbit, file_obj=nf, parameter=p) p = dcm.get_parameter('satellite_name') pv = dcm.create_parameter_value(satname, file_obj=nf, parameter=p) sat = orbital.Orbital(sat_lookup.get(satname, satname), tle_file=get_latest_tle()) dt = timedelta(seconds=10) print time_start current_time = time_start lonlat_list = [] while current_time <= time_end: pos = sat.get_lonlatalt(current_time) lonlat_list.append(pos[:2]) current_time += dt value = 'LINESTRING (' for i, item in enumerate(lonlat_list): if i == 0: value += '%s %s' % (item[0], item[1]) else: value += ' ,%s %s' % (item[0], item[1]) value += ')' wkt_o = shapely.wkt.loads(value) p_track = dcm.get_parameter('sub_satellite_track') pls = dcm.create_parameter_linestring(wkt_o, file_obj=nf, parameter=p_track) dcm.save()
def granule_inside_area(start_time, end_time, platform_name, area_def): """Check if the IASI granule is over area interest, using the times from the filename """ metop = orbital.Orbital(PLATFORMS.get(platform_name, platform_name)) corners = area_def.corners is_inside = False for dtobj in [start_time, end_time]: lon, lat, dummy = metop.get_lonlatalt(dtobj) point = Coordinate(lon, lat) if point_inside(point, corners): is_inside = True break return is_inside
def test_get_next_passes_tricky(self): """ Check issue #34 for reference """ line1 = "1 43125U 18004Q 18251.42128650 " \ "+.00001666 +00000-0 +73564-4 0 9991" line2 = "2 43125 097.5269 314.3317 0010735 "\ "157.6344 202.5362 15.23132245036381" orb = orbital.Orbital('LEMUR-2-BROWNCOW', line1=line1, line2=line2) d = datetime(2018, 9, 8) res = orb.get_next_passes(d, 72, -8.174163, 51.953319, 0.05, horizon=5) self.assertTrue(abs( res[0][2] - datetime(2018, 9, 8, 9, 5, 46, 375248)) < timedelta(seconds=0.01)) self.assertTrue(abs( res[-1][2] - datetime(2018, 9, 10, 22, 15, 3, 143469)) < timedelta(seconds=0.01)) self.assertTrue(len(res) == 15)
def lambda_handler(event, context): tle_path = '/tmp/tle' now = datetime.utcnow() with open('./awesome_satellites.json') as file_data: awesome_satellites = json.load(file_data) tlefile.fetch(tle_path) for satellite in awesome_satellites: sat_orbital = orbital.Orbital(satellite['name'], tle_file=tle_path) next_passes = sat_orbital.get_next_passes(now, 24, event['lon'], event['lat'], event['alt']) for next_pass in next_passes: (start, end, maximum) = next_pass publish_sns({ 'satellite': satellite, 'pass_begin': start.isoformat(), 'pass_end': end.isoformat() })
def get_next_passes(satellites, utctime, forward, coords, tle_file=None, aqua_terra_dumps=None, min_pass=MIN_PASS, local_horizon=0): """Get the next passes for *satellites*, starting at *utctime*, for a duration of *forward* hours, with observer at *coords* ie lon (°E), lat (°N), altitude (km). Uses *tle_file* if provided, downloads from celestrack otherwise. Metop-A, Terra and Aqua need special treatment due to downlink restrictions. """ passes = {} if tle_file is None and 'TLES' not in os.environ: fp_, tle_file = mkstemp(prefix="tle", dir="/tmp") os.close(fp_) logger.info("Fetch tle info from internet") tlefile.fetch(tle_file) if not os.path.exists(tle_file) and 'TLES' not in os.environ: logger.info("Fetch tle info from internet") tlefile.fetch(tle_file) for sat in satellites: if not hasattr(sat, 'name'): from trollsched.schedule import Satellite sat = Satellite(sat, 0, 0) satorb = orbital.Orbital(sat.name, tle_file=tle_file) passlist = satorb.get_next_passes(utctime, forward, horizon=local_horizon, *coords) if sat.name.lower() == "metop-a": # Take care of metop-a special case passes["metop-a"] = get_metopa_passes(sat, passlist, satorb) elif sat.name.lower() in ["aqua", "terra"] and aqua_terra_dumps: # Take care of aqua (dumps in svalbard and poker flat) # Get the Terra/Aqua passes and fill the passes dict: get_terra_aqua_passes(passes, utctime, forward, sat, passlist, satorb, aqua_terra_dumps) else: if sat.name.upper() in VIIRS_PLATFORM_NAMES: instrument = "viirs" elif sat.name.lower().startswith( "metop") or sat.name.lower().startswith("noaa"): instrument = "avhrr" elif sat.name.lower() in ["aqua", "terra"]: # when aqua_terra_dumps=False instrument = "modis" elif sat.name.upper() in MERSI_PLATFORM_NAMES: instrument = "mersi" elif sat.name.upper() in MERSI2_PLATFORM_NAMES: instrument = "mersi-2" else: instrument = "unknown" passes[sat.name] = [ Pass(sat, rtime, ftime, orb=satorb, uptime=uptime, instrument=instrument) for rtime, ftime, uptime in passlist if ftime - rtime > timedelta(minutes=MIN_PASS) ] return set(fctools_reduce(operator.concat, list(passes.values())))
# --------------------------------------------------------------------------- # # Read command line arguments argv = sys.argv if len(argv) < 2: print "Usage: python orbit.py <TLE_FILENAME>" TLE_FILENAME = argv[1] CALC_START = datetime.utcnow() CALC_PERIOD = 12 * 3600 CALC_RESOLUTION = 30 OBSERVATOR = (51.049754, 13.757227, 92.0) # --------------------------------------------------------------------------- # SATNAME = os.path.basename(TLE_FILENAME)[0:-4] orbit = orbital.Orbital(SATNAME, TLE_FILENAME) OBSERV_PARAM = (OBSERVATOR[1], OBSERVATOR[0], OBSERVATOR[2]) # --------------------------------------------------------------------------- # # calculate all positions calculated = [] startTimestamp = time.mktime(CALC_START.timetuple()) startDatetime = CALC_START incTimestamp = CALC_RESOLUTION incDatetime = timedelta(seconds=CALC_RESOLUTION) endTimestamp = startTimestamp + CALC_PERIOD nowDatetime = CALC_START nowTimestamp = startTimestamp while nowTimestamp < endTimestamp: coordSpherical = orbit.get_lonlatalt(nowDatetime) coordObserver = orbit.get_observer_look(nowDatetime, *OBSERV_PARAM)
def get_orbitnumbers_to_nppfile(npp_file): """Browse the RDR/SDR file and get granule start/end times, and determine the correct orbit numbers for those times, to be later corrected in the file.""" fobj = h5py.File(npp_file, 'r') # First get all start and end date/time of the granules: obstimes = {} start_obstime = None end_obstime = None for group in fobj['/Data_Products'].keys(): for dset in fobj['/Data_Products'][group]: # Get begining and ending date/time: for begin_end in ['Beginning', 'Ending']: try: time_key = 'Aggregate' + begin_end + 'Time' date_key = 'Aggregate' + begin_end + 'Date' x_date = fobj['/Data_Products'][group][dset].attrs[ date_key] x_time = fobj['/Data_Products'][group][dset].attrs[ time_key] if not start_obstime and begin_end == 'Beginning': # Ex.: '20120405'+'021645' datetime_str = (x_date[0][0] + x_time[0][0].split('.')[0]) start_obstime = datetime.strptime( datetime_str, '%Y%m%d%H%M%S') if not end_obstime and begin_end == 'Ending': # Ex.: '20120405'+'021645' datetime_str = (x_date[0][0] + x_time[0][0].split('.')[0]) end_obstime = datetime.strptime( datetime_str, '%Y%m%d%H%M%S') except KeyError: time_key = begin_end + '_Time' date_key = begin_end + '_Date' x_date = fobj['/Data_Products'][group][dset].attrs[ date_key] x_time = fobj['/Data_Products'][group][dset].attrs[ time_key] datetime_str = (x_date[0][0] + x_time[0][0].split('.')[0]) obstimes[group + dset + begin_end] = datetime.strptime( datetime_str, '%Y%m%d%H%M%S') fobj.close() if not start_obstime and not end_obstime: raise IOError("Failed getting the granule start and end times") # Check for no date (1958) problem: dt1958 = datetime(1958, 1, 1) if abs(start_obstime - dt1958) < timedelta(days=2): print("Start time wrong: %s" % start_obstime.strftime('%Y%m%d')) print("Will use the end time to determine orbit number") if abs(end_obstime - dt1958) < timedelta(days=2): raise IOError("Both start time and end time is far off in file!") obstime = end_obstime else: obstime = start_obstime sat = orb.Orbital('SUOMI NPP') # Get the start orbit number: orbits = {} start_orbnum = sat.get_orbit_number(obstime) orbits['start'] = start_orbnum # Get all orbit numbers for the swath. # Check for erroneous date-times (1958): prev_okay_obstime = obstime for key in obstimes: if abs(obstimes[key] - dt1958) < timedelta(days=2): obstime = prev_okay_obstime else: obstime = obstimes[key] orbits[key] = sat.get_orbit_number(obstime) print("Orbit numbers in swath:") for key in obstimes: print(orbits[key], ) print() return orbits
def cubesat_t(cubesat, x): TCP_IP = '127.0.0.1' TCP_PORT = 5005 BUFFER_SIZE = 1024 s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) if x == 1: s.connect((TCP_IP, TCP_PORT)) response = urllib2.urlopen( 'http://celestrak.com/NORAD/elements/cubesat.txt') html = response.read() f = open('tle1.txt', 'r+') f.write(html) f.close() tle = tlefile.read(cubesat, 'tle1.txt') inc = tle.inclination print(inc) lon, lat = -1.394, 50.9354 alt = 41 utc_time = datetime.datetime.utcnow() passhrs = 20 o = orbital.Orbital('tisat 1', 'tle1.txt') print(o) p = o.get_next_passes(utc_time, passhrs, lon, lat, alt) print(p) for i in range(0, len(p)): d1 = o.get_observer_look(p[i][0], lon, lat, alt) d2 = o.get_observer_look(p[i][1], lon, lat, alt) d3 = o.get_observer_look(p[i][2], lon, lat, alt) print(i + 1) print 'start time:', p[i][0] print 'AOS azimuth, elevation:', d1[0], d1[1] print 'maximum elevation time:', p[i][2] print 'Max azimuth, elevation:', d3[0], d3[1] print 'end time:', p[i][1] print 'LOS azimuth, elevation:', d2[0], d2[1] ip = 0 t = [1] for i in range(len(t)): l = p[i][0] dt = 2 if l.minute != 0 and l.minute != 1: utctime2 = datetime.datetime(l.year, l.month, l.day, l.hour, l.minute - 2, l.second) else: utctime2 = datetime.datetime(l.year, l.month, l.day, l.hour - 1, 59, l.second) if (utctime2.second % 2 == 0): utctime1 = utctime2 else: utctime2 = datetime.datetime(l.year, l.month, l.day, l.hour - 1, 59, l.second - 1) utctime1 = utctime2 while p[i][1] >= utctime1: if utctime1.second < 58: utctime1 = datetime.datetime(utctime1.year, utctime1.month, utctime1.day, utctime1.hour, utctime1.minute, utctime1.second + dt) elif utctime1.second == 58: if utctime1.minute < 59: utctime1 = datetime.datetime(utctime1.year, utctime1.month, utctime1.day, utctime1.hour, utctime1.minute + 1, 0) elif utctime1.minute == 59: if utctime1.hour < 23: utctime1 = datetime.datetime(utctime1.year, utctime1.month, utctime1.day, utctime1.hour + 1, 0, 0) elif utctime1.hour == 23: if utctime1.month in [1, 3, 5, 7, 8, 10, 12 ] and utctime1.day < 31: utctime1 = datetime.datetime( utctime1.year, utctime1.month, utctime1.day + 1, 0, 0, 0) elif utctime1.month in [1, 3, 5, 7, 8, 10, 12 ] and utctime1.day == 31: utctime1 = datetime.datetime( utctime1.year, utctime1.month + 1, 1, 0, 0, 0) elif utctime1.month in [4, 6, 9, 11 ] and utctime1.month < 30: utctime1 = datetime.datetime( utctime1.year, utctime1.day, utctime1.day + 1, 0, 0, 0) elif utctime1.month in [4, 6, 9, 11 ] and utctime1.month == 30: utctime1 = datetime.datetime( utctime1.year, utctime1.day + 1, 1, 0, 0, 0) if p[i][0] <= utctime1: look = o.get_observer_look(utctime1, lon, lat, alt) "print look,utctime1" angle = ["%.3G" % (look[0]), "%.3G" % (look[1])] msg1 = str(angle[0]) + ',' + str(angle[1]) if x == 1: s.send(msg1) print msg1 time.sleep(2) ip = ip + 1 return ()
def get_location_time(satellite_name, unix_UTC_time): satellite = orbital.Orbital(satellite_name) return satellite.get_position(datetime.utcfromtimestamp(unix_UTC_time))
def setUp(self): """Set up""" from pyorbital import orbital from trollsched.schedule import Satellite self.utctime = datetime(2018, 11, 28, 10, 0) self.satellites = [ "noaa-20", ] self.tles = {'noaa-20': {}} self.tles['noaa-20'][ 'line1'] = "1 43013U 17073A 18331.00000000 .00000048 00000-0 22749-4 0 3056" self.tles['noaa-20'][ 'line2'] = "2 43013 098.7413 267.0121 0001419 108.5818 058.1314 14.19552981053016" self.aquas = [ "aqua", ] self.terras = [ "terra", ] self.terra = Satellite('terra', 0, 0) self.metopa = Satellite('metop-a', 0, 0) self.tles['aqua'] = {} self.tles['aqua'][ 'line1'] = "1 27424U 02022A 18332.21220389 .00000093 00000-0 30754-4 0 9994" self.tles['aqua'][ 'line2'] = "2 27424 98.2121 270.9368 0001045 343.9225 155.8703 14.57111538881313" self.tles['terra'] = {} self.tles['terra'][ 'line1'] = "1 25994U 99068A 18338.20920286 .00000076 00000-0 26867-4 0 9999" self.tles['terra'][ 'line2'] = "2 25994 98.2142 50.5750 0000577 102.5211 257.6060 14.57132862 8586" self.tles['metop-a'] = {} self.tles['metop-a'][ 'line1'] = "1 29499U 06044A 18338.30873671 .00000000 00000+0 31223-4 0 00013" self.tles['metop-a'][ 'line2'] = "2 29499 98.6045 31.7725 0001942 91.8780 346.4884 14.21536046629175" self.orb = orbital.Orbital('NOAA 20', line1=self.tles['noaa-20']['line1'], line2=self.tles['noaa-20']['line2']) self.aqua_orb = orbital.Orbital('AQUA', line1=self.tles['aqua']['line1'], line2=self.tles['aqua']['line2']) self.terra_orb = orbital.Orbital('TERRA', line1=self.tles['terra']['line1'], line2=self.tles['terra']['line2']) self.metopa_orb = orbital.Orbital('Metop-A', line1=self.tles['metop-a']['line1'], line2=self.tles['metop-a']['line2']) # These values were used to generate the get_next_passes list mock: # utctime = datetime(2018, 12, 4, 9, 0) # forward = 6 # coords = (16, 58, 0) self.metopa_passlist = [ (datetime(2018, 12, 4, 9, 10, 4, 574801), datetime(2018, 12, 4, 9, 25, 29, 157194), datetime(2018, 12, 4, 9, 17, 48, 530484)), (datetime(2018, 12, 4, 10, 50, 23, 899232), datetime(2018, 12, 4, 11, 4, 2, 335184), datetime(2018, 12, 4, 10, 57, 13, 691637)), (datetime(2018, 12, 4, 12, 30, 24, 97160), datetime(2018, 12, 4, 12, 40, 42, 403698), datetime(2018, 12, 4, 12, 35, 33, 317647)), (datetime(2018, 12, 4, 14, 9, 1, 937869), datetime(2018, 12, 4, 14, 17, 20, 556654), datetime(2018, 12, 4, 14, 13, 11, 247497)) ] self.dumpdata = [{ 'los': datetime(2018, 11, 28, 10, 0, 30), 'station': 'USAK05', 'aos': datetime(2018, 11, 28, 9, 50, 24), 'elev': '11.188' }, { 'los': datetime(2018, 11, 28, 11, 39, 47), 'station': 'AS2', 'aos': datetime(2018, 11, 28, 11, 28, 51), 'elev': '39.235' }, { 'los': datetime(2018, 11, 28, 13, 19, 8), 'station': 'USAK05', 'aos': datetime(2018, 11, 28, 13, 6, 36), 'elev': '58.249' }, { 'los': datetime(2018, 11, 28, 14, 54, 25), 'station': 'AS2', 'aos': datetime(2018, 11, 28, 14, 44, 37), 'elev': '22.403' }, { 'los': datetime(2018, 11, 28, 16, 27, 22), 'station': 'SG1', 'aos': datetime(2018, 11, 28, 16, 16, 58), 'elev': '9.521' }] self.dumpdata_terra = [{ 'los': datetime(2018, 11, 20, 23, 24, 41), 'station': 'SG2', 'aos': datetime(2018, 11, 20, 23, 12, 32), 'elev': '17.4526' }, { 'los': datetime(2018, 11, 22, 23, 19, 21), 'station': 'AS3', 'aos': datetime(2018, 11, 22, 23, 8, 55), 'elev': '28.9558' }, { 'los': datetime(2018, 11, 22, 23, 19, 21), 'station': 'AS3', 'aos': datetime(2018, 11, 22, 23, 8, 55), 'elev': '28.9558' }, { 'los': datetime(2018, 11, 26, 22, 47, 34), 'station': 'SG1', 'aos': datetime(2018, 11, 26, 22, 34, 58), 'elev': '21.5694' }, { 'los': datetime(2018, 11, 26, 22, 47, 34), 'station': 'SG1', 'aos': datetime(2018, 11, 26, 22, 34, 58), 'elev': '21.5694' }, { 'los': datetime(2018, 11, 26, 22, 47, 34), 'station': 'SG1', 'aos': datetime(2018, 11, 26, 22, 34, 58), 'elev': '21.5694' }, { 'los': datetime(2018, 11, 27, 23, 30, 44), 'station': 'SG2', 'aos': datetime(2018, 11, 27, 23, 18, 39), 'elev': '16.8795' }, { 'los': datetime(2018, 11, 27, 23, 30, 44), 'station': 'SG2', 'aos': datetime(2018, 11, 27, 23, 18, 39), 'elev': '16.8795' }, { 'los': datetime(2018, 11, 28, 22, 43, 53), 'station': 'USAK05', 'aos': datetime(2018, 11, 28, 22, 31, 57), 'elev': '40.9264' }, { 'los': datetime(2018, 11, 28, 22, 43, 53), 'station': 'USAK05', 'aos': datetime(2018, 11, 28, 22, 31, 57), 'elev': '40.9264' }, { 'los': datetime(2018, 11, 29, 23, 25, 11), 'station': 'USAK05', 'aos': datetime(2018, 11, 29, 23, 14, 47), 'elev': '26.9937' }, { 'los': datetime(2018, 11, 29, 23, 25, 11), 'station': 'USAK05', 'aos': datetime(2018, 11, 29, 23, 14, 47), 'elev': '26.9937' }, { 'los': datetime(2018, 11, 30, 22, 31, 3), 'station': 'AS2', 'aos': datetime(2018, 11, 30, 22, 19, 48), 'elev': '47.8599' }, { 'los': datetime(2018, 12, 1, 1, 29, 2), 'station': 'WG1', 'aos': datetime(2018, 12, 1, 1, 21, 11), 'elev': '8.0543' }, { 'los': datetime(2018, 11, 30, 22, 31, 3), 'station': 'AS2', 'aos': datetime(2018, 11, 30, 22, 19, 48), 'elev': '47.8599' }, { 'los': datetime(2018, 12, 1, 1, 29, 2), 'station': 'WG1', 'aos': datetime(2018, 12, 1, 1, 21, 11), 'elev': '8.0543' }, { 'los': datetime(2018, 12, 3, 1, 28, 14), 'station': 'SG2', 'aos': datetime(2018, 12, 3, 1, 17, 53), 'elev': '9.2428' }, { 'los': datetime(2018, 12, 3, 22, 53, 35), 'station': 'SG1', 'aos': datetime(2018, 12, 3, 22, 41, 5), 'elev': '20.8371' }, { 'los': datetime(2018, 12, 3, 22, 53, 35), 'station': 'SG1', 'aos': datetime(2018, 12, 3, 22, 41, 5), 'elev': '20.8371' }, { 'los': datetime(2018, 12, 4, 23, 43, 5), 'station': 'AS2', 'aos': datetime(2018, 12, 4, 23, 33, 8), 'elev': '23.546' }]
from datetime import datetime from tabulate import tabulate from pyorbital import orbital # --------------------------------------------------------------------------- # satCache = {} tleList = os.listdir('./tlefiles') for each in tleList: fullpath = os.path.join('tlefiles', each) if not os.path.isfile(fullpath): continue if not each.endswith('.tle'): continue satName = each[0:-4].lower() satCache[satName] = orbital.Orbital(satName, fullpath) # --------------------------------------------------------------------------- # OBSERVATOR = (51.049754, 13.757227, 92.0) NOWTIME = datetime.utcnow() EMAX_MINIMAL = 10.0 # minimal max-elevation for calculating satellite passes PASS_PERIOD = 24 # hours for calculating next passes # --------------------------------------------------------------------------- # # calculate all passes of all satellites calculated = [] OBSERV_PARAM = (OBSERVATOR[1], OBSERVATOR[0], OBSERVATOR[2]) for satName in satCache: sat = satCache[satName]
def generate_process_config(msg, config): """ Check sensors to process and setup config for this Need to check if it is a collection or file message. Then get sensor information from this. """ # All possible instruments to process initialized to false. config['process_amsua'] = False config['process_amsub'] = False config['process_hirs'] = False config['process_avhrr'] = False config['process_msu'] = False config['process_mhs'] = False config['process_dcs'] = False # Check sensors and file as given in the incomming message # Note: zip iterates two list at the same time if 'dataset' in msg.data: LOG.debug("Checking dataset") for sensor, sensor_filename in zip(msg.data['sensor'], msg.data['dataset']): LOG.debug("{} {}".format(sensor, sensor_filename['uri'])) process_name = "process_{}".format( config['aapp_static_configuration'] ['sensor_name_converter'].get(sensor, sensor)) config[process_name] = True # Name of the input file for given instrument input_file_name = "input_{}_file".format( config['aapp_static_configuration'] ['sensor_name_converter'].get(sensor, sensor)) # print urlparse(sensor_filename['uri']).path config[input_file_name] = urlparse(sensor_filename['uri']).path elif 'uri' in msg.data: LOG.debug("Checking uri") # Need to force list if type(msg.data["sensor"]) not in (tuple, list, set): msg.data["sensor"] = [msg.data["sensor"]] LOG.debug("sensor: {}".format(msg.data["sensor"])) for sensor in msg.data['sensor']: process_name = "process_{}".format( config['aapp_static_configuration'] ['sensor_name_converter'].get(sensor, sensor)) LOG.debug("{} {}".format(sensor, process_name)) config[process_name] = True # For POES 18 and 19 and the METOPs there are MHS. but no AMSU-B. # AAPP processing handles MHS as AMSU-B if (('NOAA' in msg.data['platform_name'].upper() and int(msg.data['platform_name'][-2:]) >= 18) or ('METOP' in msg.data['platform_name'].upper()) ) and config['process_mhs']: config['process_amsub'] = True # Name of the input file for given instrument # Needed for METOP processing input_file_name = "input_{}_file".format( config['aapp_static_configuration'] ['sensor_name_converter'].get(sensor, sensor)) config[input_file_name] = urlparse(msg.data['uri']).path # Needed for POES processing config['input_hrpt_file'] = urlparse(msg.data['uri']).path else: LOG.error( "Could not find needed dataset or uri in message. Can not handle.") return False # Be sure to set MHS process to False for NOAA15 as there is no MHS, but amsu-b if ('NOAA' in msg.data['platform_name'].upper() and int( msg.data['platform_name'][-2:]) == 15) and config['process_mhs']: config['process_mhs'] = False # Check if processing for this platform should be altered # due to config. if 'instrument_skipped_in_processing' in config['aapp_processes'][ config.process_name]: for platform_name in config['aapp_processes'][ config.process_name]['instrument_skipped_in_processing']: _platform_name = platform_name.keys()[0] if _platform_name.upper() == msg.data['platform_name'].upper(): for sensor in msg.data['sensor']: for skip_sensor in platform_name[_platform_name]: if skip_sensor == sensor: process_name = "process_{}".format( config['aapp_static_configuration'] ['sensor_name_converter'].get(sensor, sensor)) if config[process_name]: LOG.debug( "Skipping processing of sensor: {} as of config." .format(skip_sensor)) config[process_name] = False config['calibration_location'] = "-c -l" config['a_tovs'] = list("ATOVS") if 'keep_orbit_number_from_message' in config['aapp_processes'][ config.process_name] and 'orbit_number' in msg.data: config['orbit_number'] = int(msg.data['orbit_number']) else: # Check the case of no orbit number in message, typically EARS stream start_orbnum = None try: import pyorbital.orbital as orb LOG.debug("platform_name: {}".format(msg.data['platform_name'])) sat = orb.Orbital(config['aapp_static_configuration'] ['tle_platform_name_aliases'].get( msg.data['platform_name'], msg.data['platform_name'])) start_orbnum = sat.get_orbit_number(msg.data['start_time']) except ImportError: LOG.warning("Failed importing pyorbital, " + "cannot calculate orbit number") except AttributeError: LOG.warning("Failed calculating orbit number using pyorbital") LOG.warning("platform name in msg and config = " + str( config['aapp_static_configuration'] ['tle_platform_name_aliases'].get(msg.data['platform_name'], msg.data['platform_name'])) + " " + str(config['platform_name'])) LOG.info("Orbit number determined from pyorbital = " + str(start_orbnum)) try: config['orbit_number'] = int(msg.data['orbit_number']) except KeyError: LOG.warning("No orbit_number in message! Set to none...") config['orbit_number'] = None if start_orbnum and config['orbit_number'] != start_orbnum: LOG.warning("Correcting orbit number: Orbit now = " + str(start_orbnum) + " Before = " + str(config['orbit_number'])) config['orbit_number'] = start_orbnum else: LOG.debug("Orbit number in message determined" "to be okay and not changed...") config['orbit_number'] = int(msg.data['orbit_number']) # How to give the platform name? # Which format? # Used are for Metop: #Metop-A/'Metop A'/'METOP A' # M02 # metop02 # Throughout this processing the last convention is used! if msg.data['platform_name'] in config['aapp_static_configuration'][ 'platform_name_aliases']: config['platform_name'] = config['aapp_static_configuration'][ 'platform_name_aliases'][msg.data['platform_name']] # print config['platform_name'] # TODO Should not use satellite_name config['satellite_name'] = config['platform_name'] else: LOG.error( "Failed to replace platform_name: {}. Can not continue.".format( msg.data['platform_name'])) return False config['start_time'] = msg.data['start_time'] return True
class AappLvl1Processor(object): """ Container for the Metop/NOAA level-1 processing based on AAPP """ def __init__(self): self.lvl1_home = OPTIONS['aapp_out_dir'] self.fullswath = True # Always a full swath (never HRPT granules) self.ishmf = False self.working_dir = None self.level0_filename = None self.starttime = None self.endtime = None self.platform_name = "Unknown" self.satnum = "0" self.orbit = "00000" self.result_files = None self.level0files = None self.job_register = {} self.initialise() def initialise(self): """Initialise the processor""" self.working_dir = None self.level0_filename = None self.starttime = None self.endtime = None self.platform_name = "Unknown" self.satnum = "0" self.orbit = "00000" self.result_files = [] self.level0files = {} def cleanup_aapp_workdir(self): """Clean up the AAPP working dir after processing""" filelist = glob('%s/*' % self.working_dir) dummy = [os.remove(s) for s in filelist if os.path.isfile(s)] filelist = glob('%s/*' % self.working_dir) LOG.info("Number of items left after cleaning working dir = " + str(len(filelist))) LOG.debug("Files: " + str(filelist)) shutil.rmtree(self.working_dir) return def pack_aapplvl1_files(self, subd): return pack_aapplvl1_files(self.result_files, self.lvl1_home, subd, self.satnum) def move_lvl1dir(self): if len(self.result_files) == 0: LOG.warning("No files in directory to move!") return {} # Get the subdirname: path = os.path.dirname(self.result_files[0]) subd = os.path.basename(path) LOG.debug("path = " + str(path)) LOG.debug("lvl1_home = " + self.lvl1_home) try: shutil.move(path, self.lvl1_home) except shutil.Error: LOG.warning("Directory already exists: " + str(subd)) if self.orbit == '00000' or self.orbit == None: # Extract the orbit number from the sub-dir name: dummy, dummy, dummy, self.orbit = subd.split('_') # Return a dict with sensor and level for each filename: filenames = glob(os.path.join(self.lvl1_home, subd, '*')) LOG.info(filenames) retv = {} for fname in filenames: mstr = os.path.basename(fname).split('_')[0] if mstr == 'hrpt': lvl = '1b' instr = 'avhrr/3' else: lvl = mstr[-2:] try: instr = SENSOR_NAME_CONVERTER[mstr[0:-3]] except KeyError: LOG.warning("Sensor name will not be converted %s" % str(mstr[0:-3])) LOG.debug("mstr = " + str(mstr)) instr = mstr[0:-3] retv[fname] = {'level': lvl, 'sensor': instr} LOG.info(str(retv)) return retv def run(self, msg): """Start the AAPP level 1 processing on either a NOAA HRPT file or a set of Metop HRPT files""" # Avoid 'collections' and other stuff: if msg is None or msg.type != 'file': return True LOG.debug("Received message: " + str(msg)) LOG.debug("Supported Metop satellites: " + str(SUPPORTED_METOP_SATELLITES)) try: if (msg.data['platform_name'] not in SUPPORTED_NOAA_SATELLITES and msg.data['platform_name'] not in SUPPORTED_METOP_SATELLITES): LOG.info("Not a NOAA/Metop scene. Continue...") return True except Exception, err: LOG.warning(str(err)) return True self.platform_name = msg.data['platform_name'] LOG.debug("Satellite = " + str(self.platform_name)) LOG.debug("") LOG.debug("\tMessage:") LOG.debug(str(msg)) urlobj = urlparse(msg.data['uri']) server = urlobj.netloc LOG.debug('Server = <' + str(server) + '>') if len(server) > 0 and server != SERVERNAME: LOG.warning("Server %s not the current one: %s" % (str(server), SERVERNAME)) return True LOG.info("Ok... " + str(urlobj.netloc)) LOG.info("Sat and Sensor: " + str(msg.data['platform_name']) + " " + str(msg.data['sensor'])) self.starttime = msg.data['start_time'] try: self.endtime = msg.data['end_time'] except KeyError: LOG.warning( "No end_time in message! Guessing start_time + 14 minutes...") self.endtime = msg.data['start_time'] + timedelta(seconds=60 * 14) start_orbnum = None try: import pyorbital.orbital as orb sat = orb.Orbital( TLE_SATNAME.get(self.platform_name, self.platform_name)) start_orbnum = sat.get_orbit_number(self.starttime) except ImportError: LOG.warning("Failed importing pyorbital, " + "cannot calculate orbit number") except AttributeError: LOG.warning("Failed calculating orbit number using pyorbital") LOG.warning( "platform name = " + str(TLE_SATNAME.get(self.platform_name, self.platform_name)) + " " + str(self.platform_name)) LOG.info("Orbit number determined from pyorbital = " + str(start_orbnum)) try: self.orbit = int(msg.data['orbit_number']) except KeyError: LOG.warning("No orbit_number in message! Set to none...") self.orbit = None if start_orbnum and self.orbit != start_orbnum: LOG.warning("Correcting orbit number: Orbit now = " + str(start_orbnum) + " Before = " + str(self.orbit)) self.orbit = start_orbnum else: LOG.debug( 'Orbit number in message determined to be okay and not changed...' ) if self.platform_name in SUPPORTED_METOP_SATELLITES: metop_id = SATELLITE_NAME[self.platform_name].split('metop')[1] self.satnum = METOP_NUMBER.get(metop_id, metop_id) else: self.satnum = SATELLITE_NAME[self.platform_name].strip('noaa') year = self.starttime.year keyname = str(self.platform_name) LOG.debug("Keyname = " + str(keyname)) LOG.debug("Start: job register = " + str(self.job_register)) # Use sat id, start and end time as the unique identifier of the scene! if keyname in self.job_register and len( self.job_register[keyname]) > 0: # Go through list of start,end time tuples and see if the current # scene overlaps with any: status = overlapping_timeinterval((self.starttime, self.endtime), self.job_register[keyname]) if status: LOG.warning( "Processing of scene " + keyname + " " + str(status[0]) + " " + str(status[1]) + " with overlapping time have been launched previously") LOG.info("Skip it...") return True else: LOG.debug("No overlap with any recently processed scenes...") scene_id = (str(self.platform_name) + '_' + self.starttime.strftime('%Y%m%d%H%M%S') + '_' + self.endtime.strftime('%Y%m%d%H%M%S')) LOG.debug("scene_id = " + str(scene_id)) # Check for keys representing the same scene (slightly different # start/end times): LOG.debug("Level-0files = " + str(self.level0files)) for key in self.level0files: pltrfn, startt, endt = key.split('_') if not self.platform_name == pltrfn: continue t1_ = datetime.strptime(startt, '%Y%m%d%H%M%S') t2_ = datetime.strptime(endt, '%Y%m%d%H%M%S') if (abs(self.starttime - t1_).seconds < 60 and abs(self.endtime - t2_).seconds < 60): # It is the same scene! LOG.debug( "It is the same scene, though the file times differ a bit..." ) scene_id = key break LOG.debug("scene_id = " + str(scene_id)) if scene_id in self.level0files: LOG.debug("Level-0files = " + str(self.level0files[scene_id])) else: LOG.debug("No level-0files yet...") self.level0_filename = urlobj.path dummy, fname = os.path.split(self.level0_filename) if fname.find('.hmf') > 0: self.ishmf = True else: LOG.info("File is not a hmf file, " + "probably a Metop file or a NOAA from DMI: " + str(fname)) LOG.debug("Sensor = " + str(msg.data['sensor'])) LOG.debug("type: " + str(type(msg.data['sensor']))) if type(msg.data['sensor']) in [str, unicode]: sensors = [msg.data['sensor']] elif type(msg.data['sensor']) is list: sensors = msg.data['sensor'] else: sensors = [] LOG.warning('Failed interpreting sensor(s)!') LOG.info("Sensor(s): " + str(sensors)) sensor_ok = False for sensor in sensors: if sensor in SENSOR_NAMES: sensor_ok = True break if not sensor_ok: LOG.info("No required sensors....") return True if scene_id not in self.level0files: LOG.debug("Reset level0files: scene_id = " + str(scene_id)) self.level0files[scene_id] = [] for sensor in sensors: item = (self.level0_filename, sensor) if item not in self.level0files[scene_id]: self.level0files[scene_id].append(item) LOG.debug("Appending item to list: " + str(item)) else: LOG.debug("item already in list: " + str(item)) if len(self.level0files[scene_id]) < 4: LOG.info("Not enough sensor data available yet. " + "Level-0files = " + str(self.level0files[scene_id])) return True else: LOG.info("Level 0 files ready: " + str(self.level0files[scene_id])) if not self.working_dir: try: self.working_dir = tempfile.mkdtemp(dir=AAPP_WORKDIR) except OSError: self.working_dir = tempfile.mkdtemp() finally: LOG.info("Create new working dir...") LOG.info("Working dir = " + str(self.working_dir)) my_env = os.environ.copy() my_env['DYN_WRK_DIR'] = self.working_dir LOG.info("working dir: self.working_dir = " + str(self.working_dir)) for envkey in my_env: LOG.debug("ENV: " + str(envkey) + " " + str(my_env[envkey])) if self.platform_name in SUPPORTED_NOAA_SATELLITES: LOG.info("This is a NOAA scene. Start the NOAA processing!") LOG.info("Process the file %s" % self.level0_filename) cmdseq = (NOAA_RUN_SCRIPT + ' -Y ' + str(year) + ' ' + self.level0_filename) LOG.info("Command sequence: " + str(cmdseq)) # Run the command: aapplvl1_proc = Popen(cmdseq, cwd=self.working_dir, shell=True, env=my_env, stderr=PIPE, stdout=PIPE) elif self.platform_name in SUPPORTED_METOP_SATELLITES: LOG.info("This is a Metop scene. Start the METOP processing!") LOG.info("Process the scene %s %s" % (self.platform_name, str(self.orbit))) sensor_filename = {} for (fname, instr) in self.level0files[scene_id]: sensor_filename[instr] = os.path.basename(fname) for instr in sensor_filename.keys(): if instr not in SENSOR_NAMES: LOG.error("Sensor name mismatch! name = " + str(instr)) return True cmdstr = "%s -d %s -a %s -u %s -m %s -h %s -o %s" % ( METOP_RUN_SCRIPT, METOP_IN_DIR, sensor_filename['avhrr/3'], sensor_filename['amsu-a'], sensor_filename['mhs'], sensor_filename['hirs/4'], AAPP_OUT_DIR) LOG.info("Command sequence: " + str(cmdstr)) # Run the command: aapplvl1_proc = Popen(cmdstr, cwd=self.working_dir, shell=True, env=my_env, stderr=PIPE, stdout=PIPE) # Taking the stderr before stdout seems to be better preventing a # hangup! AD, 2013-03-07 while True: line = nonblock_read(aapplvl1_proc.stderr) if not line: break LOG.info(line) while True: line = nonblock_read(aapplvl1_proc.stdout) if not line: break LOG.info(line) aapplvl1_proc.poll() dummy = aapplvl1_proc.returncode LOG.info("Before call to communicate:") out, err = aapplvl1_proc.communicate() lines = out.splitlines() for line in lines: LOG.info(line) lines = err.splitlines() for line in lines: LOG.info(line) LOG.info("Communicate done...") LOG.info("Ready with AAPP level-1 processing on NOAA scene: " + str(fname)) LOG.info("working dir: self.working_dir = " + str(self.working_dir)) # Add to job register to avoid this to be run again if keyname not in self.job_register.keys(): self.job_register[keyname] = [] self.job_register[keyname].append((self.starttime, self.endtime)) LOG.debug("End: job register = " + str(self.job_register)) # Block any future run on this scene for x (e.g. 10) minutes from now t__ = threading.Timer(10 * 60.0, reset_job_registry, args=(self.job_register, str(self.platform_name), (self.starttime, self.endtime))) t__.start() LOG.debug("After timer call: job register = " + str(self.job_register)) self.result_files = get_aapp_lvl1_files(self.working_dir, msg.data['platform_name']) LOG.info("Output files: " + str(self.result_files)) statresult = aapp_stat.do_noaa_and_metop( self.level0_filename, SATELLITE_NAME.get(self.platform_name, self.platform_name), self.starttime) if os.path.exists(_AAPP_STAT_FILE): fd = open(_AAPP_STAT_FILE, "r") lines = fd.readlines() fd.close() else: lines = [] lines = lines + [statresult + '\n'] fd = open(_AAPP_STAT_FILE, "w") fd.writelines(lines) fd.close() return False