; docformat = 'rst' ;+ ;This function returns information about all of the orbits within a ;provided time range. ; Returns orbits whose start times are within the requested interval. For instance, ; ; A A A A A A ; N N N N N N ; |---Orbit 123---|---Orbit 124---|---Orbit 125---|---Orbit 126---|---Orbit 127---| ; ^Start Time ^Stop Time ; ; This will return orbits 124-126. ; ; If the start time is the same as the stop time, then the orbit that overlaps the ; times will be returned. ; A A A A A A ; N N N N N N ; |---Orbit 123---|---Orbit 124---|---Orbit 125---|---Orbit 126---|---Orbit 127---| ; ^Start Time ; ^Stop Time ; ; This will return orbit 124. Note that this is a special case. If the times are even ; fractionally different, the normal case above will take over and you will only get ; an orbit if one of the ascending nodes happens to fall in the right place ; ; A A A A A A ; N N N N N N ; |---Orbit 123---|---Orbit 124---|---Orbit 125---|---Orbit 126---|---Orbit 127---| ; ^Start Time ; ^Stop Time ; ; This will return no orbits, and will probably cause a runtime error. ; ; :Author: ; Chris Jeppesen, Bill Barrett ; ; :Examples: ; orbit_info = get_orbit_info(start_time, stop_time) ;+ ; :Params: ; lstart_time : in, optional, type=double ; Defines the starting time of orbits to return info for, in GPS ; microseconds. ; lstop_time : in, optional, type=double ; Defines the ending time of the orbits to return info form in GPS ; microseconds. ; ; :Keywords: ; lag : in, optional, type=double ; Time lag to be subtracted if start and stop times are not set. ; days : in, optional, type=double ; Number of days tp be added after lag if start and stop times are not ; set. ; verbose : in, optional, type=boolean ; If set prints additional information to the console when this ; routine is running. ; first_image : in, optional, type=boolean ; If set subtracts 96 minutes off of the query start time and adds 96 ; minutes to the query stop time. ; ; :Returns: ; Returns an array of structures is returned where each array element ; contains a structure of info for a particular orbit. Times in this ; structure are GPS microseconds. Each structure has the following ; fields: ; start_time - Time that the satellite crosses the ascending node ; into this orbit ; stop_time - Time that the satellite crosses the ascending node ; exiting this orbit ; sunrise - Time of sunrise for this orbit ; rise150 - Time SOFIE tangent height exceeds 150km at sunrise ; set150 - Time SOFIE tangent height goes below 150km at sunset ; sunset - Time of sunset for this orbit ; n_term - Time of overflight of terminator in north ; s_term - Time of overflight of terminator in south ; orbit_number - Orbit number. Trajectory from launch to first asc node is orbit zero. Every ; subsequent asc node crossing starts orbits 1,2,3,etc. ; preliminary - 0 if orbit is definitive, 1 if preliminary. An orbit is preliminary if its ; ending time is after the epoch of the second-to-last TLE in the TLE file. ; ;- function get_orbit_info, lstart_time, lstop_time, lag=lag,days=days,verbose=verbose,first_image=first_image ; Keep a cache of the orbits retrieved from the database, so that it is not necessary ; to continually repeat the same database query. common cached_orbits, $ found_orbits if ~keyword_set(found_orbits) then found_orbits = [] if n_elements(lag) eq 0 then lag=0 if n_elements(days) eq 0 then days=0 if n_elements(lstart_time) eq 0 then lstart_time=jd2usec(long(systime(/jul,/utc))-lag) if n_elements(lstop_time) eq 0 then lstop_time= jd2usec(long(systime(/jul,/utc))-lag+days) if size(lstart_time,/type) eq 7 then start_time=jd2usec(oasis2jd(lstart_time)) else start_time=lstart_time if size(lstop_time ,/type) eq 7 then stop_time= jd2usec(oasis2jd(lstop_time)) else stop_time= lstop_time l64_start_time = long64(start_time) l64_stop_time = long64(stop_time) start_string = strtrim(string(l64_start_time), 2) stop_string = strtrim(string(l64_stop_time), 2) print, get_routine_name() + ' Getting orbit info for time range ' + $ usec2vms(start_time) + ' / ' + start_string + $ " to " + usec2vms(stop_time) + ' / ' + stop_string if get_debug_level() gt 5 then print, get_routine_name() + " start log time: " + systime() get_database_login, 'AIM_CIPS_SCIENCE', user=user, password=password, url=url sql_base = get_orbit_info_base_query() ;If the time range is zero length, get the orbit in which the time occurs IF start_time EQ stop_time THEN BEGIN if n_elements(found_orbits) gt 0 then begin cached_orbit = where(found_orbits.start_time gt start_time and found_orbits.stop_time lt start_time, n_orbits) if get_debug_level() gt 5 then print, get_routine_name() + " Using cached single orbit" endif else n_orbits = 0 if n_orbits ge 1 then begin single_orbit = found_orbits[cached_orbit[0]] endif else begin ;get the orbit from the table which covers this time sql2=sql_base+ " where (Orbits.startTime <= " +start_string $ +" and Orbits.endTime > " + stop_string +")" if keyword_set(verbose) then print,sql2 query_database, sql2, data, nrows, user=user, password=password, dburl=url, /dbConnect ;If there is an orbit in the table if nrows gt 0 then begin ;Mark it definitive, return it single_orbit=sql_to_orbit_info(data) endif else begin last_orbit = get_last_orbit_info() while start_time gt last_orbit.stop_time do begin last_orbit = generate_orbit_info(last_orbit.stop_time, $ last_orbit.orbit_number + 1, stop_time) if size(last_orbit, /type) ne 8 then begin print, get_routine_name() + ' generate_orbit_info did not return a structure' break endif if n_elements(last_orbit) gt 1 then begin last_orbit = last_orbit[n_elements(last_orbit) - 1] endif endwhile single_orbit = last_orbit endelse found_orbits = n_elements(found_orbits) gt 0 ? [found_orbits, single_orbit] : [single_orbit] endelse result = single_orbit endif else begin ;the start and end are not the same time if keyword_set(first_image) then begin ninety_six_minutes_as_microseconds = 5760d6 ; 96d * 60d * 1d6 start_time = start_time - ninety_six_minutes_as_microseconds stop_time = stop_time + ninety_six_minutes_as_microseconds start_string = strtrim(string(long64(start_time)), 2) ;96 minutes before stop_string = strtrim(string(long64(stop_time)), 2) ;96 minutes after endif ;Get the orbits from the table where the start time is in the range, mark them definitive sql2=sql_base+ " where (Orbits.startTime >= " +start_string + " and Orbits.startTime <= " + stop_string + $ ") order by Orbits.startTime" query_database, sql2, data, nrows, user=user, password=password, dburl=url, /dbConnect result = [] IF nrows GT 0 THEN begin table_orbit_info=sql_to_orbit_info(data) w = where( start_time GE table_orbit_info.start_time AND stop_time LE table_orbit_info.stop_time ) result = w[0] NE -1 ? table_orbit_info[w] : table_orbit_info endif ; If there is a meaningful result already but it doesn't stretch to the end of the specified ; time interval, create the data necessary to extend the result to the end of the interval. ; Note that this does NOT write to the database, if n_elements(result) eq 0 || result[n_elements(result) - 1].stop_time lt stop_time then begin last_orbit = get_last_orbit_info() more_results = generate_orbit_info(last_orbit.stop_time, $ last_orbit.orbit_number + 1, stop_time) w = where((start_time LE more_results.stop_time) AND (more_results.start_time ge start_time)) more_results = w[0] NE -1 ? more_results[w] : [] for i = 0, n_elements(more_results) - 1 do begin result = [result, more_results[i]] endfor endif endelse if get_debug_level() gt 5 then print, get_routine_name() + " stop log time: " + systime() return,result end