Esempio n. 1
0
def init_source_wl(spec: Spectrum) -> float:
    """
    When binning a source spectrum with the intention of shifting it back to rest frame and avoid re-binning,
    this method what the desired first wavelength should be in the source frame.

    Operates under the assumption that the desired rest frame bins are integer wavelength values.

    ie. if first wl in spectrum is 3805.43 at a redshift of z = 0.55, the first rest frame wavelength is 2454.4709...
    Thus, the first (integer wavelength) bin begins at 2454.

    Returning to the source frame, this becomes 3805.12.
    This method would, in this case, return 3805.12.  Pass this to the source binning process and it will begin the
    binning process there.


    :param spec: Source frame spectrum
    :type spec: Spectrum
    :return: initial source bin wavelength
    :rtype: float
    """
    z = shenCat.subkey(spec.getNS(), 'z')
    first_wl = spec.getWavelengths()[0] / (1 + z)
    first_wl = int(first_wl)
    first_wl *= (1 + z)
    return first_wl
Esempio n. 2
0
def source_frame_step(spec: Union[Spectrum, str],
                      desired_step: float = 1) -> float:
    """
    Determines the step size necessary (in the spectrum's source frame) which will yield the desired_step
    when the spectrum is shifted back to rest.

    :param spec:
    :param desired_step:
    :return:
    """
    if type(spec) == Spectrum:
        spec = spec.getNS()
    z = shenCat.subkey(spec, 'z')
    return (1 + z) * desired_step
Esempio n. 3
0
 def _sort_key(x: Union[Spectrum, str]) -> float:
     return shenCat.subkey(x.getNS() if isinstance(x, Spectrum) else x,
                           sort_key)
Esempio n. 4
0
def fit_spec_loader(path: str,
                    filename: str,
                    mask_dict: dict = DEF_MASK_DICT) -> Spectrum:
    """
    Loads a FIT spectrum file from SDSS DR 7 or lower.  Converts it into Spectrum type.

    Note: error_dict has the actual mask values as keys.  Loader will iterate through these keys
    and delete any points where these keys are found.  The dict format is an artifact where the values attached
    to each key are the SDSS error names in text.

    :param path: /path/to/file
    :param filename: filename.fits
    :param mask_dict: Defaults to DEF_ERR_DICT defined in this file if not passed
    :type path: str
    :type filename: str
    :type mask_dict: dict
    :rtype: Spectrum
    """
    from astropy.io.fits import getheader, getdata
    from fileio.utils import fileCheck, join
    from catalog import shenCat

    fileCheck(path, filename)

    shenCat.load()
    infile = join(path, filename)

    # Assemble basic info from the header
    # Check if the HW redshift is included in the shenCat.  If so, assign it,
    # otherwise use the one in the file
    header = getheader(infile, 0)
    namestring = "%05i-%04i-%03i" % (header['MJD'], header['PLATEID'],
                                     header['FIBERID'])
    z = shenCat.subkey(namestring, 'z') if namestring in shenCat else float(
        header['z'])
    gmag = float(header['MAG'].split()[1])  # Stored as UGRIZ

    data = getdata(infile, 0)
    flux_data = data[0].tolist(
    )  # first apertrure is the calibrated spectrum flux density
    # data[ 1 ] is the continuum-subtracted spectrum.  Not of interest
    err_data = data[2].tolist()  # third is the +/- of flux denisty
    mask_data = data[3].tolist()  # error mask

    # Wavelength values are not stored in FIT files.  Only three values are available, and these are used to
    # generate the wavelengths which correspond to the pixels
    #   i.e. wl[ pixel 0 ] -> flux density[ 0 ], error[ 0 ], mask[ 0 ], etc
    #
    # Those 3 values are:
    #   naxis1 : number of pixels stored
    #   coeff0 : Log10 of the first wavelength
    #   coeff1 : Log10 of the dispersion coefficient
    #
    # Log10( wavelengths ) are generated by the function:   log_wl_n( n ) = c0 + c1 * n
    # where n is the nth pixel
    # Then the wavelength, in angstroms is given 10^(log_wl_n)
    c0 = header['coeff0']
    c1 = header['coeff1']
    num_pixels = header['naxis1']
    # The actual wavelength generation happens here
    wavelengths = [pow(10, c0 + c1 * n) for n in num_pixels]

    out_spec = Spectrum(namestring=namestring, z=z, gmag=gmag)
    out_spec.setDict(wavelengths, flux_data, err_data)

    # Mask out the errors
    for i in range(len(err_data)):
        if __bit_mask(mask_data[i], mask_dict):
            del out_spec[wavelengths[i]]
    return out_spec
Esempio n. 5
0
def ab_z_plot( path: str, filename: str, points: Union[ dict, List[ str ], List[ Spectrum ] ],
               primary: Union[ str or Spectrum ] = None, plotTitle: str = "", n_sigma: float = 1,
               rs_fit_func: Callable[ [ float ], float ] = None, rs_fit_title: str = None, png: bool = False,
               debug: bool = False ) -> None:
    """
    Make an AB magnitude vs Redshift plot.
    
    The input values can vary from Spectrum to namestrings, or in the case of points, even a results_pipeline.  All data
    used for plotting is pulled out of shenCat, so if a Spectrum carries different information, it will be lost.
    
    If primary is not passed, this will simply make a scatter plot.  If it IS passed, this will generate a magnitude
    evolution line using tools.cosmo and will highlight that primary point in dark-red with n_sigma as the multiplier
    of evolution error
    
    The rs_fit_func can be used to provide a fit line a to the points data.  This will not fit the data - it should 
    already be fit to the data.  This will simply call it over the redshift range ( 0.46, 0.82 ) to generate a line on
    the plot and so should only take one value: rs_fit_func( z ).  A specific title for the key can be provided in 
    rs_fit_title.  Otherwise it will be labeled simply "Fit function."
    
    If png = True is passed, png terminal will be used to plot output rather than the default PDF terminal.  The
    filename extension will be adjusted accordingly.
    
    :param path: /path/to/output file
    :type path: str
    :param filename: output filename
    :type filename: str
    :param points:  list[ string ] or [ Spectrum ], dict{ namestring : otherdata }, or resutls_pipeline of data to plot
    :type points: list or dict or results_pipeline
    :param primary: Primary point to highlight / generate evolution from
    :type primary: Spectrum or str
    :param plotTitle: Title of plot
    :type plotTitle: str
    :param n_sigma: Magnitude evolution uncertainty multiplier
    :type n_sigma: float
    :param rs_fit_func: Callable.  Takes one input:  redshift over range ( 0.46, 0.82 ).  Returns one output: float
    :type rs_fit_func: Callable
    :param rs_fit_title: Title of rs_fit_function for key
    :type rs_fit_title: str
    :param png: Use PNG terminal rather than PDF terminal.  Not as pretty, but quicker to scroll between when visually parsing data
    :type png: bool
    :param debug: Don't output to a file, call Gnuplot with persist = True.
    :type debug: bool
    :return: 
    :rtype: None
    """
    from tools.cosmo import magnitude_evolution
    from catalog import shenCat

    """ Make AB vs Z points data """
    z_data = [ ]
    ab_data = [ ]
    ab_err = [ ]
    if type( points ) is list:
        if type( points[ 0 ] ) is str:
            for ns in points:
                z_data.append( shenCat.subkey( ns, 'z' ) )
                ab_data.append( shenCat.subkey( ns, 'ab' ) )
                ab_err.append( n_sigma * shenCat.subkey( ns, 'ab_err' ) )
        else:
            for spec in points:
                z_data.append( shenCat.subkey( spec.getNS(), 'z' ) )
                ab_data.append( shenCat.subkey( spec.getNS(), 'ab' ) )
                ab_err.append( n_sigma * shenCat.subkey( spec.getNS(), 'ab_err' ) )
    elif type( points ) is dict:
        for ns in points:
            z_data.append( shenCat.subkey( ns, 'z' ) )
            ab_data.append( shenCat.subkey( ns, 'ab' ) )
            ab_err.append( n_sigma * shenCat.subkey( ns, 'ab_err' ) )

    plot_points = make_points_plotitem( z_data, ab_data, ab_err, color="royalblue" )
    plotlist = [ plot_points ]

    """ If there is a primary value to identify, make that data """
    if primary is not None:
        if type( primary ) is Spectrum:
            if primary.getNS() in shenCat:
                p_z, p_ab, p_ab_err = shenCat.subkey( primary.getNS(), 'z', 'ab', 'ab_err' )
            else:
                p_z, p_ab, p_ab_err = primary.getRS(), primary.magAB(), primary.abErr()
            primary = primary.getNS()
        else:
            p_z, p_ab, p_ab_err = shenCat.subkey( primary, 'z', 'ab', 'ab_err' )

        """ Make Magnitude Evolutiion Data """
        p_ab_err *= n_sigma
        prime_upper_plot = make_line_plotitem( *magnitude_evolution( p_ab + p_ab_err, p_z, splitLists=True )[ :2 ],
                                               title="Upper / Lower Bounds of Expected Evolution", color="grey" )
        prime_lower_plot = make_line_plotitem( *magnitude_evolution( p_ab - p_ab_err, p_z, splitLists=True )[ :2 ],
                                               title="", color="grey" )
        prime_plot = make_line_plotitem( *magnitude_evolution( p_ab, p_z, splitLists=True )[ :2 ],
                                         title="Expected Evolution", color="black" )
        prime_point = make_points_plotitem( [ p_z ], [ p_ab ], error_data=[ p_ab_err ], title=f"{primary}",
                                            color="dark-red" )
        plotlist.extend( [ prime_plot, prime_upper_plot, prime_lower_plot, prime_point ] )

    if rs_fit_func is not None:
        fitx = [ (z / 100) for z in range( 46, 83 ) ]
        fity = [ rs_fit_func( z ) for z in fitx ]
        fitplot = make_line_plotitem( fitx, fity, "Fit Function" if rs_fit_title is None else rs_fit_title,
                                      with_=" dt '-'", color="grey50" )
        plotlist.append( fitplot )

    """ Data has been formed.  Make actual plot """
    g = Gnuplot.Gnuplot( persist=debug )
    g.title( r"%s" % plotTitle )
    g.xlabel( "Redshift" )
    g.ylabel( "AB Magnitude" )
    g( "set key bottom right opaque box" )
    g( "set grid" )
    g( "set xrange [0.46:0.82]" )

    if not debug:
        from fileio.utils import dirCheck, join
        dirCheck( path )
        if png:
            if not filename.lower().endswith( ".png" ): filename += ".png"
            g( 'set terminal png enhanced size 800, 600' )
        else:
            if not filename.lower().endswith( ".pdf" ): filename += ".pdf"
            g( 'set terminal pdf enhanced size 9,6' )
        g( f'set output {__fix_outpath( path, filename ) }' )

    g.plot( *plotlist )

    if not debug:
        g( 'set output' )
        g.close()