Пример #1
0
class TracefitScreen(IRScreen):
    paths = DictProperty([])
    itexture = ObjectProperty(Texture.create(size = (2048, 2048)))
    iregion = ObjectProperty(None)
    current_impair = ObjectProperty(None)
    extractregion = ObjectProperty(None)
    tplot = ObjectProperty(MeshLinePlot(color=[1,1,1,1])) #change to SmoothLinePlot when kivy 1.8.1
    current_target = ObjectProperty(None)
    pairstrings = ListProperty([])
    apertures = DictProperty({'pos':[], 'neg':[]})
    drange = ListProperty([0,1024])
    tracepoints = ListProperty([])
    trace_axis = NumericProperty(0)
    fit_params = DictProperty({})
    trace_lines = ListProperty([MeshLinePlot(color=[0,0,1,1]),MeshLinePlot(color=[0,1,1,1])])
    current_flats = ObjectProperty(None)
    theapp = ObjectProperty(None)
    
    def on_enter(self):
        self.pairstrings = ['{0} - {1}'.format(*[path.basename(x.fitsfile) for x in y]) \
            for y in self.theapp.extract_pairs]
            
    def set_imagepair(self, val):
        if not self.theapp.current_target:
            popup = WarningDialog(text='You need to select a target (on the Observing Screen) before proceeding!')
            popup.open()
            return
        self.pair_index = self.pairstrings.index(val)
        fitsfile = self.paths['out']+re.sub(' ','',re.sub('.fits','',val))+'.fits'
        if not path.isfile(fitsfile):
            popup = WarningDialog(text='You have to select an extraction'\
                'region for this image pair \nbefore you can move on to this step.')
            popup.open()
            return
        self.current_impair = FitsImage(fitsfile)
        self.region = self.current_impair.get_header_keyword(*('EXREG' + x for x in ['X1','Y1','X2','Y2']))
        if not any(self.region):
            popup = WarningDialog(text='You have to select an extraction'\
                'region for this image pair \nbefore you can move on to this step.')
            popup.open()
            return
        self.current_impair.load()
        idata = ''.join(map(chr,self.current_impair.scaled))
        self.itexture.blit_buffer(idata, colorfmt='luminance', bufferfmt='ubyte', \
            size = self.current_impair.dimensions)
        self.trace_axis = 0 if get_tracedir(self.current_target.instrument_id) == 'vertical' else 1
        #tmp = self.current_impair.data_array[self.region[1]:self.region[3]+1,self.region[0]:self.region[2]+1]
        #self.extractregion = med_normal(tmp)
        tmp = self.theapp.extract_pairs[self.pair_index]
        if self.trace_axis:
            #self.trace_axis = 1
            reg = [self.region[x] for x in [1, 0, 3, 2]]
            self.extractregion = make_region(tmp[0], tmp[1], reg, self.current_flats)#.transpose()
        else:
            self.extractregion = make_region(tmp[0], tmp[1], self.region, self.current_flats).transpose()
        reg = self.region[:]
        reg[2] = reg[2] - reg[0]
        reg[3] = reg[3] - reg[1]
        self.iregion = self.itexture.get_region(*reg)
        dims = [[0,0],list(self.extractregion.shape)]
        dims[0][self.trace_axis] = 0.4 * self.extractregion.shape[self.trace_axis]
        dims[1][self.trace_axis] = 0.6 * self.extractregion.shape[self.trace_axis]
        self.tracepoints = robm(self.extractregion[dims[0][0]:dims[1][0]+1,\
            dims[0][1]:dims[1][1]+1], axis = self.trace_axis)
        self.tplot.points = interp_nan(list(enumerate(self.tracepoints)))
        pxs, self.tracepoints = zip(*self.tplot.points)
        self.drange = minmax(self.tracepoints)
        self.ids.the_graph.add_plot(self.tplot)
    
    def add_postrace(self):
        peaks = find_peaks(self.tracepoints, len(self.apertures['pos'])+1, \
            tracedir = self.trace_axis)
        #new_peak = float(peaks[-1])
        new_peak = float(peaks)
        peakheight = interp_x(self.tplot.points, new_peak)
        plot = MeshLinePlot(color=[0,1,0,1], points=[(new_peak, 0), (new_peak, peakheight)])
        self.ids.the_graph.add_plot(plot)
        newspin = ApertureSlider(aperture_line = plot, tfscreen = self)
        newspin.slider.range = [0, len(self.tracepoints)-1]
        newspin.slider.step = 0.1
        newspin.slider.value = new_peak
        newspin.trash.bind(on_press = lambda x: self.remtrace('pos',newspin))
        self.ids.postrace.add_widget(newspin)
        self.apertures['pos'].append(newspin)
        
    def add_negtrace(self):
        peaks = find_peaks(self.tracepoints, len(self.apertures['neg'])+1, \
            tracedir = self.trace_axis, pn='neg')
        #new_peak = float(peaks[-1])
        new_peak = float(peaks)
        peakheight = interp_x(self.tplot.points, new_peak)
        plot = MeshLinePlot(color=[1,0,0,1], points=[(new_peak, 0), (new_peak, peakheight)])
        self.ids.the_graph.add_plot(plot)
        newspin = ApertureSlider(aperture_line = plot, tfscreen = self)
        newspin.slider.range = [0, len(self.tracepoints)-1]
        newspin.slider.step = 0.1
        newspin.slider.value = new_peak
        newspin.trash.bind(on_press = lambda x: self.remtrace('neg',newspin))
        self.ids.negtrace.add_widget(newspin)
        self.apertures['neg'].append(newspin)
    
    def remtrace(self, which, widg):
        self.ids.the_graph.remove_plot(widg.aperture_line)
        self.apertures[which].remove(widg)
        if which == 'pos':
            self.ids.postrace.remove_widget(widg)
        else:
            self.ids.negtrace.remove_widget(widg)
        
    def set_psf(self):
        popup = SetFitParams()
        popup.bind(on_dismiss = lambda x: self.setfp(popup.fit_args))
        popup.open()
    
    def setfp(self, args):
        self.fit_params = args
        
    def fit_trace(self):
        if not self.fit_params or self.fit_params['shape'] not in ('Gaussian','Lorentzian'):
            popup = WarningDialog(text='Make sure you set up your fit parameters!')
            popup.open()
            return
        pos = {'pos':[x.slider.value for x in self.apertures['pos']], \
            'neg':[x.slider.value for x in self.apertures['neg']]}
        for x in self.trace_lines:
            if x in self.ids.the_graph.plots:
                self.ids.the_graph.remove_plot(x)
        if self.fit_params.get('man',False):
            popup = DefineTrace(npos=len(self.apertures['pos']), \
                nneg=len(self.apertures['neg']), imtexture = self.iregion)
            popup.bind(on_dismiss = self.manual_trace(popup.tracepoints))
            popup.open()
            return
        self.xx, self.fit_params['pmodel'], self.fit_params['nmodel'] = \
            fit_multipeak(self.tracepoints, pos = pos, wid = self.fit_params['wid'], \
            ptype = self.fit_params['shape'])
        self.trace_lines[0].points = zip(self.xx, self.fit_params['pmodel'](self.xx))
        self.trace_lines[1].points = zip(self.xx, self.fit_params['nmodel'](self.xx))
        self.ids.the_graph.add_plot(self.trace_lines[0])
        self.ids.the_graph.add_plot(self.trace_lines[1])
        
    def fix_distort(self):
        if not (self.fit_params.get('pmodel',False) or \
            self.fit_params.get('nmodel',False)):
            popup = WarningDialog(text='Make sure you fit the trace centers first!')
            popup.open()
            return
        pdistort, ndistort = draw_trace(self.extractregion, self.xx, self.fit_params['pmodel'], \
            self.fit_params['nmodel'], fixdistort = True, fitdegree = self.fit_params['deg'])
        
        im1, im2 = [x for x in copy.deepcopy(self.theapp.extract_pairs[self.pair_index])]
        im1.load(); im2.load()
        #if self.current_flats:
        #    im1 = im_divide(im1, self.current_flats)
        #    im2 = im_divide(im2, self.current_flats)
        im1.data_array = undistort_imagearray(im1.data_array, pdistort)
        im2.data_array = undistort_imagearray(im2.data_array, ndistort)
        im_subtract(im1, im2, outputfile=self.current_impair.fitsfile)
        tmp = self.current_impair
        self.current_impair = FitsImage(self.current_impair.fitsfile)
        self.current_impair.header['EXREGX1'] = (tmp.get_header_keyword('EXREGX1'), 'extraction region coordinate X1')
        self.current_impair.header['EXREGY1'] = (tmp.get_header_keyword('EXREGY1'), 'extraction region coordinate Y1')
        self.current_impair.header['EXREGX2'] = (tmp.get_header_keyword('EXREGX2'), 'extraction region coordinate X2')
        self.current_impair.header['EXREGY2'] = (tmp.get_header_keyword('EXREGY2'), 'extraction region coordinate Y2')
        self.current_impair.update_fits(header_only = True)
        self.set_imagepair(self.pairstrings[self.pair_index])
        self.fit_params['nmodel'] = None
        self.fit_params['pmodel'] = None
        
    
    def manual_trace(self, traces):
        pass #need to figure out how to apply these
    
    def extract_spectrum(self):
        if not (self.fit_params.get('pmodel',False) or \
            self.fit_params.get('nmodel',False)):
            popup = WarningDialog(text='Make sure you fit the trace centers first!')
            popup.open()
            return
        
        #need a calibration, too
        self.lamp = None
        if theapp.current_night.cals:
            self.lamp = theapp.current_night.cals.data_array if not self.current_flats \
                else im_divide(theapp.current_night.cals, self.current_flats).data_array
            self.lamp = self.lamp[self.region[1]:self.region[3]+1,self.region[0]:self.region[2]+1]
        im1, im2 = [x for x in copy.deepcopy(the_app.extract_pairs[self.pair_index])]
        im1.load(); im2.load()
        #if self.current_flats:
        #    im1 = im_divide(im1, self.current_flats)
        #    im2 = im_divide(im2, self.current_flats)
        im1.data_array = undistort_imagearray(im1.data_array, pdistort)
        im2.data_array = undistort_imagearray(im2.data_array, ndistort)
        self.tell = make_region(im1, im2, self.region, flat=self.current_flats, telluric=True)
        #tmp, self.tell = im_minimum(im1.data_array, im2.data_array)
        #self.tell = self.tell[self.region[1]:self.region[3]+1,self.region[0]:self.region[2]+1]
        self.pextract = extract(self.fit_params['pmodel'], self.extractregion, self.tell, 'pos', lamp = self.lamp)
        self.nextract = extract(self.fit_params['nmodel'], self.extractregion, self.tell, 'neg', lamp = self.lamp)
        
        #write uncalibrated spectra to fits files (will update after calibration)
        pstub = self.paths['out'] + re.sub('.fits','-ap%i',im1.fitsfile)
        ext = ('.fits','-sky.fits','-lamp.fits')
        h = im1.header
        for i, p_ap in enumerate(self.pextract):
            for j in range(p_ap.shape[1]):
                spec = p_ap[:,j]
                write_fits((pstub + ext[i]) % j, h, spec)
        
        nstub = self.paths['out'] + re.sub('.fits','-ap%i',im2.fitsfile)
        h = im2.header
        for i, n_ap in enumerate(self.nextract):
            for j in range(n_ap.shape[1]):
                spec = n_ap[:,j]
                write_fits((nstub + ext[i]) % j, h, spec)
Пример #2
0
class ExtractRegionScreen(IRScreen):
    paths = DictProperty({})
    extract_pairs = ListProperty([])
    pairstrings = ListProperty([])
    imwid = NumericProperty(1024)
    imht = NumericProperty(1024)
    bx1 = NumericProperty(0)
    bx2 = NumericProperty(1024)
    by1 = NumericProperty(0)
    by2 = NumericProperty(1024)
    imcanvas = ObjectProperty(None)
    current_impair = ObjectProperty(None)
    current_flats = ObjectProperty(None)
    theapp = ObjectProperty(None)
    
    def __init__(self):
        super(ExtractRegionScreen, self).__init__()
        self.ids.ipane.load_data(default_image)
        with self.imcanvas.canvas.after:
            c = Color(30./255., 227./255., 224./255.)
            self.regionline = Line(points=self.lcoords, close=True, \
                dash_length = 2, dash_offset = 1)
    
    def on_enter(self):
        flat = path.join(self.paths['cal'],'Flat.fits')
        if self.theapp.current_night.flaton and self.theapp.current_night.flaton[0]:
            fon = FitsImage(path.join(self.paths['cal'], \
                self.theapp.current_night.flaton[0]), load=True)
            if self.theapp.current_night.flatoff and self.theapp.current_night.flatoff[0]:
                foff = FitsImage(path.join(self.paths['cal'], \
                    self.theapp.current_night.flatoff[0]), load=True)
                im_subtract(fon, foff, outputfile = flat)
            else:
                write_fits(flat, fon.header, fon.data_array)
            self.current_flats = FitsImage(flat, load = True)
        self.pairstrings = ['{0} - {1}'.format(*[path.basename(x.fitsfile) for x in y]) for y in self.extract_pairs]
    
    def on_pre_leave(self):
        self.theapp.current_impair = self.current_impair
        self.theapp.current_flats = self.current_flats
    
    def set_imagepair(self, val):
        if not self.theapp.current_target:
            popup = WarningDialog(text='You need to select a target (on the Observing Screen) before proceeding!')
            popup.open()
            return
        pair_index = self.pairstrings.index(val)
        fitsfile = self.paths['out']+re.sub(' ','',re.sub('.fits','',val))+'.fits'
        if not path.isfile(fitsfile):
            im1, im2 = [x for x in copy.deepcopy(self.extract_pairs[pair_index])]
            im1.load(); im2.load()
            #if self.current_flats:
            #    tmp = im_divide(im1, self.current_flats)
            #    im1.header, im1.data_array = tmp
            #    tmp = im_divide(im2, self.current_flats)
            #    im2.header, im2.data_array = tmp
            im_subtract(im1, im2, outputfile=path.join(self.paths['out'],fitsfile))
        self.current_impair = FitsImage(path.join(self.paths['out'],fitsfile), load=True)
        self.ids.ipane.load_data(self.current_impair)
        self.imwid, self.imht = self.current_impair.dimensions
        if self.current_impair.get_header_keyword('EXREGX1'):
            for x in ['x1', 'y1', 'x2', 'y2']:
                tmp = self.current_impair.get_header_keyword('EXREG'+x.upper())
                if tmp[0] is not None:
                    self.set_coord(x, tmp[0])
    
    def get_coords(self):
        xscale = float(self.imcanvas.width) / float(self.imwid)
        yscale = float(self.imcanvas.height) / float(self.imht)
        x1 = float(self.bx1) * xscale
        y1 = float(self.by1) * yscale
        x2 = float(self.bx2) * xscale
        y2 = float(self.by2) * yscale
        return [x1, y1, x1, y2, x2, y2, x2, y1] 
    
    lcoords = AliasProperty(get_coords, None, bind=('bx1', 'bx2', 'by1', 'by2', 'imwid', 'imht'))
    
    def set_coord(self, coord, value):
        if coord == 'x1':
            self.bx1 = value
        elif coord == 'x2':
            self.bx2 = value
        elif coord == 'y1':
            self.by1 = value
        elif coord == 'y2':
            self.by2 = value
        self.regionline.points = self.lcoords
    
    def save_region(self):
        self.current_impair.header['EXREGX1'] = (self.bx1, 'extraction region coordinate X1')
        self.current_impair.header['EXREGY1'] = (self.by1, 'extraction region coordinate Y1')
        self.current_impair.header['EXREGX2'] = (self.bx2, 'extraction region coordinate X2')
        self.current_impair.header['EXREGY2'] = (self.by2, 'extraction region coordinate Y2')
        self.current_impair.update_fits()