def makeorbit(modelbox, p, orbitfile='orbit_292.txt', filealtimeter=None): '''Computes the orbit nadir on a subdomain. The path of the satellite is given by the orbit file and the subdomain corresponds to the one in the model. Note that a subdomain can be manually added in the parameters file. \n Inputs are satellite orbit (p.filesat), subdomain (modelbox), Along track sampling, along track resolution). \n Outputs are Sat_Nadir object containing Nadir track (along track distance x_al, longitude lon and latitude lat, number of days in a cycle cycle, distance crossed in a cycle cycle_al, time, time shfit and time of pass passtime''' # npoints = 1 # - Load SWOT orbit ground track logger.info('Load data from orbit file') if p.order_orbit_col is None: volon, volat, votime = numpy.loadtxt(orbitfile, usecols=(1, 2, 0), comments='#', unpack=True) else: ncols = p.order_orbit_col volon, volat, votime = numpy.loadtxt(orbitfile, usecols=ncols, comments='#', unpack=True) votime *= const.secinday if (volon > 360).any() or (numpy.abs(volat) > 90).any(): logger.error('Error in orbit file or wrong order of column \n' 'Columns should be in the following order' '(time, lon, lat)') sys.exit(1) dic_sat = {} with open(orbitfile, 'r') as fh: for i, line in enumerate(fh): if line.strip().startswith('#'): key, value = line.strip().split('=') dic_sat[key[1:].strip()] = float(value.strip()) else: break if 'cycle' in dic_sat.keys() and 'elevation' in dic_sat.keys(): p.satcycle = dic_sat['cycle'] p.sat_elev = dic_sat['elevation'] # - If orbit is at low resolution, interpolate at 0.5 s resolution # nop = numpy.shape(votime)[0] # tcycle = votime[nop-1] + votime[1] - votime[0] if numpy.mean(votime[1:] - votime[:-1]) > 0.5: x, y, z = mod_tools.spher2cart(volon, volat) time_hr = numpy.arange(0., votime[-1], 0.5) f = interpolate.interp1d(votime, x) x_hr = f(time_hr) f = interpolate.interp1d(votime, y) y_hr = f(time_hr) f = interpolate.interp1d(votime, z) z_hr = f(time_hr) lon_hr = numpy.zeros(len(x_hr)) + numpy.nan lat_hr = numpy.zeros(len(x_hr)) + numpy.nan lon_hr, lat_hr = mod_tools.cart2sphervect(x_hr, y_hr, z_hr) # Cut orbit if more than an orbit cycle if p.satcycle is None: p.satcycle = const.tcycle time_hr = time_hr / const.secinday ind = numpy.where((time_hr < p.satcycle)) volon = lon_hr[ind] volat = lat_hr[ind] votime = time_hr[ind] # - Get number of points in orbit nop = numpy.shape(votime)[0] # - Get cycle period. tcycle = votime[nop - 1] + votime[1] - votime[0] # shift time if the user needs to shift the time of the orbit if p.shift_time is not None: shift_index = numpy.where(votime >= p.shift_time)[0] volon = numpy.hstack([volon[shift_index[0]:], volon[:shift_index[0]]]) volat = numpy.hstack([volat[shift_index[0]:], volat[:shift_index[0]]]) # shift lon if the user needs to shift the localisation of the orbit if p.shift_lon is not None: volon = volon + p.shift_lon volon = (volon + 360) % 360 # - Rearrange orbit starting from pass 1 # Detect the beginning of pass 1 in orbit txt file. By definition, it is # the first passage at southernmost latitude. dlat = numpy.roll(volat, 1) - volat ind = numpy.where((dlat < 0) & (numpy.roll(dlat, 1) >= 0)) # Shift coordinates, so that the first point of the orbit is the beginning # of pass 1 decal = ind[0][-1] # timeshift = votime[-1] - votime[decal] volon = numpy.hstack([volon[decal:], volon[:decal]]) volat = numpy.hstack([volat[decal:], volat[:decal]]) votime = numpy.hstack([votime[decal:], votime[:decal]]) votime = (votime - votime[0]) % tcycle if votime[numpy.where(votime < 0)]: logger.warn('WARNING: there are negative times in your orbit') del ind # Compute the initial time of each pass dlat = numpy.roll(volat, 1) - volat ind = numpy.where(((dlat < 0) & (numpy.roll(dlat, 1) >= 0)) | ((dlat > 0) & (numpy.roll(dlat, 1) <= 0))) # index=numpy.hstack([0,ind[0]-1]) index = ind[0] passtime = votime[index] # Times of pass # - Compute accumulated along-track distance, longitude, latitude # in the subdomain chosen by the user or given by the model # Extract points in the domain and count the number of points (nop) in the # subdomain # modelbox=[lonmin lonmax latmin latmax] add margin around the domain # plus one point to compute Satdir matnpbox = numpy.zeros((nop)) halfswath = getattr(p, 'halfswath', 1) if modelbox[0] > modelbox[1]: matnpbox[numpy.where( (((modelbox[0] - halfswath / (const.deg2km * math.cos(modelbox[2] * math.pi / 180.)) ) <= volon) | (volon <= (modelbox[1] + halfswath / (const.deg2km * math.cos(modelbox[3] * math.pi / 180.))))) & ((modelbox[2] - halfswath / const.deg2km) <= volat) & ((modelbox[3] + halfswath / const.deg2km) >= volat))] = 1 else: matnpbox[numpy.where( ((modelbox[0] - halfswath / (const.deg2km * math.cos(modelbox[2] * math.pi / 180.))) <= volon ) & (volon <= (modelbox[1] + halfswath / (const.deg2km * math.cos(modelbox[3] * math.pi / 180.)))) & ((modelbox[2] - halfswath / const.deg2km) <= volat) & ((modelbox[3] + halfswath / const.deg2km) >= volat))] = 1 norp = int(numpy.sum(matnpbox)) # Initialize total distance travelled by the satellite since the first # point of the cycle in the subdomain at low (orbital file) resolution x_al_lr = numpy.zeros((norp)) lon_lr = numpy.zeros((norp)) lat_lr = numpy.zeros((norp)) stime_lr = numpy.zeros((norp)) # Initialize vector with accumulated distance travelled by the satellite indp = 0 distance = numpy.zeros((nop)) # Compute and store distances and coordinates that are in the defined # subdomain logger.info('Compute nadir coordinate in the new domain') for i in range(0, nop - 1): if p.progress_bar is True: mod_tools.update_progress(float(i) / float(nop - 1), None, None) if abs(volon[i + 1] - volon[i]) > 1: if volon[i + 1] > 180.: volon[i + 1] = volon[i + 1] - 360 if volon[i] > 180.: volon[i] = volon[i] - 360 distance[i + 1] = ( distance[i] + numpy.sqrt(((volon[i + 1] - volon[i]) * const.deg2km * numpy.cos(volat[i + 1] * 2 * math.pi / 360.))**2 + ((volat[i + 1] - volat[i]) * const.deg2km)**2)) volon[i + 1] = (volon[i + 1] + 360) % 360 if matnpbox[i]: x_al_lr[indp] = distance[i] lon_lr[indp] = (volon[i] + 360) % 360 lat_lr[indp] = volat[i] stime_lr[indp] = votime[i] indp += 1 # - Interpolate orbit at delta_al km resolution (default is delta_al=1) # Detect gap in time in stime (to detect step in x_al, lon and lat) dstime = stime_lr[:] - numpy.roll(stime_lr[:], 1) ind = numpy.where(dstime > 3 * (votime[1] - votime[0])) index = numpy.hstack([0, ind[0]]) nindex = numpy.shape(index)[0] # Initialize along track distance, time and coordinates at delta_al # resolution if nindex > 1: dgap = numpy.zeros((nindex)) for i in range(1, nindex): dgap[i] = x_al_lr[index[i]] - x_al_lr[max(index[i] - 1, 0)] Ninterp = (int( (x_al_lr[-1] - x_al_lr[0] - sum(dgap)) / float(p.delta_al)) + 1) x_al = numpy.zeros((Ninterp)) stime = numpy.zeros((Ninterp)) lon = numpy.zeros((Ninterp)) lat = numpy.zeros((Ninterp)) imin = 0 imax = 0 for i in range(0, nindex - 1): imax = imin + int((x_al_lr[index[i + 1] - 1] - x_al_lr[index[i]]) / float(p.delta_al)) + 1 if imax <= (imin + 1): x_al[imin] = x_al_lr[index[i]] stime[imin] = stime_lr[index[i]] lon[imin] = lon_lr[index[i]] lat[imin] = lat_lr[index[i]] else: slicei = slice(index[i], index[i + 1]) x_al[imin:imax] = numpy.arange(x_al_lr[index[i]], x_al_lr[index[i + 1] - 1], p.delta_al) stime[imin:imax] = numpy.interp(x_al[imin:imax], x_al_lr[slicei], stime_lr[slicei]) loncirc = numpy.rad2deg( numpy.unwrap(numpy.deg2rad(lon_lr[slicei]))) # if numpy.min(lon_lr[index[i]:index[i+1]])<1. # and numpy.max(lon_lr[index[i]:index[i+1]])>359.: # lontmp=lon_lr[index[i]:index[i+1]] # lontmp[numpy.where(lontmp>180.)]=lontmp[numpy.where( # lontmp>180.)]-360. # lon[imin:imax]=numpy.interp(x_al[imin:imax], # x_al_lr[index[i]:index[i+1]], lontmp) # lon[imin:imax]=(lon[imin:imax]+360)%360 # else: # lon[imin:imax]=numpy.interp(x_al[imin:imax], # x_al_lr[index[i]:index[i+1]], lon_lr[index[i]:index[i+1]]) lon[imin:imax] = numpy.interp(x_al[imin:imax], x_al_lr[slicei], loncirc) lat[imin:imax] = numpy.interp(x_al[imin:imax], x_al_lr[slicei], lat_lr[slicei]) imin = imax x_al[imin:] = numpy.arange( x_al_lr[index[-1]], x_al_lr[index[-1]] + (Ninterp - imin) * p.delta_al, p.delta_al) stime[imin:] = numpy.interp(x_al[imin:], x_al_lr[index[-1]:], stime_lr[index[-1]:]) loncirc = numpy.rad2deg(numpy.unwrap(numpy.deg2rad( lon_lr[index[-1]:]))) lon[imin:] = numpy.interp(x_al[imin:], x_al_lr[index[-1]:], loncirc) lat[imin:] = numpy.interp(x_al[imin:], x_al_lr[index[-1]:], lat_lr[index[-1]:]) else: Ninterp = int((x_al_lr[-2] - x_al_lr[0]) / float(p.delta_al)) + 1 x_al = numpy.zeros((Ninterp)) stime = numpy.zeros((Ninterp)) lon = numpy.zeros((Ninterp)) lat = numpy.zeros((Ninterp)) x_al = numpy.arange(x_al_lr[0], x_al_lr[-2], p.delta_al) stime = numpy.interp(x_al, x_al_lr[:-1], stime_lr[:-1]) loncirc = numpy.rad2deg(numpy.unwrap(numpy.deg2rad(lon_lr[:-1]))) lon = numpy.interp(x_al, x_al_lr[:-1], loncirc) lat = numpy.interp(x_al, x_al_lr[:-1], lat_lr[:-1]) lon = lon % 360 nfile = '{}.nc'.format(orbitfile[:-4]) orb = rw_data.Sat_nadir(nfile=nfile) orb.x_al = x_al orb.time = stime orb.lon = lon orb.lat = lat orb.cycle = tcycle orb.al_cycle = distance[-1] orb.passtime = numpy.sort(passtime) orb.timeshift = p.timeshift orb.sat_elev = p.sat_elev return orb
def worker_method_grid(*args, **kwargs): #_args = list(args)# [0] #msg_queue = _args.pop() #ipass = _args[0] msg_queue, ipass, p2, passtime, stime = args[:5] x_al, x_ac, tcycle, al_cycle, nhalfswath, lon, lat, timeshift = args[5:] p = mod_tools.fromdict(p2) npoints = 1 sat_elev = p.sat_elev if sat_elev is None: sat_elev = const.sat_elev # Detect indices corresponding to the pass if ipass == numpy.shape(passtime)[0] - 1: ind = numpy.where((stime >= passtime[ipass]))[0] else: ind = numpy.where((stime >= passtime[ipass]) & (stime < passtime[ipass + 1]))[0] nind = numpy.shape(ind)[0] # Compute swath grid if pass is in the subdomain if nind > 5: # pstep = float(ipass + 1) / float(numpy.shape(passtime)[0]) # str1 = 'selected pass: {}'.format(ipass + 1) # mod_tools.update_progress(pstep, str1, None) # Initialize SWOT grid, grid variables and Satellite # direction and Location filesgrid = '{}_p{:03d}.nc'.format(p.filesgrid, ipass + 1) sgrid = rw_data.Sat_SWOT(nfile=filesgrid) sgrid.x_al = x_al[ind] sgrid.x_ac = x_ac sgrid.cycle = tcycle sgrid.al_cycle = al_cycle sgrid.time = stime[ind] sgrid.lon = numpy.zeros((nind, 2 * nhalfswath)) sgrid.lat = numpy.zeros((nind, 2 * nhalfswath)) SatDir = numpy.zeros((int(nind / npoints), 3)) SatLoc = numpy.zeros((int((nind) / npoints), 3)) # Initialize Nadir track, grid variables filengrid = '{}nadir_p{:03d}.nc'.format(p.filesgrid, ipass + 1) ngrid = rw_data.Sat_nadir(nfile=filengrid) ngrid.x_al = x_al[ind] ngrid.cycle = tcycle ngrid.al_cycle = al_cycle ngrid.time = stime[ind] # Project in cartesian coordinates satellite ground location s2cart = mod_tools.spher2cart(lon[ind[0]:ind[-1] + 1:npoints], lat[ind[0]:ind[-1] + 1:npoints]) SatLoc[:, 0], SatLoc[:, 1], SatLoc[:, 2] = s2cart # Compute satellite direction (SatLoc is periodic) SatDir[1:-1, 0] = ((SatLoc[2:, 0] - SatLoc[:-2, 0]) / numpy.sqrt(SatLoc[1:-1, 0]**2 + SatLoc[1:-1, 1]**2 + SatLoc[1:-1, 2]**2)) SatDir[1:-1, 1] = ((SatLoc[2:, 1] - SatLoc[:-2, 1]) / numpy.sqrt(SatLoc[1:-1, 0]**2 + SatLoc[1:-1, 1]**2 + SatLoc[1:-1, 2]**2)) SatDir[1:-1, 2] = ((SatLoc[2:, 2] - SatLoc[:-2, 2]) / numpy.sqrt(SatLoc[1:-1, 0]**2 + SatLoc[1:-1, 1]**2 + SatLoc[1:-1, 2]**2)) SatDir[-1, :] = SatDir[-2, :] SatDir[0, :] = SatDir[1, :] # Rotate from earth center around satellite direction to compute # swath points of angles between the borders of the swath in left # and right swath for i in range(0, nind, npoints): for j in range(0, int(nhalfswath)): R = mod_tools.rotationmat3D( float((j * p.delta_ac + p.halfgap) / (const.Rearth * 10**-3)), SatDir[int(i / npoints), :]) ObsLoc = numpy.dot(R, SatLoc[int(i / npoints)]) cs = mod_tools.cart2spher(ObsLoc[0], ObsLoc[1], ObsLoc[2]) sgrid.lon[i, nhalfswath + j], sgrid.lat[i, nhalfswath + j] = cs ObsLoc = numpy.dot(numpy.transpose(R), SatLoc[int(i / npoints)]) cs = mod_tools.cart2spher(ObsLoc[0], ObsLoc[1], ObsLoc[2]) sgrid.lon[i, nhalfswath - j - 1], sgrid.lat[i, nhalfswath - j - 1] = cs if npoints > p.delta_al: if i >= npoints: lon1 = +sgrid.lon[i - npoints, nhalfswath + j] lon2 = +sgrid.lon[i, nhalfswath + j] _lon = numpy.arange(lon1, lon2, (lon2 - lon1) / npoints) sgrid.lon[i - npoints:i, nhalfswath + j] = _lon lat1 = +sgrid.lat[i - npoints, nhalfswath + j] lat2 = +sgrid.lat[i, nhalfswath + j] _lat = numpy.arange(lat1, lat2, (lat2 - lat1) / npoints) sgrid.lat[i - npoints:i, nhalfswath + j] = _lat # if npoints>p.delta_al: # for j in range(0, 2*int(nhalfswath+1)): # sgrid.lon[:,j]=numpy.arange(sgrid.lon[0,j], sgrid.lon[ind[-1],j], # (sgrid.lon[-1,j]-sgrid.lon[0,j])/npoints) # sgrid.lat[:,j]=numpy.arange(sgrid.lat[0,j], sgrid.lat[-1,j], # (sgrid.lat[-1,j]-sgrid.lat[0,j])/npoints) # Save Sgrid object sgrid.timeshift = timeshift ngrid.timeshift = timeshift ngrid.lon = (lon[ind] + 360) % 360 ngrid.lat = lat[ind] sgrid.lon_nadir = (lon[ind] + 360) % 360 sgrid.lat_nadir = lat[ind] # Remove grid file if it exists and save it if os.path.exists(filesgrid): os.remove(filesgrid) sgrid.first_time = p.first_time sgrid.write_swath() if p.nadir: if os.path.exists(filengrid): os.remove(filengrid) ngrid.first_time = p.first_time ngrid.write_orb() msg_queue.put((os.getpid(), ipass, None, None)) return None
def orbit2swath(modelbox, p, orb): '''Computes the swath of SWOT satellites on a subdomain from an orbit. The path of the satellite is given by the orbit file and the subdomain corresponds to the one in the model. Note that a subdomain can be manually added in the parameters file. \n Inputs are satellite orbit (p.filesat), subdomain (modelbox), Swath parameters (half gap distance p.halfgap, half swath distance p.halfswath, along track resolution p.delta_al, across track resolution p.delta_ac). \n Outputs are netcdf files containing SWOT grid (along track distance x_al, across track distance from nadir x_ac, longitude lon and latitude lat, number of days in a cycle cycle, distance crossed in a cycle cycle_al, time''' ''' Compute orbit from Swath ''' # - Load altimeter orbit npoints = 1 x_al = orb.x_al stime = orb.time lon = orb.lon lat = orb.lat tcycle = orb.cycle al_cycle = orb.al_cycle passtime = orb.passtime # - Compute accross track distances from nadir # Number of points in half of the swath nhalfswath = int((p.halfswath-p.halfgap)/p.delta_ac) + 1 # Across track distance from nadir x_ac = numpy.zeros((2*nhalfswath)) for i in range(0, int(nhalfswath)): x_ac[i] = -(nhalfswath - i)*p.delta_ac - p.halfgap + p.delta_ac x_ac[i + nhalfswath] = i * p.delta_ac + p.halfgap # - Computation of SWOT grid and storage by passes logger.info('\n Compute SWOT grid') # Detect first pass that is in the subdomain ipass0 = 0 # strpass = [] # Loop on all passes after the first pass detected for ipass in range(ipass0, numpy.shape(passtime)[0]): # Detect indices corresponding to the pass if ipass == numpy.shape(passtime)[0]-1: ind = numpy.where((stime >= passtime[ipass]))[0] else: ind = numpy.where((stime >= passtime[ipass]) & (stime < passtime[ipass+1]))[0] nind = numpy.shape(ind)[0] # Compute swath grid if pass is in the subdomain if nind > 5: pstep = float(ipass + 1) / float(numpy.shape(passtime)[0]) str1 = 'selected pass: {}'.format(ipass + 1) mod_tools.update_progress(pstep, str1, None) # Initialize SWOT grid, grid variables and Satellite # direction and Location filesgrid = '{}_p{:03d}.nc'.format(p.filesgrid,ipass + 1) sgrid = rw_data.Sat_SWOT(nfile=filesgrid) sgrid.x_al = x_al[ind] sgrid.x_ac = x_ac sgrid.cycle = tcycle sgrid.al_cycle = al_cycle sgrid.time = stime[ind] sgrid.lon = numpy.zeros((nind, 2*nhalfswath)) sgrid.lat = numpy.zeros((nind, 2*nhalfswath)) SatDir = numpy.zeros((int(nind/npoints), 3)) SatLoc = numpy.zeros((int((nind)/npoints), 3)) # Initialize Nadir track, grid variables filengrid = '{}nadir_p{:03d}.nc'.format(p.filesgrid,ipass + 1) ngrid = rw_data.Sat_nadir(nfile=filengrid) ngrid.x_al = x_al[ind] ngrid.cycle = tcycle ngrid.al_cycle = al_cycle ngrid.time = stime[ind] # Project in cartesian coordinates satellite ground location s2cart = mod_tools.spher2cart(lon[ind[0]: ind[-1]+1: npoints], lat[ind[0]: ind[-1]+1: npoints]) SatLoc[:, 0], SatLoc[:, 1], SatLoc[:, 2] = s2cart # Compute satellite direction (SatLoc is periodic) SatDir[1: -1, 0] = ((SatLoc[2:, 0] - SatLoc[: -2, 0]) / numpy.sqrt(SatLoc[1: -1, 0]**2 + SatLoc[1: -1, 1]**2 + SatLoc[1: -1, 2]**2)) SatDir[1: -1, 1] = ((SatLoc[2:, 1] - SatLoc[: -2, 1]) / numpy.sqrt(SatLoc[1: -1, 0]**2 + SatLoc[1: -1, 1]**2 + SatLoc[1: -1, 2]**2)) SatDir[1: -1, 2] = ((SatLoc[2:, 2] - SatLoc[: -2, 2]) / numpy.sqrt(SatLoc[1: -1, 0]**2 + SatLoc[1: -1, 1]**2 + SatLoc[1: -1, 2]**2)) SatDir[-1, :] = SatDir[-2, :] SatDir[0, :] = SatDir[1, :] # Rotate from earth center around satellite direction to compute # swath points of angles between the borders of the swath in left # and right swath for i in range(0, nind, npoints): for j in range(0, int(nhalfswath)): R = mod_tools.rotationmat3D(float((j*p.delta_ac+p.halfgap) / (const.Rearth*10**-3)), SatDir[int(i/npoints), :]) ObsLoc = numpy.dot(R, SatLoc[int(i/npoints)]) cs = mod_tools.cart2spher(ObsLoc[0], ObsLoc[1], ObsLoc[2]) sgrid.lon[i, nhalfswath+j], sgrid.lat[i, nhalfswath+j] = cs ObsLoc = numpy.dot(numpy.transpose(R), SatLoc[int(i/npoints)]) cs = mod_tools.cart2spher(ObsLoc[0], ObsLoc[1], ObsLoc[2]) sgrid.lon[i, nhalfswath-j-1], sgrid.lat[i, nhalfswath-j-1] = cs if npoints > p.delta_al: if i >= npoints: sgrid.lon[i-npoints: i, nhalfswath+j] = numpy.arange(sgrid.lon[i-npoints, nhalfswath+j], sgrid.lon[i, nhalfswath+j], (sgrid.lon[i, nhalfswath+j]-sgrid.lon[i-npoints, nhalfswath+j])/npoints) sgrid.lat[i-npoints: i, nhalfswath+j] = numpy.arange(sgrid.lat[i-npoints, nhalfswath+j], sgrid.lat[i, nhalfswath+j], (sgrid.lat[i, nhalfswath+j]-sgrid.lat[i-npoints, nhalfswath+j])/npoints) # if npoints>p.delta_al: # print 'interp not coded' # for j in range(0, 2*int(nhalfswath+1)): # sgrid.lon[:,j]=numpy.arange(sgrid.lon[0,j], sgrid.lon[ind[-1],j], # (sgrid.lon[-1,j]-sgrid.lon[0,j])/npoints) # sgrid.lat[:,j]=numpy.arange(sgrid.lat[0,j], sgrid.lat[-1,j], # (sgrid.lat[-1,j]-sgrid.lat[0,j])/npoints) # Save Sgrid object sgrid.timeshift = orb.timeshift ngrid.timeshift = orb.timeshift ngrid.lon = (lon[ind] + 360) % 360 ngrid.lat = lat[ind] sgrid.lon_nadir = (lon[ind] + 360) % 360 sgrid.lat_nadir = lat[ind] # Remove grid file if it exists and save it if os.path.exists(filesgrid): os.remove(filesgrid) sgrid.write_swath() if p.nadir: if os.path.exists(filengrid): os.remove(filengrid) ngrid.write_orb() mod_tools.update_progress(1, 'All swaths have been processed', ' ') return None
def worker_method_grid(*args, **kwargs): #_args = list(args)# [0] #msg_queue = _args.pop() #ipass = _args[0] msg_queue, ipass, p2, passtime, stime = args[:5] x_al, x_ac, tcycle, al_cycle, nhalfswath, lon, lat, timeshift = args[5:] p = mod_tools.fromdict(p2) npoints = 1 sat_elev= p.sat_elev if sat_elev is None: sat_elev = const.sat_elev # Detect indices corresponding to the pass if ipass == numpy.shape(passtime)[0]-1: ind = numpy.where((stime >= passtime[ipass]))[0] else: ind = numpy.where((stime >= passtime[ipass]) & (stime < passtime[ipass+1]))[0] nind = numpy.shape(ind)[0] # Compute swath grid if pass is in the subdomain if nind > 5: # pstep = float(ipass + 1) / float(numpy.shape(passtime)[0]) # str1 = 'selected pass: {}'.format(ipass + 1) # mod_tools.update_progress(pstep, str1, None) # Initialize SWOT grid, grid variables and Satellite # direction and Location filesgrid = '{}_p{:03d}.nc'.format(p.filesgrid, ipass + 1) sgrid = rw_data.Sat_SWOT(nfile=filesgrid) sgrid.x_al = x_al[ind] sgrid.x_ac = x_ac sgrid.cycle = tcycle sgrid.al_cycle = al_cycle sgrid.time = stime[ind] sgrid.lon = numpy.zeros((nind, 2*nhalfswath)) sgrid.lat = numpy.zeros((nind, 2*nhalfswath)) SatDir = numpy.zeros((int(nind/npoints), 3)) SatLoc = numpy.zeros((int((nind)/npoints), 3)) # Initialize Nadir track, grid variables filengrid = '{}nadir_p{:03d}.nc'.format(p.filesgrid,ipass + 1) ngrid = rw_data.Sat_nadir(nfile=filengrid) ngrid.x_al = x_al[ind] ngrid.cycle = tcycle ngrid.al_cycle = al_cycle ngrid.time = stime[ind] # Project in cartesian coordinates satellite ground location s2cart = mod_tools.spher2cart(lon[ind[0]: ind[-1]+1: npoints], lat[ind[0]: ind[-1]+1: npoints]) SatLoc[:, 0], SatLoc[:, 1], SatLoc[:, 2] = s2cart # Compute satellite direction (SatLoc is periodic) SatDir[1: -1, 0] = ((SatLoc[2:, 0] - SatLoc[: -2, 0]) / numpy.sqrt(SatLoc[1: -1, 0]**2 + SatLoc[1: -1, 1]**2 + SatLoc[1: -1, 2]**2)) SatDir[1: -1, 1] = ((SatLoc[2:, 1] - SatLoc[: -2, 1]) / numpy.sqrt(SatLoc[1: -1, 0]**2 + SatLoc[1: -1, 1]**2 + SatLoc[1: -1, 2]**2)) SatDir[1: -1, 2] = ((SatLoc[2:, 2] - SatLoc[: -2, 2]) / numpy.sqrt(SatLoc[1: -1, 0]**2 + SatLoc[1: -1, 1]**2 + SatLoc[1: -1, 2]**2)) SatDir[-1, :] = SatDir[-2, :] SatDir[0, :] = SatDir[1, :] # Rotate from earth center around satellite direction to compute # swath points of angles between the borders of the swath in left # and right swath for i in range(0, nind, npoints): for j in range(0, int(nhalfswath)): R = mod_tools.rotationmat3D(float((j*p.delta_ac+p.halfgap) / (const.Rearth*10**-3)), SatDir[int(i/npoints), :]) ObsLoc = numpy.dot(R, SatLoc[int(i/npoints)]) cs = mod_tools.cart2spher(ObsLoc[0], ObsLoc[1], ObsLoc[2]) sgrid.lon[i, nhalfswath+j], sgrid.lat[i, nhalfswath+j] = cs ObsLoc = numpy.dot(numpy.transpose(R), SatLoc[int(i/npoints)]) cs = mod_tools.cart2spher(ObsLoc[0], ObsLoc[1], ObsLoc[2]) sgrid.lon[i, nhalfswath-j-1], sgrid.lat[i, nhalfswath-j-1] = cs if npoints > p.delta_al: if i >= npoints: lon1 = + sgrid.lon[i-npoints, nhalfswath+j] lon2 = + sgrid.lon[i, nhalfswath+j] _lon = numpy.arange(lon1, lon2, (lon2 - lon1)/npoints) sgrid.lon[i-npoints: i, nhalfswath+j] = _lon lat1 = + sgrid.lat[i-npoints, nhalfswath+j] lat2 = + sgrid.lat[i, nhalfswath+j] _lat = numpy.arange(lat1, lat2, (lat2 - lat1)/npoints) sgrid.lat[i-npoints: i, nhalfswath+j] = _lat # if npoints>p.delta_al: # for j in range(0, 2*int(nhalfswath+1)): # sgrid.lon[:,j]=numpy.arange(sgrid.lon[0,j], sgrid.lon[ind[-1],j], # (sgrid.lon[-1,j]-sgrid.lon[0,j])/npoints) # sgrid.lat[:,j]=numpy.arange(sgrid.lat[0,j], sgrid.lat[-1,j], # (sgrid.lat[-1,j]-sgrid.lat[0,j])/npoints) # Save Sgrid object sgrid.timeshift = timeshift ngrid.timeshift = timeshift ngrid.lon = (lon[ind] + 360) % 360 ngrid.lat = lat[ind] sgrid.lon_nadir = (lon[ind] + 360) % 360 sgrid.lat_nadir = lat[ind] # Remove grid file if it exists and save it if os.path.exists(filesgrid): os.remove(filesgrid) sgrid.first_time = p.first_time sgrid.write_swath() if p.nadir: if os.path.exists(filengrid): os.remove(filengrid) ngrid.first_time = p.first_time ngrid.write_orb() msg_queue.put((os.getpid(), ipass, None, None)) return None
def makeorbit(modelbox, p, orbitfile='orbit_292.txt', filealtimeter=None): '''Computes the orbit nadir on a subdomain. The path of the satellite is given by the orbit file and the subdomain corresponds to the one in the model. Note that a subdomain can be manually added in the parameters file. \n Inputs are satellite orbit (p.filesat), subdomain (modelbox), Along track sampling, along track resolution). \n Outputs are Sat_Nadir object containing Nadir track (along track distance x_al, longitude lon and latitude lat, number of days in a cycle cycle, distance crossed in a cycle cycle_al, time, time shfit and time of pass passtime''' # npoints = 1 # - Load SWOT orbit ground track logger.info('Load data from orbit file') if p.order_orbit_col is None: volon, volat, votime = numpy.loadtxt(orbitfile, usecols=(1, 2, 0), comments='#', unpack=True) else: ncols = p.order_orbit_col volon, volat, votime = numpy.loadtxt(orbitfile, usecols=ncols, comments='#', unpack=True) votime *= const.secinday if (volon > 360).any() or (numpy.abs(volat) > 90).any(): logger.error('Error in orbit file or wrong order of column \n' 'Columns should be in the following order' '(time, lon, lat)') sys.exit(1) dic_sat = {} with open(orbitfile, 'r') as fh: for i, line in enumerate(fh): if line.strip().startswith('#'): key, value = line.strip().split('=') dic_sat[key[1:].strip()] = float(value.strip()) else: break if 'cycle' in dic_sat.keys() and 'elevation' in dic_sat.keys(): p.satcycle = dic_sat['cycle'] p.sat_elev = dic_sat['elevation'] # - If orbit is at low resolution, interpolate at 0.5 s resolution # nop = numpy.shape(votime)[0] # tcycle = votime[nop-1] + votime[1] - votime[0] if numpy.mean(votime[1:] - votime[:-1]) > 0.5: x, y, z = mod_tools.spher2cart(volon, volat) time_hr = numpy.arange(0., votime[-1], 0.5) f = interpolate.interp1d(votime, x) x_hr = f(time_hr) f = interpolate.interp1d(votime, y) y_hr = f(time_hr) f = interpolate.interp1d(votime, z) z_hr = f(time_hr) lon_hr = numpy.zeros(len(x_hr)) + numpy.nan lat_hr = numpy.zeros(len(x_hr)) + numpy.nan lon_hr, lat_hr = mod_tools.cart2sphervect(x_hr, y_hr, z_hr) # Cut orbit if more than an orbit cycle if p.satcycle is None: p.satcycle = const.tcycle time_hr = time_hr / const.secinday ind = numpy.where((time_hr < p.satcycle)) volon = lon_hr[ind] volat = lat_hr[ind] votime = time_hr[ind] # - Get number of points in orbit nop = numpy.shape(votime)[0] # - Get cycle period. tcycle = votime[nop-1] + votime[1] - votime[0] # shift time if the user needs to shift the time of the orbit if p.shift_time is not None: shift_index = numpy.where(votime >= p.shift_time)[0] volon = numpy.hstack([volon[shift_index[0]:], volon[:shift_index[0]]]) volat = numpy.hstack([volat[shift_index[0]:], volat[:shift_index[0]]]) # shift lon if the user needs to shift the localisation of the orbit if p.shift_lon is not None: volon = volon + p.shift_lon volon = (volon + 360) % 360 # - Rearrange orbit starting from pass 1 # Detect the beginning of pass 1 in orbit txt file. By definition, it is # the first passage at southernmost latitude. dlat = numpy.roll(volat, 1) - volat ind = numpy.where((dlat < 0) & (numpy.roll(dlat, 1) >= 0)) # Shift coordinates, so that the first point of the orbit is the beginning # of pass 1 decal = ind[0][-1] # timeshift = votime[-1] - votime[decal] volon = numpy.hstack([volon[decal:], volon[:decal]]) volat = numpy.hstack([volat[decal:], volat[:decal]]) votime = numpy.hstack([votime[decal:], votime[:decal]]) votime = (votime - votime[0]) % tcycle if votime[numpy.where(votime < 0)]: logger.warn('WARNING: there are negative times in your orbit') del ind # Compute the initial time of each pass dlat = numpy.roll(volat, 1) - volat ind = numpy.where(((dlat < 0) & (numpy.roll(dlat, 1) >= 0)) | ((dlat > 0) & (numpy.roll(dlat, 1) <= 0))) # index=numpy.hstack([0,ind[0]-1]) index = ind[0] passtime = votime[index] # Times of pass # - Compute accumulated along-track distance, longitude, latitude # in the subdomain chosen by the user or given by the model # Extract points in the domain and count the number of points (nop) in the # subdomain # modelbox=[lonmin lonmax latmin latmax] add margin around the domain # plus one point to compute Satdir matnpbox = numpy.zeros((nop)) halfswath = getattr(p, 'halfswath', 1) if modelbox[0] > modelbox[1]: matnpbox[numpy.where((((modelbox[0] - halfswath / (const.deg2km * math.cos(modelbox[2]*math.pi/180.))) <= volon) | (volon <= (modelbox[1] + halfswath/(const.deg2km * math.cos(modelbox[3]*math.pi/180.))))) & ((modelbox[2] - halfswath/const.deg2km) <= volat) & ((modelbox[3] + halfswath/const.deg2km) >= volat))] = 1 else: matnpbox[numpy.where(((modelbox[0] - halfswath / (const.deg2km * math.cos(modelbox[2]*math.pi/180.))) <= volon) & (volon <= (modelbox[1] + halfswath/(const.deg2km * math.cos(modelbox[3]*math.pi/180.)))) & ((modelbox[2] - halfswath/const.deg2km) <= volat) & ((modelbox[3] + halfswath/const.deg2km) >= volat))] = 1 norp = int(numpy.sum(matnpbox)) # Initialize total distance travelled by the satellite since the first # point of the cycle in the subdomain at low (orbital file) resolution x_al_lr = numpy.zeros((norp)) lon_lr = numpy.zeros((norp)) lat_lr = numpy.zeros((norp)) stime_lr = numpy.zeros((norp)) # Initialize vector with accumulated distance travelled by the satellite indp = 0 distance = numpy.zeros((nop)) # Compute and store distances and coordinates that are in the defined # subdomain logger.info('Compute nadir coordinate in the new domain') for i in range(0, nop - 1): if p.progress_bar is True: mod_tools.update_progress(float(i) / float(nop-1), None, None) if abs(volon[i + 1] - volon[i]) > 1: if volon[i + 1] > 180.: volon[i + 1] = volon[i + 1] - 360 if volon[i] > 180.: volon[i] = volon[i] - 360 distance[i+1] = (distance[i] + numpy.sqrt(((volon[i+1]-volon[i]) * const.deg2km*numpy.cos(volat[i+1] * 2*math.pi/360.))**2 + ((volat[i+1] - volat[i]) * const.deg2km)**2)) volon[i + 1] = (volon[i + 1] + 360) % 360 if matnpbox[i]: x_al_lr[indp] = distance[i] lon_lr[indp] = (volon[i] + 360) % 360 lat_lr[indp] = volat[i] stime_lr[indp] = votime[i] indp += 1 # - Interpolate orbit at delta_al km resolution (default is delta_al=1) # Detect gap in time in stime (to detect step in x_al, lon and lat) dstime = stime_lr[:] - numpy.roll(stime_lr[:], 1) ind = numpy.where(dstime > 3*(votime[1] - votime[0])) index = numpy.hstack([0, ind[0]]) nindex = numpy.shape(index)[0] # Initialize along track distance, time and coordinates at delta_al # resolution if nindex > 1: dgap = numpy.zeros((nindex)) for i in range(1, nindex): dgap[i] = x_al_lr[index[i]] - x_al_lr[max(index[i] - 1, 0)] Ninterp = (int((x_al_lr[-1] - x_al_lr[0] - sum(dgap)) / float(p.delta_al)) + 1) x_al = numpy.zeros((Ninterp)) stime = numpy.zeros((Ninterp)) lon = numpy.zeros((Ninterp)) lat = numpy.zeros((Ninterp)) imin = 0 imax = 0 for i in range(0, nindex - 1): imax = imin + int((x_al_lr[index[i+1]-1] - x_al_lr[index[i]]) / float(p.delta_al)) + 1 if imax <= (imin + 1): x_al[imin] = x_al_lr[index[i]] stime[imin] = stime_lr[index[i]] lon[imin] = lon_lr[index[i]] lat[imin] = lat_lr[index[i]] else: slicei = slice(index[i], index[i + 1]) x_al[imin: imax] = numpy.arange(x_al_lr[index[i]], x_al_lr[index[i+1] - 1], p.delta_al) stime[imin: imax] = numpy.interp(x_al[imin: imax], x_al_lr[slicei], stime_lr[slicei]) loncirc = numpy.rad2deg(numpy.unwrap(numpy.deg2rad( lon_lr[slicei]))) # if numpy.min(lon_lr[index[i]:index[i+1]])<1. # and numpy.max(lon_lr[index[i]:index[i+1]])>359.: # lontmp=lon_lr[index[i]:index[i+1]] # lontmp[numpy.where(lontmp>180.)]=lontmp[numpy.where( # lontmp>180.)]-360. # lon[imin:imax]=numpy.interp(x_al[imin:imax], # x_al_lr[index[i]:index[i+1]], lontmp) # lon[imin:imax]=(lon[imin:imax]+360)%360 # else: # lon[imin:imax]=numpy.interp(x_al[imin:imax], # x_al_lr[index[i]:index[i+1]], lon_lr[index[i]:index[i+1]]) lon[imin: imax] = numpy.interp(x_al[imin: imax], x_al_lr[slicei], loncirc) lat[imin: imax] = numpy.interp(x_al[imin: imax], x_al_lr[slicei], lat_lr[slicei]) imin = imax x_al[imin:] = numpy.arange(x_al_lr[index[-1]], x_al_lr[index[-1]] + (Ninterp - imin)*p.delta_al, p.delta_al) stime[imin:] = numpy.interp(x_al[imin:], x_al_lr[index[-1]:], stime_lr[index[-1]:]) loncirc = numpy.rad2deg(numpy.unwrap(numpy.deg2rad( lon_lr[index[-1]:]))) lon[imin:] = numpy.interp(x_al[imin:], x_al_lr[index[-1]:], loncirc) lat[imin:] = numpy.interp(x_al[imin:], x_al_lr[index[-1]:], lat_lr[index[-1]:]) else: Ninterp = int((x_al_lr[-2] - x_al_lr[0]) / float(p.delta_al)) + 1 x_al = numpy.zeros((Ninterp)) stime = numpy.zeros((Ninterp)) lon = numpy.zeros((Ninterp)) lat = numpy.zeros((Ninterp)) x_al = numpy.arange(x_al_lr[0], x_al_lr[-2], p.delta_al) stime = numpy.interp(x_al, x_al_lr[:-1], stime_lr[:-1]) loncirc = numpy.rad2deg(numpy.unwrap(numpy.deg2rad(lon_lr[:-1]))) lon = numpy.interp(x_al, x_al_lr[:-1], loncirc) lat = numpy.interp(x_al, x_al_lr[:-1], lat_lr[:-1]) lon = lon % 360 nfile = '{}.nc'.format(orbitfile[:-4]) orb = rw_data.Sat_nadir(nfile=nfile) orb.x_al = x_al orb.time = stime orb.lon = lon orb.lat = lat orb.cycle = tcycle orb.al_cycle = distance[-1] orb.passtime = numpy.sort(passtime) orb.timeshift = p.timeshift orb.sat_elev = p.sat_elev return orb
def makeorbit(modelbox,p,orbitfile='orbit_292.txt', filealtimeter=None): '''Computes the swath of SWOT satellites on a subdomain. The path of the satellite is given by the orbit file and the subdomain corresponds to the one in the model. Note that a subdomain can be manually added in the parameters file. \n Inputs are satellite orbit (p.filesat), subdomain (modelbox), Swath parameters (half gap distance p.halfgap, half swath distance p.halfswath, along track resolution p.delta_al, across track resolution p.delta_ac). \n Outputs are netcdf files containing SWOT grid (along track distance x_al, across track distance from nadir x_ac, longitude lon and latitude lat, number of days in a cycle cycle, distance crossed in a cycle cycle_al, time''' npoints=1 ## --Load SWOT orbit ground track print('Load data from orbit file') volon, volat, votime=numpy.loadtxt(orbitfile, usecols=(0,1,2), unpack=True) ## --If orbit is at low resolution, interpolate at 0.5 s resolution if numpy.mean(votime[1:]-votime[:-1])>0.5: x,y,z=mod_tools.spher2cart(volon, volat) time_hr=numpy.arange(0.,votime[-1],0.5) f = interpolate.interp1d(votime, x) x_hr=f(time_hr) f = interpolate.interp1d(votime, y) y_hr=f(time_hr) f = interpolate.interp1d(votime, z) z_hr=f(time_hr) lon_hr=numpy.zeros(len(x_hr))+numpy.nan lat_hr=numpy.zeros(len(x_hr))+numpy.nan for ii in range(len(x_hr)): lon_hr[ii],lat_hr[ii]=mod_tools.cart2spher(x_hr[ii],y_hr[ii],z_hr[ii]) time_hr=time_hr/86400. ind=numpy.where((time_hr<20.86455)) volon=lon_hr[ind] volat=lat_hr[ind] votime=time_hr[ind] ## --Get number of points in orbit nop=numpy.shape(votime)[0] ## --Get cycle period. tcycle=votime[nop-1]+votime[1]-votime[0] # shift time if the user needs to shift the time of the orbit try: pshift_time=p.shift_time if pshift_time: shift_index=numpy.where(votime>=pshift_time)[0] volon=numpy.hstack([volon[shift_index[0][0]:], volon[:shift_index[0][0]]]) volat=numpy.hstack([volat[shift_index[0][0]:], volat[:shift_index[0][0]]]) except: p.shift_time=None # shift lon if the user needs to shift the localisation of the orbit try: pshift_lon=p.shift_lon if pshift_lon: volon=volon+pshift_lon except: p.shift_lon=None volon=(volon+360)%360 ## --Rearrange orbit starting from pass 1 # Detect the beginning of pass 1 in orbit txt file. By definition, it is the first passage at southernmost latitude. dlat=numpy.roll(volat,1) -volat ind=numpy.where((dlat<0) & (numpy.roll(dlat,1)>=0)) # Shift coordinates, so that the first point of the orbit is the beginning of pass 1 decal=ind[0][-1] timeshift=votime[-1]-votime[decal] volon=numpy.hstack([volon[decal:], volon[:decal]]) #numpy.roll(volon,decal) volat=numpy.hstack([volat[decal:], volat[:decal]]) #numpy.roll(volat,decal) votime=numpy.hstack([votime[decal:], votime[:decal]]) #numpy.roll(votime,decal) votime=(votime-votime[0])%tcycle if votime[numpy.where(votime<0)]: print('WARNING: there are negative times in your orbit') del ind # Compute the initial time of each pass dlat=numpy.roll(volat,1) -volat ind=numpy.where(((dlat<0) & (numpy.roll(dlat,1)>=0))|((dlat>0) & (numpy.roll(dlat,1)<=0))) #index=numpy.hstack([0,ind[0]-1]) index=ind[0] passtime=votime[index] # Times of pass ## -- Compute accumulated along-track distance, longitude, latitude in the subdomain # chosen by the user or given by the model # Extract points in the domain and count the number of points (nop) in the subdomain #modelbox=[lonmin lonmax latmin latmax] add margin around the domain plus one point to compute Satdir matnpbox=numpy.zeros((nop)) if modelbox[0]>modelbox[1]: matnpbox[numpy.where((((modelbox[0]-p.halfswath/(const.deg2km*math.cos(modelbox[2]*math.pi/180.)))<=volon) | (volon<=(modelbox[1]+p.halfswath/(const.deg2km*math.cos(modelbox[3]*math.pi/180.))))) & ((modelbox[2]-p.halfswath/const.deg2km)<=volat) & ((modelbox[3]+p.halfswath/const.deg2km)>=volat))]=1 else: matnpbox[numpy.where(((modelbox[0]-p.halfswath/(const.deg2km*math.cos(modelbox[2]*math.pi/180.)))<=volon) & (volon<=(modelbox[1]+p.halfswath/(const.deg2km*math.cos(modelbox[3]*math.pi/180.)))) & ((modelbox[2]-p.halfswath/const.deg2km)<=volat) & ((modelbox[3]+p.halfswath/const.deg2km)>=volat))]=1 norp=int(numpy.sum(matnpbox)) # Initialize total distance travelled by the satellite since the first point of the cycle # in the subdomain at low (orbital file) resolution x_al_lr=numpy.zeros((norp)) lon_lr=numpy.zeros((norp)) lat_lr=numpy.zeros((norp)) stime_lr=numpy.zeros((norp)) # Initialize vector with accumulated distance travelled by the satellite indp = 0 distance=numpy.zeros((nop)) # Compute and store distances and coordinates that are in the defined subdomain print('Compute SWOT nadir coordinate in the new domain') for i in range(0,nop-1): mod_tools.update_progress(float(i)/float(nop-1), None, None) if abs(volon[i+1]-volon[i])>1: if volon[i+1]>180. : volon[i+1]=volon[i+1]-360 if volon[i]>180. : volon[i]=volon[i]-360 distance[i+1]=distance[i]+numpy.sqrt(((volon[i+1]-volon[i])*const.deg2km*numpy.cos(volat[i+1]*2*math.pi/360.))**2 + ((volat[i+1]-volat[i])*const.deg2km)**2 ) #numpy.sum(dl[:i]) volon[i+1]=(volon[i+1]+360)%360 if matnpbox[i]: x_al_lr[indp] = distance[i] lon_lr[indp] = (volon[i]+360)%360 lat_lr[indp] = volat[i] stime_lr[indp] = votime[i] indp=indp+1 ## -- Interpolate orbit at delta_al km resolution (default is delta_al=1) #Detect gap in time in stime (to detect step in x_al, lon and lat) dstime=stime_lr[:]-numpy.roll(stime_lr[:],1) ind=numpy.where(dstime>3*(votime[1]-votime[0])) index=numpy.hstack([0,ind[0]]) nindex=numpy.shape(index)[0] # Initialize along track distance, time and coordinates at delta_al resolution if nindex>1: dgap=numpy.zeros((nindex)) for i in range(1,nindex): dgap[i]=x_al_lr[index[i]]-x_al_lr[max(index[i]-1,0)] Ninterp=int((x_al_lr[-1]-x_al_lr[0] -sum(dgap))/float(p.delta_al))+1 x_al=numpy.zeros((Ninterp)) stime=numpy.zeros((Ninterp)) lon=numpy.zeros((Ninterp)) lat=numpy.zeros((Ninterp)) imin=0 ; imax=0 for i in range(0,nindex-1): imax=imin+int((x_al_lr[index[i+1]-1]-x_al_lr[index[i]])/float(p.delta_al))+1 if imax<=(imin+1): x_al[imin]=x_al_lr[index[i]] stime[imin]=stime_lr[index[i]] lon[imin]=lon_lr[index[i]] lat[imin]=lat_lr[index[i]] else: x_al[imin:imax]=numpy.arange(x_al_lr[index[i]],x_al_lr[index[i+1]-1], p.delta_al) stime[imin:imax]=numpy.interp(x_al[imin:imax], x_al_lr[index[i]:index[i+1]], stime_lr[index[i]:index[i+1]]) loncirc=numpy.rad2deg(numpy.unwrap(numpy.deg2rad(lon_lr[index[i]:index[i+1]]))) #if numpy.min(lon_lr[index[i]:index[i+1]])<1. and numpy.max(lon_lr[index[i]:index[i+1]])>359.: # lontmp=lon_lr[index[i]:index[i+1]] # lontmp[numpy.where(lontmp>180.)]=lontmp[numpy.where(lontmp>180.)]-360. # lon[imin:imax]=numpy.interp(x_al[imin:imax], x_al_lr[index[i]:index[i+1]], lontmp) #_lr[index[i]:index[i+1]]) # lon[imin:imax]=(lon[imin:imax]+360)%360 #else: # lon[imin:imax]=numpy.interp(x_al[imin:imax], x_al_lr[index[i]:index[i+1]], lon_lr[index[i]:index[i+1]]) lon[imin:imax]=numpy.interp(x_al[imin:imax], x_al_lr[index[i]:index[i+1]], loncirc) lat[imin:imax]=numpy.interp(x_al[imin:imax], x_al_lr[index[i]:index[i+1]], lat_lr[index[i]:index[i+1]]) imin=imax x_al[imin:]=numpy.arange(x_al_lr[index[-1]],x_al_lr[index[-1]]+(Ninterp-imin)*p.delta_al, p.delta_al) stime[imin:]=numpy.interp(x_al[imin:], x_al_lr[index[-1]:], stime_lr[index[-1]:]) loncirc=numpy.rad2deg(numpy.unwrap(numpy.deg2rad(lon_lr[index[-1]:]))) #if numpy.min(lon_lr[index[-1]:])<1. and numpy.max(lon_lr[index[-1]:])>539: # lontmp=lon_lr[index[-1]:] # lontmp[numpy.where(lontmp>180.)]=lontmp[numpy.where(lontmp>180.)]-360. # lon[imin:]=numpy.interp(x_al[imin:], x_al_lr[index[-1]:], lontmp) # lon[imin:]=(lon[imin:]+360)%360 #else: # lon[imin:]=numpy.interp(x_al[imin:], x_al_lr[index[-1]:], lon_lr[index[-1]:]) lon[imin:]=numpy.interp(x_al[imin:], x_al_lr[index[-1]:], loncirc) lat[imin:]=numpy.interp(x_al[imin:], x_al_lr[index[-1]:], lat_lr[index[-1]:]) else: Ninterp=int((x_al_lr[-2]-x_al_lr[0] )/float(p.delta_al))+1 x_al=numpy.zeros((Ninterp)) stime=numpy.zeros((Ninterp)) lon=numpy.zeros((Ninterp)) lat=numpy.zeros((Ninterp)) x_al=numpy.arange(x_al_lr[0],x_al_lr[-2], p.delta_al) stime=numpy.interp(x_al, x_al_lr[:-1], stime_lr[:-1]) loncirc=numpy.rad2deg(numpy.unwrap(numpy.deg2rad(lon_lr[:-1]))) lon=numpy.interp(x_al, x_al_lr[:-1],loncirc) lat=numpy.interp(x_al, x_al_lr[:-1],lat_lr[:-1]) lon=lon%360 orb=rw_data.Sat_nadir(file=orbitfile[:-4]+'.nc') orb.x_al=x_al orb.time=stime orb.lon=lon orb.lat=lat orb.cycle=tcycle orb.al_cycle=distance[-1] orb.passtime=numpy.sort(passtime) orb.timeshift=timeshift return orb
def orbit2swath(modelbox, p,orb): # -- Load altimeter orbit npoints=1 x_al=orb.x_al stime=orb.time lon=orb.lon lat=orb.lat tcycle=orb.cycle al_cycle=orb.al_cycle passtime=orb.passtime ## -- Compute accross track distances from nadir # Number of points in half of the swath nhalfswath=int( (p.halfswath-p.halfgap)/p.delta_ac) +1 # Across track distance from nadir x_ac=numpy.zeros((2*nhalfswath)) for i in range(0, int(nhalfswath)): x_ac[i]=-(nhalfswath-i)*p.delta_ac-p.halfgap+p.delta_ac x_ac[i+nhalfswath]=i*p.delta_ac+p.halfgap ## -- Computation of SWOT grid and storage by passes print('\n Compute SWOT grid') # Detect first pass that is in the subdomain ipass0=0 strpass=[] # Loop on all passes after the first pass detected for ipass in range(ipass0,numpy.shape(passtime)[0]): # Detect indices corresponding to the pass if ipass==numpy.shape(passtime)[0]-1: ind=numpy.where((stime>=passtime[ipass]))[0] else: ind=numpy.where((stime>=passtime[ipass]) & (stime<passtime[ipass+1]))[0] nind=numpy.shape(ind)[0] # Compute swath grid if pass is in the subdomain if nind>5: mod_tools.update_progress(float(ipass+1)/float(numpy.shape(passtime)[0]), 'selected pass: '******'_p'+str(ipass+1).zfill(3)+'.nc' sgrid=rw_data.Sat_SWOT(file=filesgrid) sgrid.x_al=x_al[ind] sgrid.x_ac=x_ac sgrid.cycle=tcycle sgrid.al_cycle=al_cycle sgrid.time=stime[ind] sgrid.lon=numpy.zeros((nind,2*nhalfswath)) sgrid.lat=numpy.zeros((nind,2*nhalfswath)) SatDir=numpy.zeros((int(nind/npoints),3)) SatLoc=numpy.zeros((int((nind)/npoints),3)) # Initialize Nadir track, grid variables filengrid=p.filesgrid+'nadir_p'+str(ipass+1).zfill(3)+'.nc' ngrid=rw_data.Sat_nadir(file=filengrid) ngrid.x_al=x_al[ind] ngrid.cycle=tcycle ngrid.al_cycle=al_cycle ngrid.time=stime[ind] ## Project in cartesian coordinates satellite ground location #SatLoc[:,0], SatLoc[:,1], SatLoc[:,2]=mod_tools.spher2cart(lon[ind[0]:ind[-1]+npoints:npoints], lat[ind[0]:ind[-1]+npoints:npoints]) #if numpy.min(lon[ind[0]:ind[-1]+1])<1. and numpy.max(lon[ind[0]:ind[-1]+1])>359.: #lontmp=lon[ind[0]:ind[-1]+1] #lontmp[numpy.where(lontmp>180.)]=lontmp[numpy.where(lontmp>180.)]-360. SatLoc[:,0], SatLoc[:,1], SatLoc[:,2]=mod_tools.spher2cart(lon[ind[0]:ind[-1]+1:npoints], lat[ind[0]:ind[-1]+1:npoints]) ## Compute satellite direction (SatLoc is periodic) SatDir[1:-1,0]=(SatLoc[2:,0]-SatLoc[:-2,0])/numpy.sqrt(SatLoc[1:-1,0]**2+SatLoc[1:-1,1]**2+SatLoc[1:-1,2]**2) SatDir[1:-1,1]=(SatLoc[2:,1]-SatLoc[:-2,1])/numpy.sqrt(SatLoc[1:-1,0]**2+SatLoc[1:-1,1]**2+SatLoc[1:-1,2]**2) SatDir[1:-1,2]=(SatLoc[2:,2]-SatLoc[:-2,2])/numpy.sqrt(SatLoc[1:-1,0]**2+SatLoc[1:-1,1]**2+SatLoc[1:-1,2]**2) SatDir[-1]=SatDir[-2] SatDir[0]=SatDir[1] ## Rotate from earth center around satellite direction to compute swath points of angles between the borders of the swath in left and right swath for i in range(0, nind, npoints): for j in range(0, int(nhalfswath)): R=mod_tools.rotationmat3D(float((j*p.delta_ac + p.halfgap)/(const.Rearth*10**-3)) , SatDir[int(i/npoints),:]) ObsLoc=numpy.dot(R,SatLoc[int(i/npoints)]) sgrid.lon[i,nhalfswath+j], sgrid.lat[i, nhalfswath+j]=mod_tools.cart2spher(ObsLoc[0], ObsLoc[1], ObsLoc[2]) ObsLoc=numpy.dot(numpy.transpose(R),SatLoc[int(i/npoints)]) sgrid.lon[i,nhalfswath-j-1], sgrid.lat[i, nhalfswath-j-1]=mod_tools.cart2spher(ObsLoc[0], ObsLoc[1], ObsLoc[2]) if npoints>p.delta_al: if i>=npoints: sgrid.lon[i-npoints:i, nhalfswath+j]=numpy.arange(sgrid.lon[i-npoints,nhalfswath+j], sgrid.lon[i,nhalfswath+j], (sgrid.lon[i,nhalfswath+j]-sgrid.lon[i-npoints,nhalfswath+j])/npoints) sgrid.lat[i-npoints:i,nhalfswath+j]=numpy.arange(sgrid.lat[i-npoints,nhalfswath+j], sgrid.lat[i,nhalfswath+j], (sgrid.lat[i,nhalfswath+j]-sgrid.lat[i-npoints,nhalfswath+j])/npoints) #if npoints>p.delta_al: #print 'interp not coded' #for j in range(0, 2*int(nhalfswath+1)): #sgrid.lon[:,j]=numpy.arange(sgrid.lon[0,j], sgrid.lon[ind[-1],j], (sgrid.lon[-1,j]-sgrid.lon[0,j])/npoints) #sgrid.lat[:,j]=numpy.arange(sgrid.lat[0,j], sgrid.lat[-1,j], (sgrid.lat[-1,j]-sgrid.lat[0,j])/npoints) sgrid.timeshift=orb.timeshift ngrid.timeshift=orb.timeshift ngrid.lon=(lon[ind]+360)%360 ngrid.lat=lat[ind] sgrid.lon_nadir=(lon[ind]+360)%360 sgrid.lat_nadir=lat[ind] if os.path.exists(filesgrid): os.remove(filesgrid) sgrid.write_swath() if p.nadir: if os.path.exists(filengrid): os.remove(filengrid) ngrid.write_orb() mod_tools.update_progress(1, 'All swaths have been processed', ' ') return None