Ejemplo n.º 1
0
def main(options):
    """
    The main method of PyHammer which executes the overarching procedure.

    Description:
        This is the main part of the code that executes the
        actual pyhammer algorithms. This is arrived at either
        by startCmd or StartGUI, both of which get all the
        necessary options from the user and pass them to
        this function. The general process of this function
        should be to:
        
        - Define a Spectrum object to be used in reading files.
        - Load each spectrum sequentially.
        - Guess the spectral type.
        - Use the best guess for the spectral type and find the radial
          velocity shift. Shift the spectrum to rest.
        - Guess the spectral type again.
        - Repeat for all spectra
        - Bring up eyecheck GUI.

    Input:
        options: A dict containing the options the user has specified.

    Output:
        This program outputs two files, an outfile and a rejectfile.
        The outfile contains all results of the spectral type guess
        as well as the user's eyecheck guess and the rejectfile contains
        the list of spectra which could not be classified for some reason.
    """

    # Create a Spectrum object
    spec = Spectrum()

    # If the user has decided to not skip to the eyecheck, let's
    # do some processing
    if not options["eyecheck"]:

        # Open the input file
        try:
            infile = open(options["infile"], "r")
        except IOError as e:
            notifyUser(options["useGUI"], str(e))
            return

        # Open and setup the output files
        outfile = open(options["outfile"], "w")
        rejectfile = open(options["rejectfile"], "w")
        outfile.write(
            "#Filename,Radial Velocity (km/s),Guessed Spectral Type,Guessed [Fe/H],User Spectral Type,User [Fe/H]\n"
        )
        rejectfile.write("#Filename,File Type,Spectra S/N\n")

        # Define the string to contain all failure messages. These will be compiled
        # and printed once at the end, if anything is put into it.
        rejectMessage = ""

        for i, line in enumerate(infile):
            # Remove extra whitespace and other unwanted characters and split
            line = line.strip()
            if line.find(",") > 0:
                line = line.replace(",", " ")
            fname, ftype = " ".join(line.split()).rsplit(" ", 1)

            # Print statement of progress for user
            print(i + 1, ") Processing ", os.path.basename(fname), sep="")

            # Now read in the current file (this process reads in the file, converts air to
            # vac when necessary and interpolates onto the template grid)
            success, message = spec.readFile(options["spectraPath"] + fname, ftype)

            # If the attempt at reading the file did not succeed, then we
            # should just continue
            if not success:
                rejectfile.write(fname + "," + ftype + ",N/A\n")
                rejectMessage += "FILE: " + fname + "  REASON: " + message.replace("\n", "") + "\n"
                continue

            # Now that we have the necessary data in the spec object, let's
            # begin processing.

            # --- 1 ---
            # Calculate the signal to noise of the spectrum to potentially reject
            if options["sncut"] is not None:
                snVal = spec.calcSN()
                if snVal < options["sncut"]:
                    rejectfile.write(fname + "," + ftype + "," + str(snVal) + "\n")
                    rejectMessage += (
                        "FILE: " + fname + "  REASON: S/N = " + str(snVal) + " < " + str(options["sncut"]) + "\n"
                    )
                    continue

            # --- 2 ---
            # Normalize the input spectrum to the same place where the templates are normalized (8000A)
            spec.normalizeFlux()

            # --- 3 ---
            # Call guessSpecType function for the initial guess
            # this function measures the lines then makes a guess of all parameters
            spec.guessSpecType()

            # --- 4 ---
            # Call findRadialVelocity function using the initial guess
            shift = spec.findRadialVelocity()

            # --- 5 ---
            # Call shiftToRest that shifts the spectrum to rest wavelengths,
            # then interp back onto the grid
            spec.shiftToRest(shift)
            spec.interpOntoGrid()

            # --- 6 ---
            # Repeat guessSpecType function to get a better guess of the spectral
            # type and metallicity
            spec.guessSpecType()

            # End of the automatic guessing. We should have:
            #  1. Spectrum object with observed wavelength, flux, var,
            #  2. rest wavelength,
            #  3. spectral type (guessed),
            #  4. radial velocity and uncertainty,
            #  5. metallicity estimate,
            #  6. and line indice measurements

            # --- 7 ---

            # Translate the numbered spectral types into letters
            letterSpt = ["O", "B", "A", "F", "G", "K", "M", "L"][spec.guess["specType"]]

            # Write the file
            outfile.write(
                fname
                + ","
                + str(shift)
                + ","
                + letterSpt
                + str(spec.guess["subType"])
                + ","
                + "{:+2.1f}".format(spec.guess["metal"])
                + ",nan,nan"
                + "\n"
            )

        # We're done so let's close all the files.
        infile.close()
        outfile.close()
        rejectfile.close()

        # Check that we processed every spectrum in the infile. If not, print out
        # the reject method.
        if rejectMessage != "":
            # Prepend to the reject message
            rejectMessage = (
                "The following is a list of rejected spectra\n"
                "along with the reason for its rejection.\n\n" + rejectMessage
            )
            notifyUser(options["useGUI"], rejectMessage)
            # Check if all spectra were skipped by seeing if the number of
            # lines in the reject message is equal to the number of spectra
            # processed (plus three lines for the prepended message). If
            # they were all skipped, theres nothing to eyecheck so return.
            if rejectMessage.count("\n") == i + 4:
                notifyUser(options["useGUI"], "All spectra were bad. Exiting PyHammer.")
                # Clean up any temporary input files created
                if os.path.basename(options["infile"])[:11] == "temp_input_":
                    os.remove(options["infile"])
                return

    # At this point, we should call up the GUI to do the eyechecking.
    Eyecheck(spec, options)

    # Clean up any temporary input files created
    if os.path.basename(options["infile"])[:11] == "temp_input_":
        os.remove(options["infile"])
Ejemplo n.º 2
0
def main(options):
    """
    The main method of PyHammer which executes the overarching procedure.

    Description:
        This is the main part of the code that executes the
        actual pyhammer algorithms. This is arrived at either
        by pyhammerStartCmd or PyHammerStartGui, both of which
        get all the necessary options from the user and pass
        them to this function. The general process of this
        function should be to:
        
        - Define a Spectrum object to be used in reading files.
        - Load each spectrum sequentially.
        - Guess the spectral type.
        - Use the best guess for the spectral type and find the radial
          velocity shift. Shift the spectrum to rest.
        - Guess the spectral type again.
        - Repeat for all spectra
        - Bring up eyecheck GUI.

    Input:
        options: A dict containing the options the user has specified.

    Output:
        This program outputs two files, an outfile and a rejectfile.
        The outfile contains all results of the spectral type guess
        as well as the user's eyecheck guess and the rejectfile contains
        the list of spectra which could not be classified for some reason.
    """

    # Create a Spectrum object
    spec = Spectrum()

    # If the user has decided to not skip to the eyecheck, let's
    # do some processing
    if not options['eyecheck']:

        # Open the input file
        try:
            infile = open(options['infile'], 'r')
        except IOError as e:
            notifyUser(options['useGUI'], str(e))
            return

        # Open and setup the output files
        outfile = open(options['outfile'], 'w')
        rejectfile = open(options['rejectfile'], 'w')
        outfile.write(
            '#Filename,File Type,Radial Velocity (km/s),Guessed Spectral Type,Guessed [Fe/H],User Spectral Type,User [Fe/H]\n'
        )
        rejectfile.write('#Filename,File Type,Spectra S/N\n')

        # Define the string to contain all failure messages. These will be compiled
        # and printed once at the end, if anything is put into it.
        rejectMessage = ''

        for i, line in enumerate(infile):
            # Remove extra whitespace and other unwanted characters and split
            line = line.strip()
            if ',' in line: line = line.replace(',', ' ')
            if ' ' in line:
                fname, ftype = ' '.join(line.split()).rsplit(' ', 1)
            else:
                fname = line
                ftype = None

            # Print statement of progress for user
            print(i + 1, ') Processing ', os.path.basename(fname), sep='')

            # Now read in the current file (this process reads in the file, converts air to
            # vac when necessary and interpolates onto the template grid)
            message, ftype = spec.readFile(options['spectraPath'] + fname,
                                           ftype)

            # If the attempt at reading the file did not succeed, then we
            # should just continue
            if message is not None:
                rejectfile.write(fname + ',' +
                                 ('N/A' if ftype is None else ftype) +
                                 ',N/A\n')
                rejectMessage += 'FILE: ' + fname + '\nREASON: ' + message.replace(
                    '\n', '') + '\n\n'
                continue

            # Now that we have the necessary data in the spec object, let's
            # begin processing.

            # --- 1 ---
            # Calculate the signal to noise of the spectrum to potentially reject
            if options['sncut'] is not None:
                snVal = spec.calcSN()
                if snVal < options['sncut']:
                    rejectfile.write(fname + ',' + ftype + ',' + str(snVal) +
                                     '\n')
                    rejectMessage += 'FILE: ' + fname + '\nREASON: S/N = ' + str(
                        snVal) + ' < ' + str(options['sncut']) + '\n\n'
                    continue

            # --- 2 ---
            # Normalize the input spectrum to the same place where the templates are normalized (8000A)
            spec.normalizeFlux()

            # --- 3 ---
            # Call guessSpecType function for the initial guess
            # this function measures the lines then makes a guess of all parameters
            spec.guessSpecType()

            # --- 4 ---
            # Call findRadialVelocity function using the initial guess
            shift = spec.findRadialVelocity()

            # --- 5 ---
            # Call shiftToRest that shifts the spectrum to rest wavelengths,
            # then interp back onto the grid
            spec.shiftToRest(shift)
            spec.interpOntoGrid()

            # --- 6 ---
            # Repeat guessSpecType function to get a better guess of the spectral
            # type and metallicity
            spec.guessSpecType()

            # End of the automatic guessing. We should have:
            #  1. Spectrum object with observed wavelength, flux, var,
            #  2. rest wavelength,
            #  3. spectral type (guessed),
            #  4. radial velocity and uncertainty,
            #  5. metallicity estimate,
            #  6. and line indice measurements

            # --- 7 ---

            # Translate the numbered spectral types into letters
            letterSpt = ['O', 'B', 'A', 'F', 'G', 'K', 'M',
                         'L'][spec.guess['specType']]

            # Write the file
            outfile.write(
                options['spectraPath'] + fname +
                ',' +  # The spectra path and filename
                ftype + ',' +  # The filetype
                str(shift) + ',' +  # The RV shift
                letterSpt + str(spec.guess['subType']) +
                ',' +  # The auto-guessed spectral type
                '{:+2.1f}'.format(
                    spec.guess['metal']) +  # The auto-guessed metallicity
                ',nan,nan\n')  # The to-be-determined user classifications

        # We're done so let's close all the files.
        infile.close()
        outfile.close()
        rejectfile.close()

        # Check that we processed every spectrum in the infile. If not, print out
        # the reject method.
        if rejectMessage != '':
            # Prepend to the reject message
            message = 'At least one spectra was rejected. See the details for more information.'
            notifyUser(options['useGUI'], message, details=rejectMessage)
            # Check if all spectra were skipped by seeing if the number of
            # lines in the reject message is equal to the number of processed
            # times 3 (since each reject message has three newlines). If they
            # were all skipped, theres nothing to eyecheck so return.
            if rejectMessage.count('\n') == 3 * (i + 1):
                notifyUser(options['useGUI'],
                           'All spectra were bad. Exiting PyHammer.')
                # Clean up any temporary input files created
                if os.path.basename(options['infile'])[:11] == 'temp_input_':

                    os.remove(options['infile'])
                return

    # At this point, we should call up the GUI to do the eyechecking.
    Eyecheck(spec, options)

    # Finally, clean up any temporary input files created
    if os.path.basename(options['infile'])[:11] == 'temp_input_':
        os.remove(options['infile'])