def get_tdb_limits(msid, dbver=None, tdbs=None): """ Retrieve the TDB limits from a json version of the MS Access database. :param msid: String containing the mnemonic name, must correspond to a numeric limit set :returns safetylimits: Dictionary of numeric limits with keys: 'warning_low', 'caution_low', 'caution_high', 'warning_high' Returns an empty dict object if there are no limits specified in the database """ def assign_sets(dbsets): """ Copy over only the limit/expst sets, other stuff is not copied. This also adds a list of set numbers. """ limits = {'setkeys': []} for setnum in dbsets.keys(): setnumint = int(setnum) - 1 limits.update({setnumint: dbsets[setnum]}) limits['setkeys'].append(setnumint) return limits def get_tdb(dbver, tdbs): if tdbs: return tdbs[dbver.lower()] else: tdbs = open_tdb_file() return tdbs[dbver.lower()] msid = msid.lower().strip() if not dbver: tdbversions = get_tdb_dates(return_dates=True) dbver = max(tdbversions.keys()) try: tdb = get_tdb(dbver, tdbs) limits = assign_sets(tdb[msid]['limit']) limits['type'] = 'limit' if is_not_nan(tdb[msid]['limit_default_set_num']): limits['default'] = tdb[msid]['limit_default_set_num'] - 1 else: limits['default'] = 0 # Add limit switch info if present if is_not_nan(tdb[msid]['limit_switch_msid']): limits['mlimsw'] = tdb[msid]['limit_switch_msid'] # Fill in switchstate info if present for setkey in limits['setkeys']: if 'state_code' in limits[setkey].keys(): limits[setkey]['switchstate'] = limits[setkey]['state_code'] _ = limits[setkey].pop('state_code') # For now, only the default limit set is returned, this will help with backwards compatibility. # Future versions, rewritten for web applications will not have this limitation. tdblimits = limits[limits['default']] except KeyError: print('{} does not have limits in the TDB'.format(msid.upper())) tdblimits = {} return tdblimits
def get_mission_safety_limits(msid, tdbs=None): """ this assumes that glimmon limits can indicate when a safety limit has been adjusted """ def liminterp(tsum, times, limits): # nans are filled in for cases where a limit isn't established until some point after launch # The last date for safety limits and for trending limits should be near the current time and # be identical so that one doesn't dominate when it shouldn't. f = interpolate.interp1d(times, limits, kind='zero', bounds_error=False, fill_value=np.nan) return list(f(tsum)) limdict = get_limits(msid) lastdate = np.max(limdict['limsets'][0]['times']) trendinglimits = {'msid': msid, 'warning_low': [], 'caution_low': [], 'caution_high': [], 'warning_high': [], 'times': []} # Assume the default set is always 0 - I know this is a hack, but it will work for now trendinglimits['warning_low'] = limdict['limsets'][0]['warning_low'] trendinglimits['caution_low'] = limdict['limsets'][0]['caution_low'] trendinglimits['caution_high'] = limdict['limsets'][0]['caution_high'] trendinglimits['warning_high'] = limdict['limsets'][0]['warning_high'] trendinglimits['times'] = limdict['limsets'][0]['times'] if not tdbs: tdbs = open_tdb_file() tdbversions = get_tdb_dates(return_dates=True) allsafetylimits = {'warning_low': [], 'caution_low': [], 'caution_high': [], 'warning_high': [], 'times': []} for ver in np.sort(tdbversions.keys()): date = tdbversions[ver] safetylimits = get_tdb_limits(msid, dbver=ver, tdbs=tdbs) if safetylimits: allsafetylimits['warning_low'].append(safetylimits['warning_low']) allsafetylimits['caution_low'].append(safetylimits['caution_low']) allsafetylimits['caution_high'].append(safetylimits['caution_high']) allsafetylimits['warning_high'].append(safetylimits['warning_high']) allsafetylimits['times'].append(DateTime(date).secs) if len(allsafetylimits['warning_low']) == 0: return None # Repeat the last limit to prevent nans from being entered for safety limits when interpolating for key in allsafetylimits.keys(): allsafetylimits[key].append(allsafetylimits[key][-1]) allsafetylimits['times'][-1] = lastdate tsum = np.sort(np.unique(np.concatenate((trendinglimits['times'], allsafetylimits['times'])))) for kind in ['warning_low', 'caution_low', 'caution_high', 'warning_high']: trendinglimits[kind] = liminterp(tsum, trendinglimits['times'], trendinglimits[kind]) allsafetylimits[kind] = liminterp(tsum, allsafetylimits['times'], allsafetylimits[kind]) if 'high' in kind: allsafetylimits[kind] = [ np.nanmax((t, a)) for t, a in zip(trendinglimits[kind], allsafetylimits[kind])] # allsafetylimits[kind] = list(np.nanmax((trendinglimits[kind], allsafetylimits[kind]), axis=0)) else: allsafetylimits[kind] = [ np.nanmin((t, a)) for t, a in zip(trendinglimits[kind], allsafetylimits[kind])] allsafetylimits['times'] = list(tsum) return allsafetylimits