def rinex_info(rinex_fname, nav_fname): """ Query RINEX file *rinex_fname* and RINEX nav file *nav_fname* for useful information and return in a key/value mapping. """ # information mapping info = {} def process_output(line): if line.startswith('Receiver type'): info['receiver'] = line.split(':')[1].split('(')[0].strip() elif line.lstrip().startswith('antenna WGS 84 (xyz)'): # make sure units are [m] assert line.rstrip().endswith('(m)') info['xyz'] = map(float, line.split(':')[1].split('(')[0].split()) elif line.lstrip().startswith('antenna WGS 84 (geo)'): if line.split(':')[1].lstrip()[0] in ['N', 'S']: # skip arcmin, arcsec line pass else: lat, _, lon, _ = line.split(':')[1].split(None, 3) info['lat'] = float(lat) lon = float(lon) while lon > 180: lon -= 360 info['lon'] = lon elif line.lstrip().startswith('WGS 84 height'): assert line.rstrip().endswith('m') info['height'] = float(line.split(':')[1].rstrip()[:-1]) elif line.startswith('|qc - header| position'): # make sure units are [m] assert line.rstrip()[-1] == 'm' info['xyz error'] = float(line.split(':')[1].rstrip()[:-1]) elif line.startswith('Observation interval'): info['interval'] = float(line.split(':')[1].split()[0]) elif line.startswith('Moving average MP12'): info['MP12'] = float(line.split(':')[1].rstrip()[:-1]) elif line.startswith('Moving average MP21'): info['MP21'] = float(line.split(':')[1].rstrip()[:-1]) # error handling error = '' def process_error(line): error += line # query the RINEX file via teqc quality check sh.teqc('+qc', '+quiet', '-R', '-S', '-E', '-C', '-J', '-nav', nav_fname, rinex_fname, _out=process_output, _err=process_error) if error: raise RuntimeError('failure running teqc on ' '{} nav={} ({})'.format(rinex_fname, nav_fname)) return info
def rinex_merge(output_fname, rinex_fnames, _err=sys.stderr): """ Using teqc, merge *rinex_fnames* and store to the file *output_fname*. Returns *output_fname*. Redirect error output to *_err*. """ args = ['-pch'] + rinex_fnames sh.teqc(*args, _out=output_fname, _err=_err) return output_fname
def normalize_rinex(output_rinex_fname, rinex_fname, gps=True, glonass=False, sbas=False, galileo=False, compass=False, qzss=False, decimate=None, clockprep=True, obs_types='L1L2P1P2C1'): """ Sanitize *rinex_fname* with teqc (which is expected to be found in the path) and store output in *output_rinex_fname*. Satellite system data are excluded if *gps*, *glonass*, *sbas*, *galileo*, *compass*, or *qzss* are `False`. If *decimate* is given, decimate the output to the given interval (in [s]). If *clockprep*, smooth time tags (useful for receivers with steered clocks). Only output the observations givne in *obs_types*. Return *output_rinex_fname*. """ if not os.path.isfile(rinex_fname): raise ValueError( 'RINEX observation file {} not found'.format(rinex_fname)) if os.path.abspath(output_rinex_fname) == os.path.abspath(rinex_fname): raise ValueError( 'input RINEX file ({}) and output RINEX file ({}) are ' 'the same'.format(rinex_fname, output_rinex_fname)) args = ['+C2'] args += ['+G'] if gps else ['-G'] args += ['+R'] if glonass else ['-R'] args += ['+S'] if sbas else ['-S'] args += ['+E'] if galileo else ['-E'] args += ['+C'] if compass else ['-C'] args += ['+J'] if qzss else ['-J'] args += ['+smtt'] if clockprep else ['-smtt'] args += ['-O.obs_types', obs_types] if decimate is not None: args += ['-O.dec', str(decimate)] args += [rinex_fname] logger.info('calling teqc with arguments: {}'.format(' '.join(args))) sh.teqc(args, _out=output_rinex_fname, _err=sys.stderr) return output_rinex_fname
def normalize_rinex(output_rinex_fname, rinex_fname, gps=True, glonass=False, sbas=False, galileo=False, compass=False, qzss=False, decimate=None, clockprep=True, obs_types = 'L1L2P1P2C1'): """ Sanitize *rinex_fname* with teqc (which is expected to be found in the path) and store output in *output_rinex_fname*. Satellite system data are excluded if *gps*, *glonass*, *sbas*, *galileo*, *compass*, or *qzss* are `False`. If *decimate* is given, decimate the output to the given interval (in [s]). If *clockprep*, smooth time tags (useful for receivers with steered clocks). Only output the observations givne in *obs_types*. Return *output_rinex_fname*. """ if not os.path.isfile(rinex_fname): raise ValueError('RINEX observation file {} not found'.format(rinex_fname)) if os.path.abspath(output_rinex_fname) == os.path.abspath(rinex_fname): raise ValueError('input RINEX file ({}) and output RINEX file ({}) are ' 'the same'.format(rinex_fname, output_rinex_fname)) args = ['+C2'] args += ['+G'] if gps else ['-G'] args += ['+R'] if glonass else ['-R'] args += ['+S'] if sbas else ['-S'] args += ['+E'] if galileo else ['-E'] args += ['+C'] if compass else ['-C'] args += ['+J'] if qzss else ['-J'] args += ['+smtt'] if clockprep else ['-smtt'] args += ['-O.obs_types', obs_types] if decimate is not None: args += ['-O.dec', str(decimate)] args += [rinex_fname] logger.info('calling teqc with arguments: {}'.format(' '.join(args))) sh.teqc(args, _out=output_rinex_fname, _err=sys.stderr) return output_rinex_fname
def normalize_rinex(rinex_fname, gps=True, glonass=False, sbas=False, galileo=False, compass=False, qzss=False, clockprep=True, obs_types = 'L1L2P1P2C1', work_path=None): """ Sanitize *rinex_fname* (warning: in place) with teqc (which is expected to be found in the path). Satellite system data are excluded if *gps*, *glonass*, *sbas*, *galileo*, *compass*, or *qzss* are `False`. If *clockprep*, smooth time tags (useful for receivers with steered clocks). Only output the observations givne in *obs_types*. Store intermediate files in *work_path*. Return *rinex_fname*. """ with SmartTempDir(work_path) as work_path: rinex_copy_fname = os.path.join(work_path, os.path.basename(rinex_fname)) logger.info('copying {} to {}'.format(rinex_fname, rinex_copy_fname)) shutil.copyfile(rinex_fname, rinex_copy_fname) args = ['+C2'] args += ['+G'] if gps else ['-G'] args += ['+R'] if glonass else ['-R'] args += ['+S'] if sbas else ['-S'] args += ['+E'] if galileo else ['-E'] args += ['+C'] if compass else ['-C'] args += ['+J'] if qzss else ['-J'] args += ['+smtt'] if clockprep else ['-smtt'] args += ['-O.obs_types', obs_types] args += [rinex_copy_fname] logger.info('calling teqc with arguments: {}'.format(' '.join(args))) sh.teqc(args, _out=rinex_fname, _err=sys.stderr) return rinex_fname
def rinex_info(rinex_fname, nav_fname, work_path=None): """ Query RINEX file *rinex_fname* and RINEX nav file *nav_fname* for useful information and return in a key/value mapping. Store intermediate files in *work_path* (a temporary, automatically cleaned up area if not specified). """ if not os.path.isfile(rinex_fname): raise ValueError( 'RINEX observation file {} does not exist'.format(rinex_fname)) if not os.path.isfile(nav_fname): raise ValueError( 'RINEX navigation file {} does not exist'.format(nav_fname)) # information mapping info = {} def process_output(line): if line.startswith('Receiver type'): info['receiver'] = line.split(':')[1].split('(')[0].strip() elif line.lstrip().startswith('antenna WGS 84 (xyz)'): # make sure units are [m] assert line.rstrip().endswith('(m)') info['xyz'] = map(float, line.split(':')[1].split('(')[0].split()) elif line.lstrip().startswith('antenna WGS 84 (geo)'): if line.split(':')[1].lstrip()[0] in ['N', 'S']: # skip arcmin, arcsec line pass else: lat, _, lon, _ = line.split(':')[1].split(None, 3) info['lat'] = float(lat) lon = float(lon) while lon > 180: lon -= 360 info['lon'] = lon elif line.lstrip().startswith('WGS 84 height'): assert line.rstrip().endswith('m') info['height'] = float(line.split(':')[1].rstrip()[:-1]) elif line.startswith('|qc - header| position'): # make sure units are [m] assert line.rstrip()[-1] == 'm' info['xyz error'] = float(line.split(':')[1].rstrip()[:-1]) elif line.startswith('Observation interval'): info['interval'] = float(line.split(':')[1].split()[0]) elif line.startswith('Moving average MP12'): info['MP12'] = float(line.split(':')[1].rstrip()[:-1]) elif line.startswith('Moving average MP21'): info['MP21'] = float(line.split(':')[1].rstrip()[:-1]) # query the RINEX file via teqc quality check --- process in given # work area to avoid intermediate file pollution with SmartTempDir(work_path) as work_path: intermediate_rinex_fname = replace_path(work_path, rinex_fname) os.symlink(os.path.abspath(rinex_fname), intermediate_rinex_fname) intermediate_nav_fname = replace_path(work_path, nav_fname) os.symlink(os.path.abspath(nav_fname), intermediate_nav_fname) sh.teqc('+qc', '+quiet', '-R', '-S', '-E', '-C', '-J', '-nav', intermediate_nav_fname, intermediate_rinex_fname, _cwd=work_path, _out=process_output, _err=sys.stderr) os.remove(intermediate_rinex_fname) os.remove(intermediate_nav_fname) return info
def rinex_info(rinex_fname, nav_fname, work_path=None): """ Query RINEX file *rinex_fname* and RINEX nav file *nav_fname* for useful information and return in a key/value mapping. Store intermediate files in *work_path* (a temporary, automatically cleaned up area if not specified). """ if not os.path.isfile(rinex_fname): raise ValueError('RINEX observation file {} does not exist'.format(rinex_fname)) if not os.path.isfile(nav_fname): raise ValueError('RINEX navigation file {} does not exist'.format(nav_fname)) # information mapping info = {} def process_output(line): if line.startswith('Receiver type'): info['receiver'] = line.split(':')[1].split('(')[0].strip() elif line.lstrip().startswith('antenna WGS 84 (xyz)'): # make sure units are [m] assert line.rstrip().endswith('(m)') info['xyz'] = map(float, line.split(':')[1].split('(')[0].split()) elif line.lstrip().startswith('antenna WGS 84 (geo)'): if line.split(':')[1].lstrip()[0] in ['N', 'S']: # skip arcmin, arcsec line pass else: lat, _, lon, _ = line.split(':')[1].split(None, 3) info['lat'] = float(lat) lon = float(lon) while lon > 180: lon -= 360 info['lon'] = lon elif line.lstrip().startswith('WGS 84 height'): assert line.rstrip().endswith('m') info['height'] = float(line.split(':')[1].rstrip()[:-1]) elif line.startswith('|qc - header| position'): # make sure units are [m] assert line.rstrip()[-1] == 'm' info['xyz error'] = float(line.split(':')[1].rstrip()[:-1]) elif line.startswith('Observation interval'): info['interval'] = float(line.split(':')[1].split()[0]) elif line.startswith('Moving average MP12'): info['MP12'] = float(line.split(':')[1].rstrip()[:-1]) elif line.startswith('Moving average MP21'): info['MP21'] = float(line.split(':')[1].rstrip()[:-1]) # query the RINEX file via teqc quality check --- process in given # work area to avoid intermediate file pollution with SmartTempDir(work_path) as work_path: intermediate_rinex_fname = replace_path(work_path, rinex_fname) os.symlink(os.path.abspath(rinex_fname), intermediate_rinex_fname) intermediate_nav_fname = replace_path(work_path, nav_fname) os.symlink(os.path.abspath(nav_fname), intermediate_nav_fname) sh.teqc('+qc', '+quiet', '-R', '-S', '-E', '-C', '-J', '-nav', intermediate_nav_fname, intermediate_rinex_fname, _cwd=work_path, _out=process_output, _err=sys.stderr) os.remove(intermediate_rinex_fname) os.remove(intermediate_nav_fname) return info