# # Copyright 2009 Free Software Foundation, Inc. # # This file is part of GNU Radio # # GNU Radio is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 3, or (at your option) # any later version. # # GNU Radio is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with GNU Radio; see the file COPYING. If not, write to # the Free Software Foundation, Inc., 51 Franklin Street, # Boston, MA 02110-1301, USA. # from gnuradio import eng_notation import math class abstract_converter(object): def external_to_internal(self, v): """ Convert from user specified value to value acceptable to underlying primitive. The underlying primitive usually expects strings. """ raise NotImplementedError def internal_to_external(self, s): """ Convert from underlying primitive value to user specified value. The underlying primitive usually expects strings. """ raise NotImplementedError def help(self): return "Any string is acceptable" class identity_converter(abstract_converter): def external_to_internal(self,v): return v def internal_to_external(self, s): return s ######################################################################## # Commonly used converters ######################################################################## class chooser_converter(abstract_converter): """ Convert between a set of possible choices and an index. Used in the chooser base and all sub-classes. """ def __init__(self, choices): #choices must be a list because tuple does not have .index() in python2.5 self._choices = list(choices) def external_to_internal(self, choice): return self._choices.index(choice) def internal_to_external(self, index): return self._choices[index] def help(self): return 'Enter a possible value in choices: "%s"'%str(self._choices) class bool_converter(abstract_converter): """ The internal representation is boolean. The external representation is specified. Used in the check box form. """ def __init__(self, true, false): self._true = true self._false = false def external_to_internal(self, v): if v == self._true: return True if v == self._false: return False raise Exception, 'Value "%s" is not a possible option.'%v def internal_to_external(self, v): if v: return self._true else: return self._false def help(self): return "Value must be in (%s, %s)."%(self._true, self._false) class eval_converter(abstract_converter): """ A catchall converter when int and float are not enough. Evaluate the internal representation with python's eval(). Possible uses, set a complex number, constellation points. Used in text box. """ def __init__(self, formatter=lambda x: '%s'%(x)): self._formatter = formatter def external_to_internal(self, v): return self._formatter(v) def internal_to_external(self, s): return eval(s) def help(self): return "Value must be evaluatable by python's eval." class str_converter(abstract_converter): def __init__(self, formatter=lambda x: '%s'%(x)): self._formatter = formatter def external_to_internal(self, v): return self._formatter(v) def internal_to_external(self, s): return str(s) class int_converter(abstract_converter): def __init__(self, formatter=lambda x: '%d'%round(x)): self._formatter = formatter def external_to_internal(self, v): return self._formatter(v) def internal_to_external(self, s): return int(s, 0) def help(self): return "Enter an integer. Leading 0x indicates hex" class float_converter(abstract_converter): def __init__(self, formatter=eng_notation.num_to_str): self._formatter = formatter def external_to_internal(self, v): return self._formatter(v) def internal_to_external(self, s): return eng_notation.str_to_num(s) def help(self): return "Enter a float with optional scale suffix. E.g., 100.1M" class slider_converter(abstract_converter): """ Scale values to and from the slider. """ def __init__(self, minimum, maximum, num_steps, cast): assert minimum < maximum assert num_steps > 0 self._offset = minimum self._scaler = float(maximum - minimum)/num_steps self._cast = cast def external_to_internal(self, v): return (v - self._offset)/self._scaler def internal_to_external(self, v): return self._cast(v*self._scaler + self._offset) def help(self): return "Value should be within slider range" class log_slider_converter(slider_converter): def __init__(self, min_exp, max_exp, num_steps, base): assert min_exp < max_exp assert num_steps > 0 self._base = base slider_converter.__init__(self, minimum=min_exp, maximum=max_exp, num_steps=num_steps, cast=float) def external_to_internal(self, v): return slider_converter.external_to_internal(self, math.log(v, self._base)) def internal_to_external(self, v): return self._base**slider_converter.internal_to_external(self, v)