def spectrum_linear_fit(spec: Spectrum, wl_low: float = None, wl_high: float = None) -> Tuple[float, float]: """ Applies a linear fit to a Specturm over the specified wavelength range. If no wl_ values are passed, the entirely of the spectrum range is used. Returns a tuple of ( m, b ) for: Flux Density = m * Wavelength + b :param spec: Spectrum to slope fit :type spec: Spectrum :param wl_low: Low limit of wavelength range. Defaults to None :type wl_low: float :param wl_high: Upper limit of wavelength range. Defaults to None :type wl_high: float :return: ( m, b ) :rtype: tuple """ wls = spec.getWavelengths() if wl_low is not None: wls = filter(lambda wl: wl >= wl_low, wls) if wl_high is not None: wls = filter(lambda wl: wl <= wl_high, wls) fluxdata = [ spec.getFlux(wl) for wl in wls ] # Can't use .getFluxlist here in clase wavelength limits used return generic_linear_fit(wls, fluxdata)
def source_bin(spec: Spectrum, step: float = None, init_wl: float = None) -> Spectrum: """ Bins a spectrum beginning given initial wavelength and desired bin spacing (step). If step and init_wl are not passed, this method will detrmine them directly from the source spectrum such that the rest frame spectrum has integer wavelengths spaced by 1 Angstrom steps. Intended to be used to bin a source spectrum which will then be shifted back into rest frame (via binned_source_to_rest). The rest frame spectrum will already be binned as a result. :param step: Desired source frame bin spacing. Will call source_frame_step( spec, 1 ) if this is not passed. :param init_wl: Desired inital bin wavelength. Will call init_source_wl( spec ) if this is not passed. :type spec: Spectrum :type step: float :type init_wl: float :return: Binned source spectrum :rtype: Spectrum """ from numpy import std, mean step = step or source_frame_step(spec, 1) oldwls = spec.getWavelengths() if init_wl is None: init_wl = init_source_wl(spec) max_wl = oldwls[-1] newwls = [init_wl] flxlist = [] errlist = [] newi = 0 oldi = 0 neww = newwls[newi] oldw = oldwls[oldi] while neww + step < max_wl: # Run until the last wavelength in spec is binned flux = [] # clear the current range of flux values while oldw < neww + step: # while the old wl is in the current bin, get its flux and advance to the next flux.append(spec.getFlux(oldw)) oldi += 1 oldw = oldwls[oldi] # see if the flux has more than one value (if so, take the mean and set the err as std deviation) # otherwise, assign it that value and error if len(flux) > 1: err = std(flux) flux = float(mean(flux)) elif len(flux) == 1: err = spec.getErr(oldwls[oldi - 1]) flux = flux[0] # if there were no values in this bin range (i.e. the flux variable is still a list, albiet an empty one) # then something's wrong. if type(flux) == float: flxlist.append(flux) errlist.append(err) while neww + step < oldw: neww += step newwls.append(neww) else: print( "Well, this is awkward. You're probably caught in an infinte loop." ) print( f"New WL:{new}, Last old wl:{oldw} on spectrun:{spec.getNS()}") spec = spec.cpy_info() spec.setDict(newwls[:-1], flxlist, errlist) return spec