def compare(line1_1, line1_2, line2_1, line2_2, timestamp_min, timestamps, td): ts = load.timescale() satrec1 = Satrec.twoline2rv(line1_1, line1_2) satrec2 = Satrec.twoline2rv(line2_1, line2_2) satellite1 = EarthSatellite.from_satrec(satrec1, ts) satellite2 = EarthSatellite.from_satrec(satrec2, ts) residual = 0 number_of_measurements = 0 for s in range(len(timestamps)): number_of_measurements += len(timestamps[s]) for t0 in range(len(timestamps[s])): time_step = timestamps[s][t0] timestamp1 = timestamp_min + time_step + td[s] observing_time = Time(timestamp1, format="unix", scale="utc") t = ts.from_astropy(observing_time) R1 = satellite1.at(t).position.km R2 = satellite2.at(t).position.km distance = ((R1[0] - R2[0])**2 + (R1[1] - R2[1])**2 + (R1[2] - R2[2])**2)**0.5 residual += distance return residual / number_of_measurements
def __init__(self, whichconst=WGS72, opsmode='i', satnum=5, epoch=None, bstar=2.8098e-05, ndot=6.969196665e-13, nddot=0.0, ecco=0.1859667, argpo=5.7904160274885, inclo=0.5980929187319, mo=0.3373093125574, no_kozai=0.0472294454407, nodeo=6.0863854713832, orientation='sun'): self.ts = load.timescale() self.t_now = self.ts.now() self.t_origin = 2433281.5 self.t_days_now = self.t_now.ut1 if epoch == None: epoch = (self.t_days_now - self.t_origin) + 0.5 else: epoch = (epoch - self.t_origin) + 0.5 self.whichconst = whichconst # gravity model self.opsmode = opsmode # 'a' = old AFSPC mode, 'i' = improved mode self.satnum = satnum # satnum: Satellite number self.epoch = epoch # epoch: days since 1949 December 31 00:00 UT self.bstar = bstar # bstar: drag coefficient (/earth radii) self.ndot = ndot # ndot: ballistic coefficient (revs/day) self.nddot = nddot # nddot: second derivative of mean motion (revs/day^3) self.ecco = ecco # ecco: eccentricity self.argpo = argpo # argpo: argument of perigee (radians) self.inclo = inclo # inclo: inclination (radians) self.mo = mo # mo: mean anomaly (radians) self.no_kozai = no_kozai # no_kozai: mean motion (radians/minute) self.nodeo = nodeo # nodeo: right ascension of ascending node (radians) self.satrec = Satrec() self.satrec.sgp4init(self.whichconst, self.opsmode, self.satnum, self.epoch, self.bstar, self.ndot, self.nddot, self.ecco, self.argpo, self.inclo, self.mo, self.no_kozai, self.nodeo) self.satellite = EarthSatellite.from_satrec(self.satrec, self.ts) self.planets = load('de421.bsp') self.earth = self.planets['earth'] self.sun = self.planets['sun'] self.ssb_satellite = self.earth + self.satellite self.orientation = orientation
return satrec MINUTES_PER_DAY = 24 * 60 ONE_METER = 1.0 / AU_M ONE_KM_PER_HOUR = 1.0 * 24.0 / AU_KM ts = load.timescale(builtin=True) # TLE stations_tle = load.tle_file("stations-tle.txt", reload=False) # XML tree = ET.parse("stations.xml") root = tree.getroot() t0 = ts.utc(2020, 6, 27) for sat_tle in stations_tle: name = sat_tle.name.strip() print(name, sat_tle.model.satnum) # Find and parse XML twin satrec = satrec_from_XML(root, sat_tle.model.satnum) sat_xml = EarthSatellite.from_satrec(satrec, ts) p_xml = sat_xml.at(t0) p_tle = sat_tle.at(t0) #print("XML Location", p_xml.position.au) #print("TLE location", p_tle.position.au) #print() #print("XML velocity", p_xml.velocity.au_per_d) #print("TLE velocity", p_tle.velocity.au_per_d) assert abs(p_xml.position.au - p_tle.position.au).max() < ONE_METER assert abs(p_xml.velocity.au_per_d - p_tle.velocity.au_per_d).max() < ONE_KM_PER_HOUR
def satellite_determination(utc_min, utc_max): """ Estimate the identity of spacecraft observed between the unix times <utc_min> and <utc_max>. :param utc_min: The start of the time period in which we should determine the identity of spacecraft (unix time). :type utc_min: float :param utc_max: The end of the time period in which we should determine the identity of spacecraft (unix time). :type utc_max: float :return: None """ # Open connection to image archive db = obsarchive_db.ObservationDatabase( file_store_path=settings['dbFilestore'], db_host=installation_info['mysqlHost'], db_user=installation_info['mysqlUser'], db_password=installation_info['mysqlPassword'], db_name=installation_info['mysqlDatabase'], obstory_id=installation_info['observatoryId']) logging.info("Starting satellite identification.") # Count how many images we manage to successfully fit outcomes = { 'successful_fits': 0, 'unsuccessful_fits': 0, 'error_records': 0, 'rescued_records': 0, 'insufficient_information': 0 } # Status update logging.info("Searching for satellites within period {} to {}".format( date_string(utc_min), date_string(utc_max))) # Open direct connection to database conn = db.con # Search for satellites within this time period conn.execute( """ SELECT ao.obsTime, ao.publicId AS observationId, f.repositoryFname, l.publicId AS observatory FROM archive_observations ao LEFT OUTER JOIN archive_files f ON (ao.uid = f.observationId AND f.semanticType=(SELECT uid FROM archive_semanticTypes WHERE name="pigazing:movingObject/video")) INNER JOIN archive_observatories l ON ao.observatory = l.uid INNER JOIN archive_metadata am2 ON ao.uid = am2.observationId AND am2.fieldId=(SELECT uid FROM archive_metadataFields WHERE metaKey="web:category") WHERE ao.obsType=(SELECT uid FROM archive_semanticTypes WHERE name='pigazing:movingObject/') AND ao.obsTime BETWEEN %s AND %s AND (am2.stringValue='Plane' OR am2.stringValue='Satellite' OR am2.stringValue='Junk') ORDER BY ao.obsTime """, (utc_min, utc_max)) results = conn.fetchall() # Display logging list of the images we are going to work on logging.info("Estimating the identity of {:d} spacecraft.".format( len(results))) # Analyse each spacecraft in turn for item_index, item in enumerate(results): # Fetch metadata about this object, some of which might be on the file, and some on the observation obs_obj = db.get_observation(observation_id=item['observationId']) obs_metadata = {item.key: item.value for item in obs_obj.meta} if item['repositoryFname']: file_obj = db.get_file(repository_fname=item['repositoryFname']) file_metadata = {item.key: item.value for item in file_obj.meta} else: file_metadata = {} all_metadata = {**obs_metadata, **file_metadata} # Check we have all required metadata if 'pigazing:path' not in all_metadata: logging.info( "Cannot process <{}> due to inadequate metadata.".format( item['observationId'])) continue # Make ID string to prefix to all logging messages about this event logging_prefix = "{date} [{obs}]".format( date=date_string(utc=item['obsTime']), obs=item['observationId']) # Project path from (x,y) coordinates into (RA, Dec) projector = PathProjection(db=db, obstory_id=item['observatory'], time=item['obsTime'], logging_prefix=logging_prefix) path_x_y, path_ra_dec_at_epoch, path_alt_az, sight_line_list_this = projector.ra_dec_from_x_y( path_json=all_metadata['pigazing:path'], path_bezier_json=all_metadata['pigazing:pathBezier'], detections=all_metadata['pigazing:detectionCount'], duration=all_metadata['pigazing:duration']) # Check for error if projector.error is not None: if projector.error in outcomes: outcomes[projector.error] += 1 continue # Check for notifications for notification in projector.notifications: if notification in outcomes: outcomes[notification] += 1 # Check number of points in path path_len = len(path_x_y) # Look up list of satellite orbital elements at the time of this sighting spacecraft_list = fetch_satellites(utc=item['obsTime']) # List of candidate satellites this object might be candidate_satellites = [] # Check that we found a list of spacecraft if spacecraft_list is None: logging.info( "{date} [{obs}] -- No spacecraft records found.".format( date=date_string(utc=item['obsTime']), obs=item['observationId'])) outcomes['insufficient_information'] += 1 continue # Logging message about how many spacecraft we're testing # logging.info("{date} [{obs}] -- Matching against {count:7d} spacecraft.".format( # date=date_string(utc=item['obsTime']), # obs=item['observationId'], # count=len(spacecraft_list) # )) # Test for each candidate satellite in turn for spacecraft in spacecraft_list: # Unit scaling deg2rad = pi / 180.0 # 0.0174532925199433 xpdotp = 1440.0 / (2.0 * pi) # 229.1831180523293 # Model the path of this spacecraft model = Satrec() model.sgp4init( # whichconst: gravity model WGS72, # opsmode: 'a' = old AFSPC mode, 'i' = improved mode 'i', # satnum: Satellite number spacecraft['noradId'], # epoch: days since 1949 December 31 00:00 UT jd_from_unix(spacecraft['epoch']) - 2433281.5, # bstar: drag coefficient (/earth radii) spacecraft['bStar'], # ndot (NOT USED): ballistic coefficient (revs/day) spacecraft['meanMotionDot'] / (xpdotp * 1440.0), # nddot (NOT USED): mean motion 2nd derivative (revs/day^3) spacecraft['meanMotionDotDot'] / (xpdotp * 1440.0 * 1440), # ecco: eccentricity spacecraft['ecc'], # argpo: argument of perigee (radians) spacecraft['argPeri'] * deg2rad, # inclo: inclination (radians) spacecraft['incl'] * deg2rad, # mo: mean anomaly (radians) spacecraft['meanAnom'] * deg2rad, # no_kozai: mean motion (radians/minute) spacecraft['meanMotion'] / xpdotp, # nodeo: right ascension of ascending node (radians) spacecraft['RAasc'] * deg2rad) # Wrap within skyfield to convert to topocentric coordinates ts = load.timescale() sat = EarthSatellite.from_satrec(model, ts) # Fetch spacecraft position at each time point along trajectory ang_mismatch_list = [] distance_list = [] # e, r, v = model.sgp4(jd_from_unix(utc=item['obsTime']), 0) # logging.info("{} {} {}".format(str(e), str(r), str(v))) tai_utc_offset = 39 # seconds def satellite_angular_offset(index, clock_offset): # Fetch observed position of object at this time point pt_utc = path_x_y[index][3] pt_alt = path_alt_az[index][0] pt_az = path_alt_az[index][1] # Project position of this satellite in space at this time point t = ts.tai_jd(jd=jd_from_unix(utc=pt_utc + tai_utc_offset + clock_offset)) # Project position of this satellite in the observer's sky sight_line = sat - observer topocentric = sight_line.at(t) sat_alt, sat_az, sat_distance = topocentric.altaz() # Work out offset of satellite's position from observed moving object ang_mismatch = ang_dist(ra0=pt_az * pi / 180, dec0=pt_alt * pi / 180, ra1=sat_az.radians, dec1=sat_alt.radians) * 180 / pi return ang_mismatch, sat_distance def time_offset_objective(p): """ Objective function that we minimise in order to find the best fit clock offset between the observed and model paths. :param p: Vector with a single component: the clock offset :return: Metric to minimise """ # Turn input parameters into a time offset clock_offset = p[0] # Look up angular offset ang_mismatch, sat_distance = satellite_angular_offset( index=0, clock_offset=clock_offset) # Return metric to minimise return ang_mismatch * exp(clock_offset / 8) # First, chuck out satellites with large angular offsets observer = wgs84.latlon( latitude_degrees=projector.obstory_info['latitude'], longitude_degrees=projector.obstory_info['longitude'], elevation_m=0) ang_mismatch, sat_distance = satellite_angular_offset( index=0, clock_offset=0) # Check angular offset is reasonable if ang_mismatch > global_settings['max_angular_mismatch']: continue # Work out the optimum time offset between the satellite's path and the observed path # See <http://www.scipy-lectures.org/advanced/mathematical_optimization/> # for more information about how this works parameters_initial = [0] parameters_optimised = scipy.optimize.minimize( time_offset_objective, np.asarray(parameters_initial), options={ 'disp': False, 'maxiter': 100 }).x # Construct best-fit linear trajectory for best-fitting parameters clock_offset = float(parameters_optimised[0]) # Check clock offset is reasonable if abs(clock_offset) > global_settings['max_clock_offset']: continue # Measure the offset between the satellite's position and the observed position at each time point for index in range(path_len): # Look up angular mismatch at this time point ang_mismatch, sat_distance = satellite_angular_offset( index=index, clock_offset=clock_offset) # Keep list of the offsets at each recorded time point along the trajectory ang_mismatch_list.append(ang_mismatch) distance_list.append(sat_distance.km) # Consider adding this satellite to list of candidates mean_ang_mismatch = np.mean(np.asarray(ang_mismatch_list)) distance_mean = np.mean(np.asarray(distance_list)) if mean_ang_mismatch < global_settings['max_mean_angular_mismatch']: candidate_satellites.append({ 'name': spacecraft['name'], # string 'noradId': spacecraft['noradId'], # int 'distance': distance_mean, # km 'clock_offset': clock_offset, # seconds 'offset': mean_ang_mismatch, # degrees 'absolute_magnitude': spacecraft['mag'] }) # Add model possibility for null satellite candidate_satellites.append({ 'name': "Unidentified", 'noradId': 0, 'distance': 35.7e3 * 0.25, # Nothing is visible beyond 25% of geostationary orbit distance 'clock_offset': 0, 'offset': 0, 'absolute_magnitude': None }) # Sort candidates by score - use absolute mag = 20 for satellites with no mag for candidate in candidate_satellites: candidate['score'] = hypot( candidate['distance'] / 1e3, candidate['clock_offset'], (20 if candidate['absolute_magnitude'] is None else candidate['absolute_magnitude']), ) candidate_satellites.sort(key=itemgetter('score')) # Report possible satellite identifications logging.info("{prefix} -- {satellites}".format( prefix=logging_prefix, satellites=", ".join([ "{} ({:.1f} deg offset; clock offset {:.1f} sec)".format( satellite['name'], satellite['offset'], satellite['clock_offset']) for satellite in candidate_satellites ]))) # Identify most likely satellite most_likely_satellite = candidate_satellites[0] # Store satellite identification user = settings['pigazingUser'] timestamp = time.time() db.set_observation_metadata(user_id=user, observation_id=item['observationId'], utc=timestamp, meta=mp.Meta( key="satellite:name", value=most_likely_satellite['name'])) db.set_observation_metadata( user_id=user, observation_id=item['observationId'], utc=timestamp, meta=mp.Meta(key="satellite:norad_id", value=most_likely_satellite['noradId'])) db.set_observation_metadata( user_id=user, observation_id=item['observationId'], utc=timestamp, meta=mp.Meta(key="satellite:clock_offset", value=most_likely_satellite['clock_offset'])) db.set_observation_metadata(user_id=user, observation_id=item['observationId'], utc=timestamp, meta=mp.Meta( key="satellite:angular_offset", value=most_likely_satellite['offset'])) db.set_observation_metadata( user_id=user, observation_id=item['observationId'], utc=timestamp, meta=mp.Meta(key="satellite:path_length", value=ang_dist(ra0=path_ra_dec_at_epoch[0][0], dec0=path_ra_dec_at_epoch[0][1], ra1=path_ra_dec_at_epoch[-1][0], dec1=path_ra_dec_at_epoch[-1][1]) * 180 / pi)) db.set_observation_metadata( user_id=user, observation_id=item['observationId'], utc=timestamp, meta=mp.Meta( key="satellite:path_ra_dec", value="[[{:.3f},{:.3f}],[{:.3f},{:.3f}],[{:.3f},{:.3f}]]". format( path_ra_dec_at_epoch[0][0] * 12 / pi, path_ra_dec_at_epoch[0][1] * 180 / pi, path_ra_dec_at_epoch[int(path_len / 2)][0] * 12 / pi, path_ra_dec_at_epoch[int(path_len / 2)][1] * 180 / pi, path_ra_dec_at_epoch[-1][0] * 12 / pi, path_ra_dec_at_epoch[-1][1] * 180 / pi, ))) # Satellite successfully identified if most_likely_satellite['name'] == "Unidentified": outcomes['unsuccessful_fits'] += 1 else: outcomes['successful_fits'] += 1 # Update database db.commit() # Report how many fits we achieved logging.info("{:d} satellites successfully identified.".format( outcomes['successful_fits'])) logging.info("{:d} satellites not identified.".format( outcomes['unsuccessful_fits'])) logging.info("{:d} malformed database records.".format( outcomes['error_records'])) logging.info("{:d} rescued database records.".format( outcomes['rescued_records'])) logging.info("{:d} satellites with incomplete data.".format( outcomes['insufficient_information'])) # Clean up and exit db.commit() db.close_db() return
def get_state_sum(r_a, r_p, inc, raan, AoP, tp, bstar, td, station, timestamp_min, timestamps, mode, measurements, meta): elevation_min = -30 # putting in the measurements ra = measurements["ra"] dec = measurements["dec"] el = measurements["el"] az = measurements["az"] ranging = measurements["range"] doppler = measurements["doppler"] satellite_pos = measurements["satellite_pos"] # preparing the orbit track that is being simulated and used for comparing to the measurements #track = np.zeros_like(satellite_pos) # did not work with strange arrays. track = [] for tr in range(len(satellite_pos)): track.append(np.zeros_like(satellite_pos[tr])) track_az = [] track_el = [] for tr in range(len(az)): track_az.append(np.zeros_like(az[tr])) track_el.append(np.zeros_like(el[tr])) track_range = [] for tr in range(len(ranging)): track_range.append(np.zeros_like(ranging[tr])) track_doppler = [] for tr in range(len(doppler)): track_doppler.append(np.zeros_like(doppler[tr])) track_ra = [] track_dec = [] for tr in range(len(ra)): track_ra.append(np.zeros_like(ra[tr])) track_dec.append(np.zeros_like(dec[tr])) # preparing the orbit parameter needed for the simulated orbit eccentricity = (r_a - r_p) / (r_a + r_p) h_angularmomentuum = np.sqrt(r_p * (1.0 + eccentricity * np.cos(0)) * mu) T_orbitperiod = 2.0 * np.pi / mu**2.0 * (h_angularmomentuum / np.sqrt(1.0 - eccentricity**2))**3 me = tp * (2.0 * np.pi) / T_orbitperiod * 180.0 / np.pi me = zeroTo360(me) AoP = zeroTo360(AoP) raan = zeroTo360(raan) n = 24.0 * 3600.0 / T_orbitperiod # preparing the orbit by putting in the orbit parameters ts = load.timescale() satnum = 0 epoch = timestamp_min ecco = eccentricity argpo = AoP inclo = inc mo = me no_kozai = n nodeo = raan ndot = 0.0 satrec = get_satrec(satnum, epoch, ecco, argpo, inclo, mo, no_kozai, nodeo, bstar, ndot, nddot=0.0) satellite = EarthSatellite.from_satrec(satrec, ts) # now for each station s the measurements are being iterated through by its measurements. # for each measurement, the orbit state is calculated based on the timestamp t0 for s in range(len(timestamps)): for t0 in range(len(satellite_pos[s])): time_step = timestamps[s][t0] timestamp1 = timestamp_min + time_step + td[s] observing_time = Time(timestamp1, format="unix", scale="utc") t = ts.from_astropy(observing_time) R1 = satellite.at(t).position.km #V1 = satellite.at(t).velocity.km_per_s #R = np.array(R1) #V = np.array(V1) track[s][t0][0] = R1[0] track[s][t0][1] = R1[1] track[s][t0][2] = R1[2] ############# #if mode == 0: # #state_sum += (R[0] - satellite_pos[s][t0][0]) ** 2 + \ # # (R[1] - satellite_pos[s][t0][1]) ** 2 + \ # # (R[2] - satellite_pos[s][t0][2]) ** 2 ### station if "long" in station[s]: gs_long = station[s]["long"] gs_lat = station[s]["lat"] gs_alt = station[s]["alt"] observer = wgs84.latlon(gs_lat, gs_long, gs_alt) difference = satellite - observer for t0 in range(len(az[s])): time_step = timestamps[s][t0] timestamp1 = timestamp_min + time_step + td[s] if np.abs(td[s]) > 2.0: # the system time is expected to be jittery only by a few seconds. # so this should be enough and stops the time seach to run amok return -np.inf observing_time = Time(timestamp1, format="unix", scale="utc") t = ts.from_astropy(observing_time) topocentric = difference.at(t) alt1, az1, distance1 = topocentric.altaz() if alt1.degrees >= elevation_min: track_az[s][t0] = az1.degrees track_el[s][t0] = alt1.degrees else: #track_az[s][t0] = np.inf #track_el[s][t0] = np.inf # if one value is not good, then it is already infinity and we can also quit now return -np.inf for t0 in range(len(ranging[s])): time_step = timestamps[s][t0] timestamp1 = timestamp_min + time_step + td[s] observing_time = Time(timestamp1, format="unix", scale="utc") t = ts.from_astropy(observing_time) topocentric = difference.at(t) alt1, az1, distance1 = topocentric.altaz() if alt1.degrees >= elevation_min: track_range[s][t0] = distance1.km else: #track_range[s][t0] = np.inf # if one value is not good, then it is already infinity and we can also quit now return -np.inf for t0 in range(len(doppler[s])): time_step = timestamps[s][t0] timestamp1 = timestamp_min + time_step + td[s] observing_time = Time(timestamp1, format="unix", scale="utc") t = ts.from_astropy(observing_time) topocentric = difference.at(t) alt1, az1, distance1 = topocentric.altaz() pointing = topocentric.position.km velo = topocentric.velocity.km_per_s #angle = np.dot(pointing, velo) angle = (pointing[0] * velo[0] + pointing[1] * velo[1] + pointing[2] * velo[2]) / (np.linalg.norm(pointing) * np.linalg.norm(velo)) angle = np.arccos(angle) range_rate = np.cos(angle) * np.linalg.norm(velo) f_0 = meta[s][0]["rf"]["fc"] c_speedoflight = 299792.458 doppler_c = -range_rate * f_0 / c_speedoflight if alt1.degrees >= elevation_min: track_doppler[s][t0] = doppler_c else: #track_doppler[s][t0] = np.inf # if one value is not good, then it is already infinity and we can also quit now return -np.inf for t0 in range(len(ra[s])): time_step = timestamps[s][t0] timestamp1 = timestamp_min + time_step + td[s] observing_time = Time(timestamp1, format="unix", scale="utc") t = ts.from_astropy(observing_time) topocentric = difference.at(t) ra1, dec1, distance1 = topocentric.radec() alt1, az1, distance2 = topocentric.altaz() if alt1.degrees >= elevation_min: track_ra[s][t0] = ra1.radians * 180.0 / np.pi track_dec[s][t0] = dec1.degrees else: #track_ra[s][t0] = np.inf #track_dec[s][t0] = np.inf # if one value is not good, then it is already infinity and we can also quit now return -np.inf # now we just do a simple Root-mean-square of the measurement positions # and the orbit positions based on the simulation # but first min-max-rescaling or currently mean. # normalization rms_sum = 0 emcee_factor = 10000 # somehow emcee seems to not like rms_sum smaller 1.0, so we artificially boost that up satellite_radius = [] for s in range(len(satellite_pos)): if len(satellite_pos[s]) > 0: for pos in range(len(satellite_pos[s])): satellite_radius.append((satellite_pos[s][pos][0]**2 + satellite_pos[s][pos][1]**2 + satellite_pos[s][pos][2]**2)**0.5) mean_radius = np.mean(satellite_radius) # unfortunately inputs can be ragged arrays, and numpy does not like it. # so we iterate through it and use numpy sub-array wise. # normalizing with mean radius track1 = np.divide(track[s], mean_radius) satellite_pos1 = np.divide(satellite_pos[s], mean_radius) rms = np.subtract(track1, satellite_pos1) rms = np.multiply(rms, emcee_factor) rms_sum += np.sum(np.square(rms)) for s in range(len(az)): if len(az[s]) > 0: mean_az = np.mean(np.abs(az[s])) mean_el = np.mean(np.abs(el[s])) # normalizing with mean az track_az1 = np.divide(track_az[s], mean_az) az1 = np.divide(az[s], mean_az) rms = np.subtract(track_az1, az1) rms = np.multiply(rms, emcee_factor) rms_sum += np.sum(np.square(rms)) # normalizing with mean el track_el1 = np.divide(track_el[s], mean_el) el1 = np.divide(el[s], mean_el) rms = np.subtract(track_el1, el1) rms = np.multiply(rms, emcee_factor) rms_sum += np.sum(np.square(rms)) for s in range(len(ranging)): if len(ranging[s]) > 0: mean_range = np.mean(ranging[s]) # normalizing with mean az track_range1 = np.divide(track_range[s], mean_range) range1 = np.divide(ranging[s], mean_range) rms = np.subtract(track_range1, range1) rms = np.multiply(rms, emcee_factor) rms_sum += np.sum(np.square(rms)) for s in range(len(doppler)): if len(doppler[s]) > 0: mean_doppler = np.mean(np.abs(doppler[s])) # normalizing with mean az track_doppler1 = np.divide(track_doppler[s], mean_doppler) doppler1 = np.divide(doppler[s], mean_doppler) rms = np.subtract(track_doppler1, doppler1) rms = np.multiply(rms, emcee_factor) rms_sum += np.sum(np.square(rms)) for s in range(len(ra)): if len(ra[s]) > 0: mean_ra = np.mean(np.abs(ra[s])) mean_dec = np.mean(np.abs(dec[s])) # normalizing with mean az track_ra1 = np.divide(track_ra[s], mean_ra) ra1 = np.divide(ra[s], mean_ra) rms = np.subtract(track_ra1, ra1) rms = np.multiply(rms, emcee_factor) rms_sum += np.sum(np.square(rms)) # normalizing with mean el track_dec1 = np.divide(track_dec[s], mean_dec) dec1 = np.divide(dec[s], mean_dec) rms = np.subtract(track_dec1, dec1) rms = np.multiply(rms, emcee_factor) rms_sum += np.sum(np.square(rms)) return -0.5 * rms_sum