def animate(i): plt.title( str(timedelta(seconds=i * 30) + start_date) ) lons = [] lats = [] vals = [] for station in stations: for prn in get_data.satellites: if prn not in vtec[station] or i >= len(vtec[station][prn][0]): continue try: ecef = vtec[station][prn][0][i] except IndexError: print(station, prn, i) raise if ecef is None: continue lat, lon, _ = coordinates.ecef2geodetic(ecef) lon = lon if lon > 0 else lon + 360 lons.append(lon) lats.append(lat) vals.append(filtered[station][prn][i]) scatter.set_offsets(numpy.array((lons, lats)).T) max_tec = 0.1 min_tec = -0.1 scatter.set_color( cm.plasma(numpy.maximum(numpy.array(vals) - min_tec, 0) / (max_tec - min_tec)) )
def animate(i): plt.title( str(timedelta(seconds=i * 30) + start_date) ) lons = [] lats = [] vals = [] for station in stations: for prn in ['G%02d' % x for x in range(1, 33)]: if prn not in vtec[station] or i >= len(vtec[station][prn][0]): continue try: ecef = vtec[station][prn][0][i] except IndexError: print(station, prn, i) raise if ecef is None: continue lat, lon, _ = coordinates.ecef2geodetic(ecef) lon = lon if lon > 0 else lon + 360 lons.append(lon) lats.append(lat) vals.append(vtec[station][prn][1][i]) scatter.set_offsets(numpy.array(globe(lons, lats)).T) max_tec = 60 scatter.set_color( cm.plasma(numpy.array(vals) / max_tec) )
def tropo_delay(measurement, height=0): # base tropospheric delay Tr(E) lat = numpy.radians(coordinates.ecef2geodetic(measurement.sat_pos)[0]) trzd, trzw, _, _ = Trz(lat, height, measurement.recv_time) m_d = M_dry(lat, height, measurement.recv_time) m_w = M_wet(lat) return trzd * m_d + trzw * m_w
def get_data_point(scenario, tickpair, tick, z_index): '''helper function to get the information of interest from the station_vtecs file.''' s = tickpair[0] p = tickpair[1] ecef = scenario.station_vtecs[s][p][0][tick] lat, lon, _ = ecef2geodetic(ecef) vtec = scenario.station_vtecs[s][p][1][tick] slant = scenario.station_vtecs[s][p][2][tick] prn_index = z_index.index(p) stn_index = z_index.index(s) return lat, lon, vtec, slant * DK, prn_index, stn_index
def est_tec(ionmap, startdate, tick, pos): # round time to 15 minutes time = tick * 30 rounded_minutes = round(time / (15 * 60)) * (15) obs_time = startdate + timedelta(minutes=rounded_minutes) lat, lon, _ = coordinates.ecef2geodetic(pos) rlat = round(lat / 2.5) * 2.5 rlon = round(lon / 5) * 5 return ionmap[obs_time][rlat][rlon]
def gather_data(station_vtecs): ''' Looks for 'coincidences'. A 'coincidence' is a set of observables for various sat/rec pairs that cross into the ionosphere at approximately the same location (lat,lon). Returns four items: final_coicidences (dict) {(lat, lon, i): Observation((lat, lon, i), station, prn, vtec, s_to_v, ...} measurements (list): [Observation 1, ....] sats, recvrs (set): sets of satellite and receiver objects included. ''' # mapping of (lat, lon, time) to [measurement_idx] coincidences = defaultdict(list) measurements = [] svs = set() recvs = set() for cnt, (station, station_dat) in enumerate(station_vtecs.items()): print("gathering data for %3d/%d" % (cnt, len(station_vtecs))) for prn, (locs, dats, slants) in station_dat.items(): for i in range(0, len(locs), time_res // 30): # look through all data in this time window cois = set() for j in range(i, i + time_res // 30): # skip if there's no data... if j >= len(locs) or locs[j] is None: continue lat, lon, _ = ecef2geodetic(locs[j]) coi = (round_to_res(lat, lat_res), round_to_res(lon, lon_res), i) # only log unique COIs if coi in cois: continue cois.add(coi) obs = Observation(coi, station, prn, dats[j], slants[j]) coincidences[coi].append(obs) final_coincidences = dict() # only include coincidences with >= 2 measurements for coi, obss in coincidences.items(): if len({obs.station for obs in obss}) > 1: final_coincidences[coi] = obss for obs in obss: svs.add(obs.sat) recvs.add(obs.station) measurements.append(obs) return final_coincidences, measurements, svs, recvs
def gather_data(station_vtecs): # mapping of (lat, lon, time) to [measurement_idx] coincidences = defaultdict(list) measurements = [] svs = set() recvs = set() for cnt, (station, station_dat) in enumerate(station_vtecs.items()): print("gathering data for %3d/%d" % (cnt, len(station_vtecs))) for prn, (locs, dats, slants) in station_dat.items(): for i in range(0, len(locs), time_res // 30): # look through all data in this time window cois = set() for j in range(i, i + time_res // 30): # skip if there's no data... if j >= len(locs) or locs[j] is None: continue lat, lon, _ = ecef2geodetic(locs[j]) coi = (round_to_res(lat, lat_res), round_to_res(lon, lon_res), i) # only log unique COIs if coi in cois: continue cois.add(coi) obs = Observation(coi, station, prn, dats[j], slants[j]) coincidences[coi].append(obs) final_coincidences = dict() # only include coincidences with >= 2 measurements for coi, obss in coincidences.items(): if len({obs.station for obs in obss}) > 1: final_coincidences[coi] = obss for obs in obss: svs.add(obs.sat) recvs.add(obs.station) measurements.append(obs) return final_coincidences, measurements, svs, recvs
def plot_map_depletion(): globe = Basemap(projection='mill', lon_0=180) # plot coastlines, draw label meridians and parallels. globe.drawcoastlines() #globe.drawparallels(numpy.arange(-90,90,30),labels=[1,0,0,0]) #globe.drawmeridians(numpy.arange(globe.lonmin,globe.lonmax+30,60),labels=[0,0,0,1]) scatter = globe.scatter([], []) stations = { 'bkvl', 'brtw', 'chin', 'crst', 'fl75', 'flbn', 'flf1', 'flkw', 'flwe', 'fmyr', 'gnvl', 'laud', 'mtnt', 'napl', 'okcb', 'ormd', 'pbch', 'pcla', 'pltk', 'prry', 'talh', 'wach', 'xcty', 'zefr', 'zjx1', 'zma1', } stations &= set(station_data.keys()) receivers = ['G%02d' % i for i in range(1, 32)] lats = [[] for _ in range(2880)] lons = [[] for _ in range(2880)] values = [[] for _ in range(2880)] for st, sv in itertools.product(stations, receivers): locs, depls = get_depletion_for(st, sv) for i in range(2880): loc = locs[i] depl = depls[i] if loc is not None and not math.isnan(depl): lat, lon, _ = coordinates.ecef2geodetic(loc) lon = lon if lon > 0 else lon + 360 lats[i].append(lat) lons[i].append(lon) values[i].append(depl) def animate(i): plt.title(str("%0.2f" % (24 * i / 2880))) lon = lons[i] lat = lats[i] val = values[i] scatter.set_offsets(numpy.array(globe(lon, lat)).T) scatter.set_color(cm.plasma(numpy.array(val) / 8)) def init(): scatter.set_offsets([]) ani = animation.FuncAnimation(plt.gcf(), animate, init_func=init, frames=range(1600, 2400), repeat=True, interval=60) #globe.draw() #globe.show(block=False) plt.show() print("done") return ani
def gather_data(start_time, station_vtecs): ''' Looks for 'coincidences'. A 'coincidence' is a set of observables for various sat/rec pairs that cross into the ionosphere at approximately the same location (lat,lon). Returns four items: final_coicidences (dict) {(lat, lon, i): Observation((lat, lon, i), station, prn, vtec, s_to_v, ...} measurements (list): [Observation 1, ....] sats, recvrs (set): sets of satellite and receiver objects included. ''' # mapping of (lat, lon, time) to [measurement_idx] coincidences = defaultdict(list) measurements = [] svs = set() recvs = set() for cnt, (station, station_dat) in enumerate(station_vtecs.items()): print("gathering data for %3d/%d" % (cnt, len(station_vtecs))) for prn, (locs, dats, slants) in station_dat.items(): if len(locs) == 0: continue # convert locs to lat lon in bulk for much better speed # dirty hack to force numpy to treat the array as 1d locs.append(None) # indices with locations set idxs = numpy.where( numpy.logical_not(numpy.vectorize(is_)(locs, None))) locs.pop(-1) if len(idxs[0]) == 0: continue locs_lla = ecef2geodetic(numpy.stack(numpy.array(locs)[idxs])) prev_coi = None for i, idx in enumerate(idxs[0]): cois = set() lat, lon, _ = locs_lla[i] coi = (round_to_res(lat, lat_res), round_to_res(lon, lon_res), (idx // (time_res / 30)) * 30) if coi == prev_coi: continue prev_coi = coi gpstime = start_time + timedelta(seconds=30 * int(idx)) gpstime = GPSTime.from_datetime(gpstime) obs = Observation(coi, station, prn, dats[idx], slants[idx], gpstime) coincidences[coi].append(obs) final_coincidences = dict() # only include coincidences with >= 2 measurements for coi, obss in coincidences.items(): if (len({obs.station for obs in obss}) > 1 or len({obs.sat for obs in obss}) > 1): final_coincidences[coi] = obss for obs in obss: svs.add(obs.sat) recvs.add(obs.station) measurements.append(obs) return final_coincidences, measurements, svs, recvs
vals = [] for j in range(len(meas_datas)): if len(meas_datas[j]) <= i: continue meas = meas_datas[j][i] for sv_dat in meas: res = tec.calc_vtec(dog, station_poss[j], sv_dat) if res is None: continue vtec, loc = res all_values.append(vtec) lat, lon, _ = coordinates.ecef2geodetic(loc) lats.append(lat) lons.append(lon if lon > 0 else lon + 360) connection_name = stations[j] + "-" + sv_dat.prn vals.append( (vtec, connection_name, len(connections[connection_name])) ) connections[connection_name].append(vtec) xs, ys = globe(lons, lats) ticks.append( (xs, ys, vals) ) epsilon = 0.4 min_tec = numpy.quantile([x for x in all_values if not math.isnan(x)], 0.5 - epsilon) max_tec = numpy.quantile([x for x in all_values if not math.isnan(x)], 0.5 + epsilon) smoothed = dict()