def find_and_fit_edges(data, header, bs, options, edgeThreshold=450): ''' Given a flat field image, find_and_fit_edges determines the position of all slits. The function works by starting with a guess at the location for a slit edge in the spatial direction(options["first-slit-edge"]). Starting from the guess, find_edge_pair works out in either direction, measuring the position of the (e.g.) bottom of slit 1 and top of slit 2: ------ pixel y value = 2048 Slit 1 data ------ (bottom) deadband ------ (top) Slit N pixel data .... ------- (bottom) pixel = 0 --------------------------------> Spectral direction 1. At the top of the flat, the slit edge is defined to be a pixel value 2. The code guesses the position of the bottom of the slit, and runs find_edge_pair to measure slit edge locations. 3. A low-order polynomial is fit to the edge locations with fit_edge_poly 4. The top and bottom of the current slit, is stored into the result list. 5. The top of the next slit is stored temporarily for the next iteration of the for loop. 6. At the bottom of the flat, the slit edge is defined to be pixel 4. options: options["edge-order"] -- The order of the polynomial [pixels] edge. options["edge-fit-width"] -- The length [pixels] of the edge to fit over ''' # TODO: move hardcoded values into Options.py # y is the location to start y = 2034 DY = 44.25 toc = 0 ssl = bs.ssl slits = [] top = [0., np.float(Options.npix)] start_slit_num = int(bs.msl[0]['Slit_Number']) - 1 if start_slit_num > 0: y -= DY * start_slit_num # Count and check that the # of objects in the SSL matches that of the MSL # This is purely a safety check numslits = np.zeros(len(ssl)) for i in xrange(len(ssl)): slit = ssl[i] M = np.where(slit["Target_Name"] == bs.msl["Target_in_Slit"]) numslits[i] = len(M[0]) numslits = np.array(numslits) if (np.sum(numslits) != CSU.numslits) and (not bs.long_slit) and ( not bs.long2pos_slit) and (not bs.long2pos_slit_specphot): error("The number of allocated CSU slits (%i) does not match " " the number of possible slits (%i)." % (np.sum(numslits), CSU.numslits)) raise Exception( "The number of allocated CSU slits (%i) does not match " " the number of possible slits (%i)." % (np.sum(numslits), CSU.numslits)) # if the mask is a long slit, the default y value will be wrong. Set instead to be the middle if bs.long_slit: y = 1104 # now begin steps outline above results = [] result = {} result["Target_Name"] = ssl[0]["Target_Name"] # 1 result["top"] = np.poly1d([y]) ''' Nomenclature here is confusing: ----- Edge -- Top of current slit, bottom of prev slit . o ' Data ===== Data .;.;' Data ----- Edge -- Bottom of current slit, top of next slit ''' topfun = np.poly1d([y]) xposs_top_this = np.arange(10, 2000, 100) yposs_top_this = topfun(xposs_top_this) for target in xrange(len(ssl)): y -= DY * numslits[target] y = max(y, 1) info("%2.2i] Finding Slit Edges for %s ending at %4.0i. Slit " "composed of %i CSU slits" % (target, ssl[target]["Target_Name"], y, numslits[target])) ''' First deal with the current slit ''' hpps = Wavelength.estimate_half_power_points( bs.scislit_to_csuslit(target + 1)[0], header, bs) if y == 1: xposs_bot = [1024] xposs_bot_missing = [] yposs_bot = [4.25] botfun = np.poly1d(yposs_bot) ok = np.where((xposs_bot > hpps[0]) & (xposs_bot < hpps[1])) else: (xposs_top_next, xposs_top_next_missing, yposs_top_next, xposs_bot, xposs_bot_missing, yposs_bot, scatter_bot_this) = find_edge_pair(data, y, options["edge-fit-width"], edgeThreshold=edgeThreshold) ok = np.where((xposs_bot > hpps[0]) & (xposs_bot < hpps[1])) ok2 = np.where((xposs_bot_missing > hpps[0]) & (xposs_bot_missing < hpps[1])) xposs_bot = xposs_bot[ok] xposs_bot_missing = xposs_bot_missing[ok2] yposs_bot = yposs_bot[ok] if len(xposs_bot) == 0: botfun = np.poly1d(y - DY) else: (botfun, bot_res, botsd, botok) = fit_edge_poly(xposs_bot, xposs_bot_missing, yposs_bot, options["edge-order"]) bot = botfun.c.copy() top = topfun.c.copy() #4 result = {} result["Target_Name"] = ssl[target]["Target_Name"] result["xposs_top"] = xposs_top_this result["yposs_top"] = yposs_top_this result["xposs_bot"] = xposs_bot result["yposs_bot"] = yposs_bot result["top"] = np.poly1d(top) result["bottom"] = np.poly1d(bot) result["hpps"] = hpps result["ok"] = ok results.append(result) #5 if y == 1: break next = target + 2 if next > len(ssl): next = len(ssl) hpps_next = Wavelength.estimate_half_power_points( bs.scislit_to_csuslit(next)[0], header, bs) ok = np.where((xposs_top_next > hpps_next[0]) & (xposs_top_next < hpps_next[1])) ok2 = np.where((xposs_top_next_missing > hpps_next[0]) & (xposs_top_next_missing < hpps_next[1])) xposs_top_next = xposs_top_next[ok] xposs_top_next_missing = xposs_top_next_missing[ok2] yposs_top_next = yposs_top_next[ok] if len(xposs_top_next) == 0: topfun = np.poly1d(y) else: (topfun, topres, topsd, ok) = fit_edge_poly(xposs_top_next, xposs_top_next_missing, yposs_top_next, options["edge-order"]) xposs_top_this = xposs_top_next xposs_top_this_missing = xposs_top_next_missing yposs_top_this = yposs_top_next results.append({"version": options["version"]}) return results
def find_and_fit_edges(data, header, bs, options,edgeThreshold=450): ''' Given a flat field image, find_and_fit_edges determines the position of all slits. The function works by starting with a guess at the location for a slit edge in the spatial direction(options["first-slit-edge"]). Starting from the guess, find_edge_pair works out in either direction, measuring the position of the (e.g.) bottom of slit 1 and top of slit 2: ------ pixel y value = 2048 Slit 1 data ------ (bottom) deadband ------ (top) Slit N pixel data .... ------- (bottom) pixel = 0 --------------------------------> Spectral direction 1. At the top of the flat, the slit edge is defined to be a pixel value 2. The code guesses the position of the bottom of the slit, and runs find_edge_pair to measure slit edge locations. 3. A low-order polynomial is fit to the edge locations with fit_edge_poly 4. The top and bottom of the current slit, is stored into the result list. 5. The top of the next slit is stored temporarily for the next iteration of the for loop. 6. At the bottom of the flat, the slit edge is defined to be pixel 4. options: options["edge-order"] -- The order of the polynomial [pixels] edge. options["edge-fit-width"] -- The length [pixels] of the edge to fit over ''' # TODO: move hardcoded values into Options.py # y is the location to start y = 2034 DY = 44.25 toc = 0 ssl = bs.ssl slits = [] top = [0., np.float(Options.npix)] start_slit_num = int(bs.msl[0]['Slit_Number'])-1 if start_slit_num > 0: y -= DY * start_slit_num # Count and check that the # of objects in the SSL matches that of the MSL # This is purely a safety check numslits = np.zeros(len(ssl)) for i in xrange(len(ssl)): slit = ssl[i] M = np.where(slit["Target_Name"] == bs.msl["Target_in_Slit"]) numslits[i] = len(M[0]) numslits = np.array(numslits) if (np.sum(numslits) != CSU.numslits) and (not bs.long_slit) and (not bs.long2pos_slit) and (not bs.long2pos_slit_specphot): error ("The number of allocated CSU slits (%i) does not match " " the number of possible slits (%i)." % (np.sum(numslits), CSU.numslits)) raise Exception("The number of allocated CSU slits (%i) does not match " " the number of possible slits (%i)." % (np.sum(numslits), CSU.numslits)) # if the mask is a long slit, the default y value will be wrong. Set instead to be the middle if bs.long_slit: y = 1104 # now begin steps outline above results = [] result = {} result["Target_Name"] = ssl[0]["Target_Name"] # 1 result["top"] = np.poly1d([y]) ''' Nomenclature here is confusing: ----- Edge -- Top of current slit, bottom of prev slit . o ' Data ===== Data .;.;' Data ----- Edge -- Bottom of current slit, top of next slit ''' topfun = np.poly1d([y]) xposs_top_this = np.arange(10,2000,100) yposs_top_this = topfun(xposs_top_this) for target in xrange(len(ssl)): y -= DY * numslits[target] y = max(y, 1) info("%2.2i] Finding Slit Edges for %s ending at %4.0i. Slit " "composed of %i CSU slits" % ( target, ssl[target]["Target_Name"], y, numslits[target])) ''' First deal with the current slit ''' hpps = Wavelength.estimate_half_power_points( bs.scislit_to_csuslit(target+1)[0], header, bs) if y == 1: xposs_bot = [1024] xposs_bot_missing = [] yposs_bot = [4.25] botfun = np.poly1d(yposs_bot) ok = np.where((xposs_bot > hpps[0]) & (xposs_bot < hpps[1])) else: (xposs_top_next, xposs_top_next_missing, yposs_top_next, xposs_bot, xposs_bot_missing, yposs_bot, scatter_bot_this) = find_edge_pair( data, y, options["edge-fit-width"],edgeThreshold=edgeThreshold) ok = np.where((xposs_bot > hpps[0]) & (xposs_bot < hpps[1])) ok2 = np.where((xposs_bot_missing > hpps[0]) & (xposs_bot_missing < hpps[1])) xposs_bot = xposs_bot[ok] xposs_bot_missing = xposs_bot_missing[ok2] yposs_bot = yposs_bot[ok] if len(xposs_bot) == 0: botfun = np.poly1d(y-DY) else: (botfun, bot_res, botsd, botok) = fit_edge_poly(xposs_bot, xposs_bot_missing, yposs_bot, options["edge-order"]) bot = botfun.c.copy() top = topfun.c.copy() #4 result = {} result["Target_Name"] = ssl[target]["Target_Name"] result["xposs_top"] = xposs_top_this result["yposs_top"] = yposs_top_this result["xposs_bot"] = xposs_bot result["yposs_bot"] = yposs_bot result["top"] = np.poly1d(top) result["bottom"] = np.poly1d(bot) result["hpps"] = hpps result["ok"] = ok results.append(result) #5 if y == 1: break next = target + 2 if next > len(ssl): next = len(ssl) hpps_next = Wavelength.estimate_half_power_points( bs.scislit_to_csuslit(next)[0], header, bs) ok = np.where((xposs_top_next > hpps_next[0]) & (xposs_top_next < hpps_next[1])) ok2 = np.where((xposs_top_next_missing > hpps_next[0]) & (xposs_top_next_missing < hpps_next[1])) xposs_top_next = xposs_top_next[ok] xposs_top_next_missing = xposs_top_next_missing[ok2] yposs_top_next = yposs_top_next[ok] if len(xposs_top_next) == 0: topfun = np.poly1d(y) else: (topfun, topres, topsd, ok) = fit_edge_poly(xposs_top_next, xposs_top_next_missing, yposs_top_next, options["edge-order"]) xposs_top_this = xposs_top_next xposs_top_this_missing = xposs_top_next_missing yposs_top_this = yposs_top_next results.append({"version": options["version"]}) return results
def find_longslit_edges(data, header, bs, options, edgeThreshold=450, longslit=None): y = 2034 DY = 44.25 toc = 0 ssl = bs.ssl slits = [] top = [0., np.float(Options.npix)] start_slit_num = int(bs.msl[0]['Slit_Number']) - 1 if start_slit_num > 0: y -= DY * start_slit_num # if the mask is a long slit, the default y value will be wrong. Set instead to be the middle if bs.long_slit: try: y = longslit["yrange"][1] except: error( "Longslit reduction mode is specified, but the row position has not been specified. Defaulting to " + str(y)) print "Longslit reduction mode is specified, but the row position has not been specified. Defaulting to " + str( y) # Count and check that the # of objects in the SSL matches that of the MSL # This is purely a safety check numslits = np.zeros(len(ssl)) for i in xrange(len(ssl)): slit = ssl[i] M = np.where(slit["Target_Name"] == bs.msl["Target_in_Slit"]) numslits[i] = len(M[0]) numslits = np.array(numslits) info("Number of slits allocated for this longslit: " + str(np.sum(numslits))) # now begin steps outline above results = [] result = {} result["Target_Name"] = ssl[0]["Target_Name"] # 1 Defines a polynomial of degree 0, which is a constant, with the value of the top of the slit result["top"] = np.poly1d([longslit["yrange"][1]]) topfun = np.poly1d([longslit["yrange"][1] ]) # this is a constant funtion with c=top of the slit botfun = np.poly1d([ longslit["yrange"][0] ]) # this is a constant funtion with c=bottom of the slit # xposs_top_this = [10 110 210 .... 1810 1910] xposs_top = np.arange(10, 2000, 100) xposs_bot = np.arange(10, 2000, 100) # yposs_top_this = [1104 1104 ... 1104 1104], it's the constant polynomium calculated at the X positions yposs_top = topfun(xposs_top) yposs_bot = botfun(xposs_bot) ''' Deal with the current slit ''' target = 0 hpps = Wavelength.estimate_half_power_points( bs.scislit_to_csuslit(target + 1)[0], header, bs) ok = np.where((xposs_top > hpps[0]) & (xposs_top < hpps[1])) xposs_bot = xposs_bot[ok] yposs_bot = yposs_bot[ok] xposs_top = xposs_top[ok] yposs_top = yposs_top[ok] if len(xposs_bot) == 0: error("The slit edges specifications appear to be incorrect.") raise Exception( "The slit edges specifications appear to be incorrect.") # bot is the polynomium that defines the shape of the bottom of the slit. In this case, we set it to a constant. bot = botfun.c.copy() top = topfun.c.copy() #4 result = {} result["Target_Name"] = ssl[target]["Target_Name"] result["xposs_top"] = xposs_top result["yposs_top"] = yposs_top result["xposs_bot"] = xposs_bot result["yposs_bot"] = yposs_bot result["top"] = np.poly1d(top) result["bottom"] = np.poly1d(bot) result["hpps"] = hpps result["ok"] = ok results.append(result) results.append({"version": options["version"]}) return results
def find_longslit_edges(data, header, bs, options, edgeThreshold=450,longslit=None): y = 2034 DY = 44.25 toc = 0 ssl = bs.ssl slits = [] top = [0., np.float(Options.npix)] start_slit_num = int(bs.msl[0]['Slit_Number'])-1 if start_slit_num > 0: y -= DY * start_slit_num # if the mask is a long slit, the default y value will be wrong. Set instead to be the middle if bs.long_slit: try: y=longslit["yrange"][1] except: error("Longslit reduction mode is specified, but the row position has not been specified. Defaulting to "+str(y)) print "Longslit reduction mode is specified, but the row position has not been specified. Defaulting to "+str(y) # Count and check that the # of objects in the SSL matches that of the MSL # This is purely a safety check numslits = np.zeros(len(ssl)) for i in xrange(len(ssl)): slit = ssl[i] M = np.where(slit["Target_Name"] == bs.msl["Target_in_Slit"]) numslits[i] = len(M[0]) numslits = np.array(numslits) info("Number of slits allocated for this longslit: "+str(np.sum(numslits))) # now begin steps outline above results = [] result = {} result["Target_Name"] = ssl[0]["Target_Name"] # 1 Defines a polynomial of degree 0, which is a constant, with the value of the top of the slit result["top"] = np.poly1d([longslit["yrange"][1]]) topfun = np.poly1d([longslit["yrange"][1]]) # this is a constant funtion with c=top of the slit botfun = np.poly1d([longslit["yrange"][0]]) # this is a constant funtion with c=bottom of the slit # xposs_top_this = [10 110 210 .... 1810 1910] xposs_top = np.arange(10,2000,100) xposs_bot = np.arange(10,2000,100) # yposs_top_this = [1104 1104 ... 1104 1104], it's the constant polynomium calculated at the X positions yposs_top = topfun(xposs_top) yposs_bot = botfun(xposs_bot) ''' Deal with the current slit ''' target=0 hpps = Wavelength.estimate_half_power_points( bs.scislit_to_csuslit(target+1)[0], header, bs) ok = np.where((xposs_top > hpps[0]) & (xposs_top < hpps[1])) xposs_bot = xposs_bot[ok] yposs_bot = yposs_bot[ok] xposs_top = xposs_top[ok] yposs_top = yposs_top[ok] if len(xposs_bot) == 0: error ("The slit edges specifications appear to be incorrect.") raise Exception("The slit edges specifications appear to be incorrect.") # bot is the polynomium that defines the shape of the bottom of the slit. In this case, we set it to a constant. bot = botfun.c.copy() top = topfun.c.copy() #4 result = {} result["Target_Name"] = ssl[target]["Target_Name"] result["xposs_top"] = xposs_top result["yposs_top"] = yposs_top result["xposs_bot"] = xposs_bot result["yposs_bot"] = yposs_bot result["top"] = np.poly1d(top) result["bottom"] = np.poly1d(bot) result["hpps"] = hpps result["ok"] = ok results.append(result) results.append({"version": options["version"]}) return results