def fitpix(wave,pararr): # define bad pixels cfg.bad_pixels = update_bad_pixels() # this variable stores the indices of bad pixels ll=pararr[0] lz=pararr[3] lv1=pararr[5] lv2=pararr[6] relpix=[] for i in range(len(ll)): vels=jbg.veltrans(lz[i],wave,ll[i]) #w1=ll[i]*(1.+lz[i]+lv1[i]/c) #w2=ll[i]*(1.+lz[i]+lv2[i]/c) #p1=jbg.closest(wave,w1) #p2=jbg.closest(wave,w2) p1=jbg.closest(vels,lv1[i]) p2=jbg.closest(vels,lv2[i]) if ((p1>=10) & (p2<=(len(wave)-1-10))): relpix.extend(range(p1-10,p2+10)) elif (p1<10): relpix.extend(range(0, p2 + 10)) else: relpix.extend(range(p1 - 10, len(wave)-1)) rp = np.unique(np.array(relpix)) clean_rp = np.array([i for i in rp if i not in cfg.bad_pixels]) return clean_rp
def fitpix(wave,pararr,find_bad_pixels=True): if find_bad_pixels: # define bad pixels cfg.bad_pixels = update_bad_pixels() # this variable stores the indices of bad pixels else: cfg.bad_pixels = [] ll=pararr[0] lz=pararr[3] lv1=pararr[5] lv2=pararr[6] relpix=[] for i in range(len(ll)): vels=jbg.veltrans(lz[i],wave,ll[i]) p1=jbg.closest(vels,lv1[i]) p2=jbg.closest(vels,lv2[i]) if ((p1>=10) & (p2<=(len(wave)-1-10))): relpix.extend(range(p1-10,p2+10)) elif (p1<10): relpix.extend(range(0, p2 + 10)) else: relpix.extend(range(p1 - 10, len(wave)-1)) rp = np.unique(np.array(relpix)) clean_rp = np.array([i for i in rp if i not in cfg.bad_pixels]) return clean_rp
def fitpix(wave, pararr, find_bad_pixels=True): if find_bad_pixels: # define bad pixels cfg.bad_pixels = update_bad_pixels( ) # this variable stores the indices of bad pixels else: cfg.bad_pixels = [] ll = pararr[0] lz = pararr[3] lv1 = pararr[5] lv2 = pararr[6] relpix = [] for i in range(len(ll)): vels = jbg.veltrans(lz[i], wave, ll[i]) p1 = jbg.closest(vels, lv1[i]) p2 = jbg.closest(vels, lv2[i]) if ((p1 >= 10) & (p2 <= (len(wave) - 1 - 10))): relpix.extend(range(p1 - 10, p2 + 10)) elif (p1 < 10): relpix.extend(range(0, p2 + 10)) else: relpix.extend(range(p1 - 10, len(wave) - 1)) rp = np.unique(np.array(relpix)) clean_rp = np.array([i for i in rp if i not in cfg.bad_pixels]) if len(clean_rp) > 1: # Matt and Kirill trimming off tiny pixel patches max_index_jump = 4 # this is called buf in makevoigt min_group_size = 5 last_idx = clean_rp[0] group_idxs = [last_idx] really_clean_rp = [] for idx in clean_rp[1:]: jump = idx - last_idx if jump <= max_index_jump: group_idxs.append(idx) else: if len(group_idxs) >= min_group_size: really_clean_rp.extend(group_idxs) group_idxs = [idx] # start a new group last_idx = idx if len(group_idxs) >= min_group_size: really_clean_rp.extend(group_idxs) return np.array(really_clean_rp, dtype=int) else: return clean_rp
def initplot(self,fig,numchunks=8): wlen=len(self.spectrum.wavelength)/numchunks self.spls=[] if self.wave1==None: waveidx1=0 # Default to plotting entire spectrum for now else: waveidx1=jbg.closest(self.wave,self.wave1) if self.fitpars!=None: model=joebvpfit.voigtfunc(self.wave,self.datamodel.fitpars) sg=jbg.subplotgrid(numchunks) for i in range(numchunks): self.spls.append(fig.add_subplot(sg[i][0],sg[i][1],sg[i][2])) pixs=np.arange(waveidx1+i*wlen,waveidx1+(i+1)*wlen, dtype='int') self.spls[i].plot(self.wave[pixs],self.normflux[pixs], linestyle='steps-mid',linewidth=cfg.spec_linewidth) if self.fitpars!=None: self.spls[i].plot(self.wave,model,'r') self.spls[i].set_xlim(self.wave[pixs[0]],self.wave[pixs[-1]]) self.spls[i].set_ylim(cfg.ylim) self.spls[i].set_xlabel('wavelength', fontsize=cfg.xy_fontsize, labelpad=cfg.x_labelpad) self.spls[i].set_ylabel('relative flux', fontsize=cfg.xy_fontsize, labelpad=cfg.y_labelpad) self.spls[i].get_xaxis().get_major_formatter().set_scientific(False) self.spls[i].tick_params(axis='both', which='major',direction='in', pad=2,length=2) fig.subplots_adjust(top=0.98,bottom=0.05,left=0.08,right=0.97, wspace=0.15,hspace=0.24) self.addmpl(fig)
def initplot(self,fig,numchunks=8): wlen=len(self.spectrum.wavelength)/numchunks self.spls=[] if self.wave1==None: waveidx1=0 # Default to plotting entire spectrum for now else: waveidx1=jbg.closest(self.wave,self.wave1) if self.fitpars!=None: model=joebvpfit.voigtfunc(self.wave,self.datamodel.fitpars) sg=jbg.subplotgrid(numchunks) for i in range(numchunks): self.spls.append(fig.add_subplot(sg[i][0],sg[i][1],sg[i][2])) pixs=range(waveidx1+i*wlen,waveidx1+(i+1)*wlen) self.spls[i].plot(self.wave[pixs],self.normflux[pixs],linestyle='steps-mid') if self.fitpars!=None: self.spls[i].plot(self.wave,model,'r') self.spls[i].set_xlim(self.wave[pixs[0]],self.wave[pixs[-1]]) self.spls[i].set_ylim(cfg.ylim) self.spls[i].set_xlabel('wavelength',labelpad=0) self.spls[i].set_ylabel('relative flux',labelpad=-5) self.spls[i].get_xaxis().get_major_formatter().set_scientific(False) fig.subplots_adjust(top=0.98,bottom=0.05,left=0.08,right=0.97,wspace=0.15,hspace=0.25) self.addmpl(fig)
def updateplot(self): if self.wave1==None: waveidx1=0 # Default to plotting entire spectrum for now else: waveidx1=jbg.closest(self.wave,self.wave1) wlen=len(self.spectrum.wavelength)/self.numchunks for i,sp in enumerate(self.spls): sp.clear() prange=range(waveidx1+i*wlen,waveidx1+(i+1)*wlen) if ((len(self.fitpars[0])>0)): sp.plot(self.wave,self.normflux,linestyle='steps-mid') if self.pixtog==1: sp.plot(self.wave[cfg.fitidx], self.normflux[cfg.fitidx], 'gs', markersize=4, mec='green') model=joebvpfit.voigtfunc(self.wave,self.fitpars) res=self.normflux-model sp.plot(self.wave,model,'r') if self.restog==1: sp.plot(self.wave,-res,'.',color='black', ms=2) sp.plot(self.wave,[0]*len(self.wave),color='gray') ### label lines we are trying to fit if self.labeltog==1: for j in range(len(self.fitpars[0])): labelloc=self.fitpars[0][j]*(1.+self.fitpars[3][j])+self.fitpars[4][j]/c*self.fitpars[0][j]*(1.+self.fitpars[3][j]) label = ' {:.1f}_\nz{:.4f}'.format(self.fitpars[0][j], self.fitpars[3][j]) sp.text(labelloc, cfg.label_ypos, label, rotation=90, withdash=True, ha='center', va='bottom', clip_on=True, fontsize=cfg.label_fontsize) sp.plot(self.wave,self.normsig,linestyle='steps-mid',color='red', lw=0.5) sp.plot(self.wave,-self.normsig,linestyle='steps-mid',color='red', lw=0.5) sp.set_ylim(cfg.ylim) sp.set_xlim(self.wave[prange[0]],self.wave[prange[-1]]) sp.set_xlabel('wavelength (A)', fontsize=cfg.xy_fontsize, labelpad=cfg.x_labelpad) sp.set_ylabel('normalized flux', fontsize=cfg.xy_fontsize, labelpad=cfg.y_labelpad) sp.get_xaxis().get_major_formatter().set_scientific(False) sp.get_xaxis().get_major_formatter().set_useOffset(False) self.changefig(self.fig)
def updateplot(self): if self.wave1==None: waveidx1=0 # Default to plotting entire spectrum for now else: waveidx1=jbg.closest(self.wave,self.wave1) wlen=len(self.spectrum.wavelength)/self.numchunks for i,sp in enumerate(self.spls): sp.clear() prange=np.arange(waveidx1+i*wlen,waveidx1+(i+1)*wlen,dtype='int') if ((len(self.fitpars[0])>0)): sp.plot(self.wave,self.normflux,linestyle='steps-mid') if self.pixtog==1: sp.plot(self.wave[cfg.fitidx], self.normflux[cfg.fitidx], 'gs', markersize=4, mec='green') model=joebvpfit.voigtfunc(self.wave,self.fitpars) res=self.normflux-model sp.plot(self.wave,model,'r') if self.restog==1: sp.plot(self.wave,-res,'.',color='black', ms=cfg.residual_markersize) sp.plot(self.wave,[0]*len(self.wave),color='gray') ### label lines we are trying to fit if self.labeltog==1: for j in range(len(self.fitpars[0])): labelloc=self.fitpars[0][j]*(1.+self.fitpars[3][j])+self.fitpars[4][j]/c*self.fitpars[0][j]*(1.+self.fitpars[3][j]) label = ' {:.1f}_\nz{:.4f}'.format(self.fitpars[0][j], self.fitpars[3][j]) sp.text(labelloc, cfg.label_ypos, label, rotation=90, withdash=True, ha='center', va='bottom', clip_on=True, fontsize=cfg.label_fontsize) sp.plot(self.wave,self.normsig,linestyle='steps-mid',color='red', lw=0.5) sp.plot(self.wave,-self.normsig,linestyle='steps-mid',color='red', lw=0.5) sp.set_ylim(cfg.ylim) sp.set_xlim(self.wave[prange[0]],self.wave[prange[-1]]) sp.set_xlabel('wavelength (A)', fontsize=cfg.xy_fontsize, labelpad=cfg.x_labelpad) sp.set_ylabel('normalized flux', fontsize=cfg.xy_fontsize, labelpad=cfg.y_labelpad) sp.get_xaxis().get_major_formatter().set_scientific(False) sp.get_xaxis().get_major_formatter().set_useOffset(False) self.changefig(self.fig)
def picksyslines(z, comps): ''' Return all lines at a systemic redshift ''' zval = comps['z'][closest(comps['z'], z)] zmatches = np.where(np.abs(comps['z'] - zval) < 0.0001)[0] return [comps['idxs'][idx] for idx in zmatches]
def writelinepars(fitpars, fiterrors, parinfo, specfile, outfilename, linecmts=None): ''' Write fit parameters out to file. Parameters ---------- fitpars : list of lists Parameters for fit ready for fitter! fiterrors : array of numpy vectors Error array for the fitting initialized to '0' for each param parinfo : array of arrays Flags to be used in fit specfile : str Name of the input file containing the spectrum outfilename : str Parameter output filename linecmts : list of lists, optional Reliability flags and comments, e.g., from igmguesses ''' import os ### Set outputs and open files bigfiletowrite = cfg.largeVPparfile filetowrite = outfilename if os.path.isfile(filetowrite): VPparfile = open(filetowrite, 'wb') bigparfile = open(bigfiletowrite, 'ab') # Append to the running list else: VPparfile = open(filetowrite, 'wb') bigparfile = open(bigfiletowrite, 'wb') ### Prep header of line parameter file if linecmts is not None: header = b'specfile|restwave|zsys|col|sigcol|bval|sigbval|vel|sigvel|nflag|bflag|vflag|vlim1|vlim2|wobs1|wobs2|pix1|pix2|z_comp|trans|rely|comment \n' else: header = b'specfile|restwave|zsys|col|sigcol|bval|sigbval|vel|sigvel|nflag|bflag|vflag|vlim1|vlim2|wobs1|wobs2|pix1|pix2|z_comp|trans \n' VPparfile.write(header) bigparfile.write(header) ### Grab parameters/info for each line for i in range(len(fitpars[0])): zline = fitpars[3][i] vlim1 = fitpars[5][i] vlim2 = fitpars[6][i] restwave = fitpars[0][i] wobs1 = restwave * (1 + zline + vlim1 / 299792.458) wobs2 = restwave * (1 + zline + vlim2 / 299792.458) pix1 = jbg.closest(cfg.wave, wobs1) pix2 = jbg.closest(cfg.wave, wobs2) trans = atomicdata.lam2ion(fitpars[0][i]) z_comp = ltu.z_from_dv(fitpars[4][i] * u.km / u.s, zline) if linecmts is not None: towrite = jbg.pipedelimrow([ specfile, restwave, round(zline, 5), round(fitpars[1][i], 3), round(fiterrors[1][i], 3), round(fitpars[2][i], 3), round(fiterrors[2][i], 3), round(fitpars[4][i], 3), round(fiterrors[4][i], 3), parinfo[1][i], parinfo[2][i], parinfo[4][i], vlim1, vlim2, wobs1, wobs2, pix1, pix2, round(z_comp, 5), trans, linecmts[0][i], linecmts[1][i] ]) else: towrite = jbg.pipedelimrow([ specfile, restwave, round(zline, 5), round(fitpars[1][i], 3), round(fiterrors[1][i], 3), round(fitpars[2][i], 3), round(fiterrors[2][i], 3), round(fitpars[4][i], 3), round(fiterrors[4][i], 3), parinfo[1][i], parinfo[2][i], parinfo[4][i], vlim1, vlim2, wobs1, wobs2, pix1, pix2, round(z_comp, 5), trans ]) VPparfile.write(towrite.encode()) bigparfile.write(towrite.encode()) VPparfile.close() bigparfile.close() print('Line parameters written to:') print(filetowrite)
def initlinepars(zs, restwaves, initvals=[], initinfo=[]): ''' Parameters ---------- zs : numpy vector of floats Redshifts of lines (this parameter will be fixed during fitting) restwaves : numpy vector of floats Rest frame wavelengths of lines to be fitted initvals : list of numpy vectors, optional Contains the following (in order): [restwaves,linecol,lineb,zs,linevel,linevlim1,linevlim2] Will default to values set in cfg.py if not set initinfo : list of numpy vectors, optional Contains the flags for fitting (in order): [colflag,bflag,velflag] Parameters with flags = 0 and 1 will freely value and fixed, respectively If 2 or more lines have the same flag value for the same parameter, the parameters will be tied to one another. Returns ------- initpars : list of lists Parameters for fit ready for fitter! parinfo : array of arrays Flags to be used in fit ''' ### Set atomic data for each line lam, fosc, gam = atomicdata.setatomicdata(restwaves) cfg.lams = lam cfg.fosc = fosc cfg.gam = gam initpars = [[], [], [], [], [], [], []] defaultcol = cfg.defaultcol defaultb = cfg.defaultb if initvals == []: for i in range(len(restwaves)): initpars[0].extend([restwaves[i]]) initpars[1].extend([defaultcol]) initpars[2].extend([defaultb]) initpars[3].extend([zs[i]]) initpars[4].extend([0.]) initpars[5].extend([-cfg.defaultvlim]) initpars[6].extend([cfg.defaultvlim]) else: if len(initvals) == 5: for i in range(len(restwaves)): initpars[0].extend([initvals[0][i]]) initpars[1].extend([initvals[1][i]]) initpars[2].extend([initvals[2][i]]) initpars[3].extend([initvals[3][i]]) initpars[4].extend([initvals[4][i]]) initpars[5].extend([-cfg.defaultvlim]) initpars[6].extend([cfg.defaultvlim]) else: initpars = [[], [], [], [], [], [], []] for i in range(len(restwaves)): initpars[0].extend([initvals[0][i]]) initpars[1].extend([initvals[1][i]]) initpars[2].extend([initvals[2][i]]) initpars[3].extend([initvals[3][i]]) initpars[4].extend([initvals[4][i]]) initpars[5].extend([initvals[5][i]]) initpars[6].extend([initvals[6][i]]) #cfg.lowblim alteration was removed from here parinfo = np.zeros([5, len(restwaves)], dtype=int) parinfo[0] = parinfo[0] + 1 parinfo[3] = parinfo[3] + 1 if ((initinfo == []) & (initvals == [])): ### Look for multiplet membership of each line seriesassoc = np.zeros(len(restwaves)) - 99 for i in range(len(restwaves)): for j in range(len(cfg.multiplets)): currmult = np.array(cfg.multiplets[j]) if (abs(restwaves[i] - currmult[jbg.closest(currmult, restwaves[i])]) < 0.01): seriesassoc[i] = j uqions = np.unique(seriesassoc).tolist() if -99 in uqions: uqions.remove(-99) flagctr = 2 for uqion in uqions: ionmatch = np.where(seriesassoc == uqion)[0] uqzs = np.unique(zs[ionmatch]) for uz in uqzs: matchcrit = (zs == uz) & (seriesassoc == uqion) rellines = np.where(matchcrit)[0] uqlams = np.unique(restwaves[rellines]) if len(uqlams) > 1: complist = [] numcomps = [] for ul in uqlams: matchcrit2 = matchcrit & (restwaves == ul) matches = np.where(matchcrit2)[0] complist.append(matches) numcomps.append(len(matches)) numcomps = np.array(numcomps) complist = np.array(complist) compidxsort = sorted(range(len(numcomps)), key=lambda x: numcomps[x], reverse=True) numcompsort = numcomps[compidxsort] complistsort = complist[compidxsort] maxcomps = numcompsort[0] for compidx in range(maxcomps): for li in range(len(complistsort)): if compidx < numcompsort[li]: parinfo[1][complistsort[li][compidx]] = flagctr parinfo[2][complistsort[li][compidx]] = flagctr parinfo[4][complistsort[li][compidx]] = flagctr else: continue flagctr += 1 elif initinfo != []: parinfo[1] = initinfo[0] parinfo[2] = initinfo[1] parinfo[4] = initinfo[2] elif ((initinfo == []) & (initvals != [])): ### Look for multiplet membership of each line seriesassoc = np.zeros(len(restwaves)) - 99 for i in range(len(restwaves)): for j in range(len(cfg.multiplets)): currmult = np.array(cfg.multiplets[j]) if (abs(restwaves[i] - currmult[jbg.closest(currmult, restwaves[i])]) < 0.01): seriesassoc[i] = j ### Fix measurements that are imported for i in range(len(restwaves)): if ((initpars[1][i] != defaultcol) & (initpars[2][i] != defaultb)): parinfo[1][i] = 1 parinfo[2][i] = 1 parinfo[4][i] = 1 uqions = np.unique(seriesassoc).tolist() if -99 in uqions: uqions.remove(-99) flagctr = 2 for uqion in uqions: ionmatch = np.where(seriesassoc == uqion)[0] uqzs = np.unique(zs[ionmatch]) for uz in uqzs: matchcrit = (zs == uz) & (seriesassoc == uqion) rellines = np.where(matchcrit)[0] uqlams = np.unique(restwaves[rellines]) if len(uqlams) > 1: complist = [] numcomps = [] for ul in uqlams: matchcrit2 = matchcrit & (restwaves == ul) matches = np.where(matchcrit2)[0] complist.append(matches.tolist()) numcomps.append(len(matches)) numcomps = np.array(numcomps) complist = np.array(complist) compidxsort = sorted(range(len(numcomps)), key=lambda x: numcomps[x]) complistsort = complist[compidxsort] complistsort = complistsort.tolist() for i in range(len(complistsort) - 1): for idx in complistsort[i]: parinfo[1][idx] = flagctr parinfo[2][idx] = flagctr parinfo[4][idx] = flagctr for j in range(i + 1, len(complistsort)): idxidx = jbg.closest( initvals[4][complistsort[j]], initvals[4][idx]) clidx = complistsort[j][idxidx] parinfo[1][clidx] = flagctr parinfo[2][clidx] = flagctr parinfo[4][clidx] = flagctr complistsort[j].remove(clidx) flagctr += 1 return initpars, parinfo
def writelinepars(fitpars,fiterrors,parinfo, specfile, outfilename, linecmts=None): ''' Write fit parameters out to file. Parameters ---------- fitpars : list of lists Parameters for fit ready for fitter! fiterrors : array of numpy vectors Error array for the fitting initialized to '0' for each param parinfo : array of arrays Flags to be used in fit specfile : str Name of the input file containing the spectrum outfilename : str Parameter output filename linecmts : list of lists, optional Reliability flags and comments, e.g., from igmguesses ''' import os ### Set outputs and open files bigfiletowrite = cfg.largeVPparfile filetowrite = outfilename if os.path.isfile(filetowrite): VPparfile = open(filetowrite, 'wb') bigparfile = open(bigfiletowrite, 'ab') # Append to the running list else: VPparfile = open(filetowrite, 'wb') bigparfile = open(bigfiletowrite, 'wb') ### Prep header of line parameter file if linecmts is not None: header = 'specfile|restwave|zsys|col|sigcol|bval|sigbval|vel|sigvel|nflag|bflag|vflag|vlim1|vlim2|wobs1|wobs2|pix1|pix2|z_comp|trans|rely|comment \n' else: header = 'specfile|restwave|zsys|col|sigcol|bval|sigbval|vel|sigvel|nflag|bflag|vflag|vlim1|vlim2|wobs1|wobs2|pix1|pix2|z_comp|trans \n' VPparfile.write(header) bigparfile.write(header) ### Grab parameters/info for each line for i in range(len(fitpars[0])): zline = fitpars[3][i] vlim1 = fitpars[5][i] vlim2 = fitpars[6][i] restwave = fitpars[0][i] wobs1 = restwave * (1 + zline + vlim1 / 299792.458) wobs2 = restwave * (1 + zline + vlim2 / 299792.458) pix1 = jbg.closest(cfg.wave, wobs1) pix2 = jbg.closest(cfg.wave, wobs2) trans = atomicdata.lam2ion(fitpars[0][i]) z_comp = ltu.z_from_dv(fitpars[4][i]*u.km/u.s, zline) if linecmts is not None: towrite = jbg.pipedelimrow( [specfile, restwave, round(zline, 5), round(fitpars[1][i], 3), round(fiterrors[1][i], 3), round(fitpars[2][i], 3), round(fiterrors[2][i], 3), round(fitpars[4][i], 3), round(fiterrors[4][i], 3), parinfo[1][i], parinfo[2][i], parinfo[4][i], vlim1, vlim2, wobs1, wobs2, pix1, pix2,round(z_comp, 5), trans, linecmts[0][i],linecmts[1][i]]) else: towrite = jbg.pipedelimrow( [specfile, restwave, round(zline, 5), round(fitpars[1][i], 3), round(fiterrors[1][i], 3), round(fitpars[2][i], 3), round(fiterrors[2][i], 3), round(fitpars[4][i], 3), round(fiterrors[4][i], 3), parinfo[1][i], parinfo[2][i], parinfo[4][i], vlim1, vlim2, wobs1, wobs2, pix1, pix2, round(z_comp, 5),trans]) VPparfile.write(towrite) bigparfile.write(towrite) VPparfile.close() bigparfile.close() print('Line parameters written to:') print(filetowrite)
def initlinepars(zs,restwaves,initvals=[],initinfo=[]): ''' Parameters ---------- zs : numpy vector of floats Redshifts of lines (this parameter will be fixed during fitting) restwaves : numpy vector of floats Rest frame wavelengths of lines to be fitted initvals : list of numpy vectors, optional Contains the following (in order): [restwaves,linecol,lineb,zs,linevel,linevlim1,linevlim2] Will default to values set in cfg.py if not set initinfo : list of numpy vectors, optional Contains the flags for fitting (in order): [colflag,bflag,velflag] Parameters with flags = 0 and 1 will freely value and fixed, respectively If 2 or more lines have the same flag value for the same parameter, the parameters will be tied to one another. Returns ------- initpars : list of lists Parameters for fit ready for fitter! parinfo : array of arrays Flags to be used in fit ''' ### Set atomic data for each line lam,fosc,gam=atomicdata.setatomicdata(restwaves) cfg.lams=lam ; cfg.fosc=fosc ; cfg.gam=gam initpars=[[],[],[],[],[],[],[]] defaultcol=cfg.defaultcol defaultb=cfg.defaultb if initvals==[]: for i in range(len(restwaves)): initpars[0].extend([restwaves[i]]) initpars[1].extend([defaultcol]) initpars[2].extend([defaultb]) initpars[3].extend([zs[i]]) initpars[4].extend([0.]) initpars[5].extend([-cfg.defaultvlim]) initpars[6].extend([cfg.defaultvlim]) else: if len(initvals)==5: for i in range(len(restwaves)): initpars[0].extend([initvals[0][i]]) initpars[1].extend([initvals[1][i]]) initpars[2].extend([initvals[2][i]]) initpars[3].extend([initvals[3][i]]) initpars[4].extend([initvals[4][i]]) initpars[5].extend([-cfg.defaultvlim]) initpars[6].extend([cfg.defaultvlim]) else: initpars=[[],[],[],[],[],[],[]] for i in range(len(restwaves)): initpars[0].extend([initvals[0][i]]) initpars[1].extend([initvals[1][i]]) initpars[2].extend([initvals[2][i]]) initpars[3].extend([initvals[3][i]]) initpars[4].extend([initvals[4][i]]) initpars[5].extend([initvals[5][i]]) initpars[6].extend([initvals[6][i]]) ### If hard limits on Doppler b-value are smaller or greater than cfg.lowblim or cfg.upperblim, ### modify those limits maxb=np.max(initpars[2][:]) minb=np.min(initpars[2][:]) if maxb>cfg.upperblim: cfg.upperblim= maxb + 10. if minb<cfg.lowblim: cfg.lowblim= minb - 2. parinfo=np.zeros([5,len(restwaves)],dtype=int) parinfo[0]=parinfo[0]+1 parinfo[3]=parinfo[3]+1 if ((initinfo==[])&(initvals==[])): ### Look for multiplet membership of each line seriesassoc = np.zeros(len(restwaves)) - 99 for i in range(len(restwaves)): for j in range(len(cfg.multiplets)): currmult = np.array(cfg.multiplets[j]) if (abs(restwaves[i] - currmult[jbg.closest(currmult, restwaves[i])]) < 0.01): seriesassoc[i] = j uqions=np.unique(seriesassoc).tolist() if -99 in uqions: uqions.remove(-99) flagctr=2 for uqion in uqions: ionmatch=np.where(seriesassoc == uqion)[0] uqzs=np.unique(zs[ionmatch]) for uz in uqzs: matchcrit=(zs==uz)&(seriesassoc==uqion) rellines=np.where(matchcrit)[0] uqlams=np.unique(restwaves[rellines]) if len(uqlams)>1: complist=[] numcomps=[] for ul in uqlams: matchcrit2=matchcrit&(restwaves==ul) matches=np.where(matchcrit2)[0] complist.append(matches) numcomps.append(len(matches)) numcomps=np.array(numcomps) complist=np.array(complist) compidxsort=sorted(range(len(numcomps)),key = lambda x: numcomps[x],reverse=True) numcompsort=numcomps[compidxsort] complistsort=complist[compidxsort] maxcomps=numcompsort[0] for compidx in range(maxcomps): for li in range(len(complistsort)): if compidx<numcompsort[li]: parinfo[1][complistsort[li][compidx]]=flagctr parinfo[2][complistsort[li][compidx]]=flagctr parinfo[4][complistsort[li][compidx]]=flagctr else: continue flagctr+=1 elif initinfo!=[]: parinfo[1]=initinfo[0] parinfo[2]=initinfo[1] parinfo[4]=initinfo[2] elif ((initinfo==[])&(initvals!=[])): ### Look for multiplet membership of each line seriesassoc = np.zeros(len(restwaves)) - 99 for i in range(len(restwaves)): for j in range(len(cfg.multiplets)): currmult = np.array(cfg.multiplets[j]) if (abs(restwaves[i] - currmult[jbg.closest(currmult, restwaves[i])]) < 0.01): seriesassoc[i] = j ### Fix measurements that are imported for i in range(len(restwaves)): if ((initpars[1][i]!=defaultcol)&(initpars[2][i]!=defaultb)): parinfo[1][i]=1 ; parinfo[2][i]=1 ; parinfo[4][i]=1 uqions=np.unique(seriesassoc).tolist() if -99 in uqions: uqions.remove(-99) flagctr=2 for uqion in uqions: ionmatch=np.where(seriesassoc == uqion)[0] uqzs=np.unique(zs[ionmatch]) for uz in uqzs: matchcrit=(zs==uz)&(seriesassoc==uqion) rellines=np.where(matchcrit)[0] uqlams=np.unique(restwaves[rellines]) if len(uqlams)>1: complist=[] numcomps=[] for ul in uqlams: matchcrit2=matchcrit&(restwaves==ul) matches=np.where(matchcrit2)[0] complist.append(matches.tolist()) numcomps.append(len(matches)) numcomps=np.array(numcomps) complist=np.array(complist) compidxsort=sorted(range(len(numcomps)),key = lambda x: numcomps[x]) complistsort=complist[compidxsort] complistsort=complistsort.tolist() for i in range(len(complistsort)-1): for idx in complistsort[i]: parinfo[1][idx]=flagctr parinfo[2][idx]=flagctr parinfo[4][idx]=flagctr for j in range(i+1,len(complistsort)): idxidx=jbg.closest(initvals[4][complistsort[j]],initvals[4][idx]) clidx=complistsort[j][idxidx] parinfo[1][clidx]=flagctr parinfo[2][clidx]=flagctr parinfo[4][clidx]=flagctr complistsort[j].remove(clidx) flagctr+=1 return initpars,parinfo