def test_TCXOPoly_compute0(): ''' Unit test for empty TCXOPoly object ''' tcxo = TCXOPoly(()) time = tcxo.computeTcxoTime(0, 10, NormalRateConfig) assert time is None
def test_TCXOPoly_compute1(): ''' Unit test for TCXOPoly with linear time shift (10e-6) ''' tcxo = TCXOPoly((1.,)) time = tcxo.computeTcxoTime(0, 10, NormalRateConfig) test_vector = numpy.linspace(0., 10. * 1e-6 / NormalRateConfig.SAMPLE_RATE_HZ, 10., endpoint=False) assert (time == test_vector).all()
def test_TCXOPoly_compute2(): ''' Unit test for TCXOPoly with linear time shift (10e-6) ''' tcxo = TCXOPoly((1., 1.)) time = tcxo.computeTcxoTime(0, 10, NormalRateConfig) test_vector = numpy.linspace(0., 10. * 1e-6 / NormalRateConfig.SAMPLE_RATE_HZ, 10., endpoint=False) test_vector = test_vector * test_vector / 2. + test_vector assert (numpy.abs(time - test_vector) < EPSILON).all()
def test_Task_generate0(): ''' Task object generation test ''' outputConfig = HighRateConfig sv0 = GPSSatellite(1) sv0.setL1CAEnabled(True) signalSources = [sv0] noiseParams = NoiseParameters(outputConfig.SAMPLE_RATE_HZ, 1.) tcxo = TCXOPoly((1., )) signalFilters = [ LowPassFilter(outputConfig, outputConfig.GPS.L1.INTERMEDIATE_FREQUENCY_HZ), None, None, None ] groupDelays = True bands = [outputConfig.GPS.L1] generateDebug = False task = Task(outputConfig, signalSources, noiseParams, tcxo, signalFilters, groupDelays, bands, generateDebug) nSamples = 1024 userTime0_s = 0. firstSampleIndex = 1 task.update(userTime0_s, nSamples, firstSampleIndex) inputParams, sigs, debugData = task.perform() assert inputParams[0] == userTime0_s assert inputParams[1] == nSamples assert inputParams[2] == firstSampleIndex assert debugData is None assert sigs.shape == (outputConfig.N_GROUPS, nSamples)
def test_Task_update1(): ''' Task object parameter update test ''' outputConfig = NormalRateConfig sv0 = GPSSatellite(1) sv0.setL1CAEnabled(True) signalSources = [sv0] noiseParams = NoiseParameters(outputConfig.SAMPLE_RATE_HZ, 1.) tcxo = TCXOPoly(()) signalFilters = [None] * 4 groupDelays = False bands = [outputConfig.GPS.L1] generateDebug = False task = Task(outputConfig, signalSources, noiseParams, tcxo, signalFilters, groupDelays, bands, generateDebug) userTime0_s = 123. nSamples = 1024 firstSampleIndex = 1 task.update(userTime0_s, nSamples, firstSampleIndex) assert task.nSamples == nSamples assert task.firstSampleIndex == firstSampleIndex assert task.userTime0_s == userTime0_s assert task.noise.shape == (outputConfig.N_GROUPS, nSamples) assert isinstance(task.signals, numpy.ndarray) assert task.signals.shape == (outputConfig.N_GROUPS, nSamples)
def test_Task_init(): ''' Task object initialization test ''' outputConfig = NormalRateConfig sv0 = GPSSatellite(1) sv0.setL1CAEnabled(True) signalSources = [sv0] noiseParams = NoiseParameters(outputConfig.SAMPLE_RATE_HZ, 1.) tcxo = TCXOPoly(()) signalFilters = [None] * 4 groupDelays = False bands = [outputConfig.GPS.L1] generateDebug = False task = Task(outputConfig, signalSources, noiseParams, tcxo, signalFilters, groupDelays, bands, generateDebug) assert task.outputConfig == outputConfig assert task.bands == bands assert task.generateDebug == generateDebug assert task.groupDelays == groupDelays assert task.noiseParams == noiseParams assert task.signalFilters == signalFilters assert task.signalSources == signalSources assert task.tcxo == tcxo assert isinstance(task.noise, numpy.ndarray) assert task.noise.shape == (outputConfig.N_GROUPS, outputConfig.SAMPLE_BATCH_SIZE) assert isinstance(task.signals, numpy.ndarray) assert task.signals.shape == (outputConfig.N_GROUPS, outputConfig.SAMPLE_BATCH_SIZE)
def test_Task_computeGroupTimeVectors1(): ''' Task object group time vector test ''' outputConfig = NormalRateConfig sv0 = GPSSatellite(1) sv0.setL1CAEnabled(True) signalSources = [sv0] noiseParams = NoiseParameters(outputConfig.SAMPLE_RATE_HZ, 1.) tcxo = TCXOPoly((1., )) signalFilters = [None] * 4 groupDelays = True bands = [outputConfig.GPS.L1] generateDebug = False task = Task(outputConfig, signalSources, noiseParams, tcxo, signalFilters, groupDelays, bands, generateDebug) nSamples = 1024 userTime0_s = 0. firstSampleIndex = 1 task.update(userTime0_s, nSamples, firstSampleIndex) userTimeAll_s = task.computeTimeVector() result = task.computeGroupTimeVectors(userTimeAll_s) assert isinstance(result, list) for i in range(outputConfig.N_GROUPS): assert (result[i] == userTimeAll_s + outputConfig.GROUP_DELAYS[i]).all()
def test_Task_createNoise(): ''' Task object noise helper test ''' outputConfig = NormalRateConfig sv0 = GPSSatellite(1) sv0.setL1CAEnabled(True) signalSources = [sv0] noiseParams = NoiseParameters(outputConfig.SAMPLE_RATE_HZ, 1.) tcxo = TCXOPoly((1., )) signalFilters = [None] * 4 groupDelays = False bands = [outputConfig.GPS.L1] generateDebug = False task = Task(outputConfig, signalSources, noiseParams, tcxo, signalFilters, groupDelays, bands, generateDebug) userTime0_s = 123. nSamples = outputConfig.SAMPLE_BATCH_SIZE firstSampleIndex = 1 task.update(userTime0_s, nSamples, firstSampleIndex) noiseMatrix = task.createNoise() assert isinstance(noiseMatrix, numpy.ndarray) assert noiseMatrix.shape == (outputConfig.N_GROUPS, nSamples) assert numpy.mean(noiseMatrix) < 0.1 assert (noiseMatrix != 0.).sum() > 1000
def test_Task_computeTcxoVector2(): ''' Task object TCXO helper test ''' outputConfig = NormalRateConfig sv0 = GPSSatellite(1) sv0.setL1CAEnabled(True) signalSources = [sv0] noiseParams = NoiseParameters(outputConfig.SAMPLE_RATE_HZ, 1.) tcxo = TCXOPoly((1., )) signalFilters = [None] * 4 groupDelays = False bands = [outputConfig.GPS.L1] generateDebug = False task = Task(outputConfig, signalSources, noiseParams, tcxo, signalFilters, groupDelays, bands, generateDebug) userTime0_s = 123. nSamples = 1024 firstSampleIndex = 1 task.update(userTime0_s, nSamples, firstSampleIndex) tcxoVector = task.computeTcxoVector() assert isinstance(tcxoVector, numpy.ndarray) assert tcxoVector.shape == (1024, ) assert (tcxoVector != 0.).all()
def test_Task_computeTcxoVector0(): ''' Task object TCXO helper test ''' outputConfig = NormalRateConfig sv0 = GPSSatellite(1) sv0.setL1CAEnabled(True) signalSources = [sv0] noiseParams = NoiseParameters(outputConfig.SAMPLE_RATE_HZ, 1.) tcxo = TCXOPoly(()) signalFilters = [None] * 4 groupDelays = False bands = [outputConfig.GPS.L1] generateDebug = False task = Task(outputConfig, signalSources, noiseParams, tcxo, signalFilters, groupDelays, bands, generateDebug) userTime0_s = 123. nSamples = 1024 firstSampleIndex = 1 task.update(userTime0_s, nSamples, firstSampleIndex) tcxo = task.computeTcxoVector() # TCXO object is None because TCXO polynomial is empty assert tcxo is None
def __call__(self, parser, namespace, values, option_string=None): setattr(namespace, self.dest, values) if namespace.tcxo_type == "poly": coeffs = [] hasHighOrder = False srcA = [ namespace.tcxo_a3, namespace.tcxo_a2, namespace.tcxo_a1, namespace.tcxo_a0 ] for a in srcA: if a is not None: coeffs.append(a) hasHighOrder = True elif hasHighOrder: coeffs.append(0.) tcxo = TCXOPoly(coeffs) elif namespace.tcxo_type == "sine": initial = 0. ampl = 0.5 period_s = 1. if namespace.tcxo_a0 is not None: ampl = namespace.tcxo_a0 if namespace.tcxo_a1 is not None: ampl = namespace.tcxo_a1 if namespace.tcxo_period is not None: period_s = namespace.tcxo_period tcxo = TCXOSine(initial, ampl, period_s) else: raise ValueError("Unsupported TCXO type") namespace.tcxo = tcxo
def prepareArgsParser(): ''' Constructs command line argument parser. Returns ------- object Command line argument parser object. ''' class AddSv(argparse.Action): def __init__(self, option_strings, dest, nargs=None, **kwargs): super(AddSv, self).__init__(option_strings, dest, **kwargs) def __call__(self, parser, namespace, values, option_string=None): # Initialize SV list if not yet done if namespace.gps_sv is None: namespace.gps_sv = [] # Add SV to the tail of the list. if option_string == '--gps-sv': sv = GPSSatellite(int(values)) elif option_string == '--glo-sv': sv = GLOSatellite(int(values)) else: raise ValueError("Option value is not supported: %s" % option_string) namespace.gps_sv.append(sv) # Reset all configuration parameters namespace.l2cl_code_type = '01' namespace.ignore_code_doppler = False # Doppler namespace.doppler_type = "zero" namespace.doppler_value = 0. namespace.doppler_speed = 0. namespace.distance = None namespace.tec = 50. namespace.doppler_amplitude = 0. namespace.doppler_period = 1. namespace.symbol_delay = None namespace.chip_delay = None # Source message data namespace.message_type = "zero" namespace.message_file = None # Amplitude parameters namespace.amplitude_type = "poly" namespace.amplitude_unis = "snr-db" namespace.amplitude_a0 = None namespace.amplitude_a1 = None namespace.amplitude_a2 = None namespace.amplitude_a3 = None namespace.amplitude_period = None class UpdateSv(argparse.Action): def __init__(self, option_strings, dest, nargs=None, **kwargs): super(UpdateSv, self).__init__(option_strings, dest, **kwargs) def __call__(self, parser, namespace, values, option_string=None): sv_list = getattr(namespace, "gps_sv") if sv_list is None: raise ValueError("No SV specified") setattr(namespace, self.dest, values) # super(UpdateSv, self).__call__(parser, namespace, values, option_string) self.doUpdate(sv_list[len(sv_list) - 1], parser, namespace, values, option_string) def doUpdate(self, sv, parser, namespace, values, option_string): pass class UpdateBands(UpdateSv): def __init__(self, option_strings, dest, nargs=None, **kwargs): super(UpdateBands, self).__init__(option_strings, dest, **kwargs) def doUpdate(self, sv, parser, namespace, values, option_string): l1caEnabled = False l2cEnabled = False if namespace.bands == "l1ca" or namespace.bands == 'l1': l1caEnabled = True elif namespace.bands == "l2c" or namespace.bands == 'l2': l2cEnabled = True elif namespace.bands == "l1ca+l2c" or namespace.bands == 'l1+l2': l1caEnabled = True l2cEnabled = True else: raise ValueError() if isinstance(sv, GPSSatellite): sv.setL2CLCodeType(namespace.l2cl_code_type) sv.setL1CAEnabled(l1caEnabled) sv.setL2CEnabled(l2cEnabled) elif isinstance(sv, GLOSatellite): sv.setL1Enabled(l1caEnabled) sv.setL2Enabled(l2cEnabled) else: raise ValueError("Unsupported object type in SV list") class UpdateDopplerType(UpdateSv): def __init__(self, option_strings, dest, nargs=None, **kwargs): super(UpdateDopplerType, self).__init__(option_strings, dest, **kwargs) def doUpdate(self, sv, parser, namespace, values, option_string): if isinstance(sv, GPSSatellite): if sv.l1caEnabled: signal = signals.GPS.L1CA elif sv.l2cEnabled: signal = signals.GPS.L2C else: raise ValueError( "Signal band must be specified before doppler") elif isinstance(sv, GLOSatellite): if sv.isL1Enabled(): frequency_hz = signals.GLONASS.L1S[ sv.prn].CENTER_FREQUENCY_HZ elif sv.isL2Enabled(): frequency_hz = signals.GLONASS.L2S[ sv.prn].CENTER_FREQUENCY_HZ else: raise ValueError( "Signal band must be specified before doppler") else: raise ValueError( "Signal band must be specified before doppler") frequency_hz = signal.CENTER_FREQUENCY_HZ # Select distance: either from a distance parameter or from delays if namespace.symbol_delay is not None or namespace.chip_delay is not None: distance = computeDistanceDelay(namespace.symbol_delay, namespace.chip_delay, signal) else: distance = namespace.distance if namespace.distance is not None else 0. if namespace.doppler_type == "zero": doppler = zeroDoppler(distance, namespace.tec, frequency_hz) elif namespace.doppler_type == "const": doppler = constDoppler(distance, namespace.tec, frequency_hz, namespace.doppler_value) elif namespace.doppler_type == "linear": doppler = linearDoppler(distance, namespace.tec, frequency_hz, namespace.doppler_value, namespace.doppler_speed) elif namespace.doppler_type == "sine": doppler = sineDoppler(distance, namespace.tec, frequency_hz, namespace.doppler_value, namespace.doppler_amplitude, namespace.doppler_period) else: raise ValueError("Unsupported doppler type") sv.doppler = doppler class DisableCodeDoppler(UpdateSv): def __init__(self, option_strings, dest, nargs=None, **kwargs): super(DisableCodeDoppler, self).__init__(option_strings, dest, **kwargs) def doUpdate(self, sv, parser, namespace, values, option_string): print "CD=", namespace.ignore_code_doppler, values, option_string sv.setCodeDopplerIgnored(namespace.ignore_code_doppler) class UpdateAmplitudeType(UpdateSv): def __init__(self, option_strings, dest, nargs=None, **kwargs): super(UpdateAmplitudeType, self).__init__(option_strings, dest, **kwargs) def doUpdate(self, sv, parser, namespace, values, option_string): amplitude_units = AMP_MAP[namespace.amplitude_units] if namespace.amplitude_type == "poly": coeffs = [] hasHighOrder = False srcA = [ namespace.amplitude_a3, namespace.amplitude_a2, namespace.amplitude_a1, namespace.amplitude_a0 ] for a in srcA: if a is not None: coeffs.append(a) hasHighOrder = True elif hasHighOrder: coeffs.append(0.) amplitude = AmplitudePoly(amplitude_units, tuple(coeffs)) elif namespace.amplitude_type == "sine": initial = 1. ampl = 0.5 period_s = 1. if namespace.amplitude_a0 is not None: initial = namespace.amplitude_a0 if namespace.amplitude_a1 is not None: ampl = namespace.amplitude_a1 if namespace.amplitude_period is not None: period_s = namespace.amplitude_period amplitude = AmplitudeSine(amplitude_units, initial, ampl, period_s) else: raise ValueError("Unsupported amplitude type") sv.setAmplitude(amplitude) class UpdateTcxoType(argparse.Action): def __init__(self, option_strings, dest, nargs=None, **kwargs): super(UpdateTcxoType, self).__init__(option_strings, dest, **kwargs) def __call__(self, parser, namespace, values, option_string=None): setattr(namespace, self.dest, values) if namespace.tcxo_type == "poly": coeffs = [] hasHighOrder = False srcA = [ namespace.tcxo_a3, namespace.tcxo_a2, namespace.tcxo_a1, namespace.tcxo_a0 ] for a in srcA: if a is not None: coeffs.append(a) hasHighOrder = True elif hasHighOrder: coeffs.append(0.) tcxo = TCXOPoly(coeffs) elif namespace.tcxo_type == "sine": initial = 0. ampl = 0.5 period_s = 1. if namespace.tcxo_a0 is not None: ampl = namespace.tcxo_a0 if namespace.tcxo_a1 is not None: ampl = namespace.tcxo_a1 if namespace.tcxo_period is not None: period_s = namespace.tcxo_period tcxo = TCXOSine(initial, ampl, period_s) else: raise ValueError("Unsupported TCXO type") namespace.tcxo = tcxo class UpdateMessageType(UpdateSv): def __init__(self, option_strings, dest, nargs=None, **kwargs): super(UpdateMessageType, self).__init__(option_strings, dest, **kwargs) def doUpdate(self, sv, parser, namespace, values, option_string): if namespace.message_type == "zero": messageL1 = ConstMessage(1) messageL2 = messageL1 elif namespace.message_type == "one": messageL1 = ConstMessage(-1) messageL2 = messageL1 elif namespace.message_type == "zero+one": messageL1 = ZeroOneMessage() messageL2 = messageL1 elif namespace.message_type == "crc": if isinstance(sv, GPSSatellite): messageL1 = LNavMessage(sv.prn) messageL2 = CNavMessage(sv.prn) elif isinstance(sv, GLOSatellite): messageL1 = GLOMessage(sv.prn) messageL2 = GLOMessage(sv.prn) else: raise ValueError( "Message type is not supported for a satellite type") else: raise ValueError("Unsupported message type") if isinstance(sv, GPSSatellite): sv.setL1CAMessage(messageL1) sv.setL2CMessage(messageL2) elif isinstance(sv, GLOSatellite): sv.setL1Message(messageL1) sv.setL2Message(messageL2) else: raise ValueError("Unsupported object type in SV list") class UpdateMessageFile(UpdateSv): def __init__(self, option_strings, dest, nargs=None, **kwargs): super(UpdateMessageFile, self).__init__(option_strings, dest, **kwargs) def doUpdate(self, sv, parser, namespace, values, option_string): data = numpy.fromfile(namespace.message_file, dtype=numpy.uint8) namespace.message_file.close() data = numpy.unpackbits(data) data = numpy.asarray(data, dtype=numpy.int8) data <<= 1 data -= 1 numpy.negative(data, out=data) message = BlockMessage(data) if isinstance(sv, GPSSatellite): sv.setL1CAMessage(message) sv.setL2CMessage(message) elif isinstance(sv, GLOSatellite): sv.setL1Message(message) sv.setL2Message(message) else: raise ValueError("Unsupported object type in SV list") class SaveConfigAction(argparse.Action): def __init__(self, option_strings, dest, nargs=None, **kwargs): super(SaveConfigAction, self).__init__(option_strings, dest, **kwargs) def __call__(self, parser, namespace, values, option_string=None): gps_sv = namespace.gps_sv encoded_gps_sv = [satelliteFO.toMapForm(sv) for sv in gps_sv] data = { 'type': 'Namespace', 'gps_sv': encoded_gps_sv, 'profile': namespace.profile, 'encoder': namespace.encoder, 'generate': namespace.generate, 'noise_sigma': namespace.noise_sigma, 'filter_type': namespace.filter_type, 'tcxo': tcxoFO.toMapForm(namespace.tcxo), 'group_delays': namespace.group_delays } json.dump(data, values, indent=2) values.close() namespace.no_run = True class LoadConfigAction(argparse.Action): def __init__(self, option_strings, dest, nargs=None, **kwargs): super(LoadConfigAction, self).__init__(option_strings, dest, **kwargs) def __call__(self, parser, namespace, values, option_string=None): loaded = json.load(values) namespace.profile = loaded['profile'] namespace.encoder = loaded['encoder'] namespace.generate = loaded['generate'] namespace.noise_sigma = loaded['noise_sigma'] namespace.filter_type = loaded['filter_type'] namespace.tcxo = tcxoFO.fromMapForm(loaded['tcxo']) namespace.gps_sv = [ satelliteFO.fromMapForm(sv) for sv in loaded['gps_sv'] ] namespace.group_delays = loaded['group_delays'] values.close() parser = argparse.ArgumentParser(description="Signal generator", usage='%(prog)s [options]') parser.add_argument('--gps-sv', default=[], help='Enable GPS satellite', action=AddSv) parser.add_argument('--glo-sv', default=[], help='Enable GLONASS satellite', action=AddSv) parser.add_argument( '--bands', default="l1ca", choices=["l1ca", "l2c", "l1ca+l2c", "l1", "l2", "l1+l2"], help="Signal bands to enable", action=UpdateBands) dopplerGrp = parser.add_argument_group("Doppler Control", "Doppler control parameters") dopplerGrp.add_argument('--doppler-type', default="zero", choices=["zero", "const", "linear", "sine"], help="Configure doppler type", action=UpdateDopplerType) dopplerGrp.add_argument('--doppler-value', type=float, help="Doppler shift in hertz (initial)", action=UpdateDopplerType) dopplerGrp.add_argument('--doppler-speed', type=float, help="Doppler shift change in hertz/second", action=UpdateDopplerType) delayGrp = parser.add_argument_group("Signal Delay Control", "Signal delay control parameters") # Common delays: ionosphere delayGrp.add_argument('--tec', type=float, help="Ionosphere TEC for signal delay" " (electrons per meter^2)", action=UpdateDopplerType) # Distance control over direct parameter delayGrp.add_argument('--distance', type=float, help="Distance in meters for signal delay (initial)", action=UpdateDopplerType) # Distance control over delays delayGrp.add_argument('--symbol-delay', type=float, help="Initial symbol index", action=UpdateDopplerType) delayGrp.add_argument('--chip-delay', type=float, help="Initial chip index", action=UpdateDopplerType) dopplerGrp.add_argument('--doppler-amplitude', type=float, help="Doppler change amplitude (hertz)", action=UpdateDopplerType) dopplerGrp.add_argument('--doppler-period', type=float, help="Doppler change period (seconds)", action=UpdateDopplerType) dopplerGrp.add_argument( '--ignore-code-doppler', type=bool, help="Disable doppler for code and data processing", action=DisableCodeDoppler) amplitudeGrp = parser.add_argument_group("Amplitude Control", "Amplitude control parameters") amplitudeGrp.add_argument( '--amplitude-type', default="poly", choices=["poly", "sine"], help="Configure amplitude type: polynomial or sine.", action=UpdateAmplitudeType) amplitudeGrp.add_argument('--amplitude-units', default="snr-db", choices=["snr-db", "snr", "amplitude", "power"], help="Configure amplitude units: SNR in dB; SNR;" " amplitude; power.", action=UpdateAmplitudeType) amplitudeGrp.add_argument('--amplitude-a0', type=float, help="Amplitude coefficient (a0 for polynomial;" " offset for sine)", action=UpdateAmplitudeType) amplitudeGrp.add_argument('--amplitude-a1', type=float, help="Amplitude coefficient (a1 for polynomial," " amplitude for size)", action=UpdateAmplitudeType) amplitudeGrp.add_argument('--amplitude-a2', type=float, help="Amplitude coefficient (a2 for polynomial)", action=UpdateAmplitudeType) amplitudeGrp.add_argument('--amplitude-a3', type=float, help="Amplitude coefficient (a3 for polynomial)", action=UpdateAmplitudeType) amplitudeGrp.add_argument('--amplitude-period', type=float, help="Amplitude period in seconds for sine", action=UpdateAmplitudeType) messageGrp = parser.add_argument_group("Message Data Control", "Message data control parameters") messageGrp.add_argument('--message-type', default="zero", choices=["zero", "one", "zero+one", "crc"], help="Message type", action=UpdateMessageType) messageGrp.add_argument('--message-file', type=argparse.FileType('rb'), help="Source file for message contents.", action=UpdateMessageFile) messageGrp.add_argument('--l2cl-code-type', default='01', choices=['01', '1', '0'], help="GPS L2 CL code type", action=UpdateBands) parser.add_argument('--filter-type', default='none', choices=['none', 'lowpass', 'bandpass'], help="Enable filter") parser.add_argument('--noise-sigma', type=float, default=1., help="Noise sigma for noise generation") tcxoGrp = parser.add_argument_group("TCXO Control", "TCXO control parameters") tcxoGrp.add_argument('--tcxo-type', choices=["poly", "sine"], help="TCXO drift type", action=UpdateTcxoType) tcxoGrp.add_argument('--tcxo-a0', type=float, help="TCXO a0 coefficient for polynomial TCXO drift" " or initial shift for sine TCXO drift", action=UpdateTcxoType) tcxoGrp.add_argument('--tcxo-a1', type=float, help="TCXO a1 coefficient for polynomial TCXO drift" " or amplitude for sine TCXO drift", action=UpdateTcxoType) tcxoGrp.add_argument('--tcxo-a2', type=float, help="TCXO a2 coefficient for polynomial TCXO drift", action=UpdateTcxoType) tcxoGrp.add_argument('--tcxo-a3', type=float, help="TCXO a3 coefficient for polynomial TCXO drift", action=UpdateTcxoType) tcxoGrp.add_argument('--tcxo-period', type=float, help="TCXO period in seconds for sine TCXO drift", action=UpdateTcxoType) parser.add_argument( '--group-delays', type=bool, help="Enable/disable group delays simulation between bands") parser.add_argument('--debug', type=argparse.FileType('wb'), help="Debug output file") parser.add_argument('--generate', type=float, default=3., help="Amount of data to generate, in seconds") parser.add_argument('--encoder', default="2bits", choices=["1bit", "2bits"], help="Output data format") parser.add_argument('--output', type=argparse.FileType('wb'), help="Output file name") parser.add_argument( '--profile', default="normal_rate", choices=["low_rate", "normal_rate", "high_rate", "custom_rate"], help="Output profile configuration") parser.add_argument('-j', '--jobs', type=int, default=0, help="Use parallel threads") parser.add_argument( '--save-config', type=argparse.FileType('wt'), help="Store configuration into file (implies --no-run)", action=SaveConfigAction) parser.add_argument('--load-config', type=argparse.FileType('rt'), help="Restore configuration from file", action=LoadConfigAction) parser.add_argument('--no-run', action="store_true", default=False, help="Do not generate output.") if sys.stdout.isatty(): progress_bar_default = 'stdout' elif sys.stderr.isatty(): progress_bar_default = 'stderr' else: progress_bar_default = 'none' parser.add_argument("--progress-bar", metavar='FLAG', choices=['stdout', 'stderr', 'none'], default=progress_bar_default, help="Show progress bar. Default is '%s'" % progress_bar_default) parser.set_defaults(tcxo=TCXOPoly(())) return parser