def OpenNormalFVFile(fv_file, type_str):
    """
    Open a normalized frequency vector file and check to make sure it's valid.

    The first line of a valid normalized FV file contains the number of vectors
    in the file followed by the char ':' and an optional char 'w'.

    Subsequent lines contain an optional weight (if 'w' is present on first line) followed
    by the number of fields in the vector, the char ':' and the values for the vector:  For example:

    80:w
    0.01250000000000000069 3:  0.00528070484084160793 0.00575272877173275011 0.00262986399034366479
    0.01250000000000000069 2:  0.00528070484084160793 0.00575272877173275011

    @return file pointer
    """

    # Read in the 1st line of the file and check for errors.
    #
    # import pdb;  pdb.set_trace()
    type_str = 'normalized frequency vector file: '
    fp = OpenFile(fv_file, type_str)
    line = fp.readline()
    field = line.split(':')
    num_vect = field[0]
    if not util.IsInt(num_vect):
        err_msg(type_str + fv_file)
    if len(field) == 2:
        if not 'w' in field[1]:
            err_msg(type_str + fv_file)
        else:
            weights = True

    # Read the 2nd line: an optional weight, the number of values in the vector and the vector itself.
    #
    line = fp.readline()
    if line == '':
        err_msg(type_str + fv_file)
    field = line.split()
    if weights:
        if not util.IsFloat(field[0]):
            err_msg(type_str + fv_file)
        field = field[1:]
    if len(field) < 2:
        err_msg(type_str + fv_file)
    num_field = int(field[0].split(':')[0])
    if not util.IsInt(num_field):
        err_msg(type_str + fv_file)
    field = field[1:]
    if len(field) != num_field:
        err_msg(type_str + fv_file)
    for f in field:
        if not util.IsFloat(f):
            err_msg(type_str + fv_file)
    fp.seek(0,0)

    return fp
def OpenWeightsFile(wt_file, type_str):
    """
    Open a weight file and check to make sure it's valid.  A valid
    wieght file must start with an floating point number.

    @return file pointer
    """

    fp = OpenFile(wt_file, type_str)
    line = fp.readline()
    field = line.split()
    if not util.IsFloat(field[0]):
        err_msg(weight_str + wt_file)
    fp.seek(0,0)

    return fp
def GetOptions():
    """
    Get users command line options/args and check to make sure they are correct.

    @return List of options and 3 file pointers for bbv, simpoint and weights files
    """

    version = '$Revision: 1.1 $';      version = version.replace('$Revision: ', '')
    ver = version.replace(' $', '')
    us = '%prog [options] action file_name [file_name]'
    desc = 'Implements several different actions to process FV (Frequency Vector) files.  ' \
           'An action must be defined in order for the script to run.  '\
           'All actions require at least one file name be given using an option. '\
           '                                                            '\
           '--------------------------------------------'\
           '                                                            '\
           'There are two types of frequency vector files:  '\
           '                                                            '\
           'BBV = Basic Block Vector, '\
           'LDV = LRU stack Distance Vector'


    parser = optparse.OptionParser(usage=us, version=ver, description=desc)

    cmd_options.focus_thread(parser, '')

    # Options which define the actions the script to execute
    #
    action_group = cmd_options.ActionGroup(parser)

    cmd_options.combine(parser, action_group)
    cmd_options.csv_region(parser, action_group)
    cmd_options.project_bbv(parser, action_group)
    cmd_options.weight_ldv(parser, action_group)

    parser.add_option_group(action_group )

    # Options which list the files the script can process
    #
    # import pdb;  pdb.set_trace()
    file_group = cmd_options.FileGroup(parser)

    cmd_options.bbv_file(parser, file_group)
    cmd_options.ldv_file(parser, file_group)
    cmd_options.normal_bbv(parser, file_group)
    cmd_options.normal_ldv(parser, file_group)
    cmd_options.region_file(parser, file_group)
    # cmd_options.vector_file(parser, file_group)
    cmd_options.weight_file(parser, file_group)

    parser.add_option_group(file_group)

    # Parse command line options and get any arguments.
    #
    (options, args) = parser.parse_args()

    matrix = ReadVectorFile(args[0])
    PrintVectorFile(matrix)
    sys.exit(0)

    def TrueXor(*args):
        """Return xor of some booleans."""
        return sum(args) == 1

    # Must have one, and only one, action on command line.
    #
    # import pdb;  pdb.set_trace()
    if not TrueXor(options.csv_region, options.project_bbv, options.weight_ldv, \
       options.combine != None):
           msg.PrintAndExit('Must give one, and only one, action for script to execute.\n'
           'Use -h to get help.')

    # Check to see if options required for the various actions are given.
    #
    file_error = lambda file, action: msg.PrintAndExit("Must use option '" + file + \
        "' to define the file to use with '"  + action + "'.   \nUse -h for help.")

    # import pdb;  pdb.set_trace()
    fp_bbv = fp_ldv = fp_simp = fp_weight = None
    if options.combine:
        # First check to make sure the scaling factor is a valid FP number between 0.0 and 1.0
        #
        if not util.IsFloat(options.combine):
           msg.PrintAndExit('Illegal value for scaling factor: ' + str(options.combine) + \
           '\nScaling factor must be a float between 0.0 and 1.0.')
        else:
            value = float(options.combine)
            if value < 0.0 or value > 1.0:
               msg.PrintAndExit('Scaling factor given (%f) must be between 0.0 and 1.0' % value)
            options.combine = value

        # Then check to make sure required files are given.
        #
        if not options.normal_bbv:
           file_error('--normal_bbv', '--combine')
        if not options.normal_ldv:
           file_error('--normal_ldv', '--combine')
        fp_bbv = OpenNormalFVFile(options.normal_bbv, 'projected, normalized BBV file: ')
        fp_ldv = OpenNormalFVFile(options.normal_ldv, 'projected, normalized BBV file: ')

    if options.csv_region:
        if not options.bbv_file:
           file_error('--bbv_file', '--csv_region')
        if not options.region_file:
           file_error('--region_file', '--csv_region')
        if not options.weight_file:
           file_error('--weight_file', '--csv_region')
        fp_bbv = OpenFVFile(options.bbv_file, 'Basic Block Vector (bbv) file: ')
        fp_simp = OpenSimpointFile(options.region_file, 'simpoints file: ')
        fp_weight = OpenWeightsFile(options.weight_file, 'weights file: ')

    if options.project_bbv:
        if not options.bbv_file:
           file_error('--bbv_file', '--project_bbv')
        fp_bbv = OpenFVFile(options.bbv_file, 'Basic Block Vector (bbv) file: ')

    if options.weight_ldv:
        if not options.ldv_file:
           file_error('--ldv_file', '--weight_ldv')
        fp_ldv = util.OpenCompressFile(options.ldv_file)

    return (options, fp_bbv, fp_ldv, fp_simp, fp_weight)