import math


def parse_symmetric_morlet_max_modulus_parameters( parameter_map ):
    """
    Parses parameters for the maximum modulus, symmetric Morlet wavelet generator.
    Takes a dictionary of (key, string value)'s and casts the values to the types
    expected by get_symmetric_morlet_max_modulus_transform().

    The following keys are expected in the supplied parameter map:

      alpha  - Morlet wavelet preferred angle, in degrees.  Must be a finite
               floating point value.
      scales - Comma separated list of length scales.  Must be positive floating
               point values.

    Raises ValueError if any of the required parameters are missing, they cannot be
    cast to the required data type, they have invalid values for their use, or if
    they're incompatible with each other.

    Takes 1 argument:

      parameter_map - Dictionary of parameters to parse for
                      get_symmetric_morlet_max_modulus_transform().

    Returns 1 value:

      parameter_map - Dictionary of parameters with type cast values.

    """

    # parse a floating point angle.
    try:
        parameter_map["alpha"] = float( parameter_map["alpha"] )
    except Exception as e:
        raise ValueError( "Failed to parse a floating point angle, \"alpha\", "
                          " from '{:s}' ({:s}).".format(
                              parameter_map["alpha"],
                              str( e ) ) )

    # ensure this is a finite value.
    if not math.isfinite( parameter_map["alpha"] ):
        raise ValueError( "Alpha is not finite ({:f}).".format(
            parameter_map["alpha"] ) )

    # parse a list of floating point values.
    try:
        parameter_map["scales"] = list( map( lambda scale: float( scale ),
                                             parameter_map["scales"].split( "," ) ) )
    except Exception as e:
        raise ValueError( "Failed to parse a list of floating point length "
                          "scales, \"scales\", from '{:s}' ({:s}).".format(
                              parameter_map["scales"],
                              str( e ) ) )

    # ensure all of the length scales are finite.
    if not all( map( lambda scale: math.isfinite( scale ) and scale > 0,
                     parameter_map["scales"] ) ):
        raise ValueError( "Length scales must be positive and finite ({:s}).".format(
            ", ".join( map( lambda scale: str( scale ),
                            parameter_map["scales"] ) ) ) )

    # make sure we have at least one length scale to work with.
    if len( parameter_map["scales"] ) == 0:
        raise ValueError( "Must have at least one length scale!" )

    return parameter_map