def update_targets(self, targs):
     targs["images"] = parse_filestring(
         targs["filestring"], os.path.join(self.current_obsnight.rawpath, self.current_obsnight.filestub)
     )
     targs["dither"] = targs["images"].dithers
     self.current_target = ObsTarget(**targs)
     tmp = self.current_obsnight.targets
     tmp[self.current_target.targid] = self.current_target
     self.current_obsnight = self.current_obsnight._replace(targets=tmp)
     self.target_list = self.current_obsnight.targets.keys()
     self.ids.targs.text = self.current_target.targid
     self.set_filelist()
     self.rdb[self.current_obsnight.date] = {self.current_obsnight.date: self.current_obsnight}
class ObservingScreen(IRScreen):
    obsids = DictProperty({})
    obsrun_list = ListProperty([])
    obsrun_buttons = ListProperty([])
    current_obsrun = ObjectProperty(ObsRun())
    obsnight_list = ListProperty([])
    obsnight_buttons = ListProperty([])
    current_obsnight = ObjectProperty(ObsNight())
    instrument_list = ListProperty([])
    caltype = StringProperty("")
    target_list = ListProperty([])
    current_target = ObjectProperty(ObsTarget())
    file_list = ListProperty([])

    def __init__(self, **kwargs):
        super(ObservingScreen, self).__init__(**kwargs)
        self.waiting = WaitingDialog(text="Please wait while the calibration images build, thank you!")

    def on_enter(self):
        self.instrument_list = instrumentdb.keys()
        self.obsids = {x: obsrundb[x] for x in obsrundb}
        self.obsrun_list = obsrundb.keys()
        self.obsrun_buttons = [Button(text=x, size_hint_y=None, height=30) for x in self.obsrun_list]

    def on_pre_leave(self):
        pairs = self.current_target.ditherpairs
        self.theapp.extract_pairs = [[self.current_target.images[x] for x in y] for y in pairs]
        self.theapp.current_target = self.current_target
        self.theapp.current_paths = {
            "cal": self.current_obsnight.calpath,
            "raw": self.current_obsnight.rawpath,
            "out": self.current_obsnight.outpath,
        }
        self.theapp.current_night = self.current_obsnight

    def set_obsrun(self):
        run_id = self.ids.obsrun.text
        if run_id not in self.obsids:
            self.rdb = AdHocDB()
            self.obsids[run_id] = self.rdb.fname
            obsrundb[run_id] = {run_id: self.rdb.fname}
        else:
            self.rdb = AdHocDB(self.obsids[run_id][run_id])
        self.current_obsrun = ObsRun(runid=run_id)
        tmp = {str(self.rdb[r][r].date): self.rdb[r][r] for r in self.rdb}
        self.current_obsrun = self.current_obsrun._replace(nights=tmp)
        self.obsnight_list = self.current_obsrun.nights.keys()
        self.obsnight_buttons = [Button(text=x, size_hint_y=None, height=30) for x in self.obsnight_list]

    def set_obsnight(self):
        night_id = self.ids.obsnight.text
        if night_id == "" or self.current_obsrun.runid == "" or night_id == "Observation Date":
            return
        if night_id not in self.obsnight_list:
            self.obsnight_list.append(night_id)
            self.obsnight_buttons.append(Button(text=night_id, size_hint_y=None, height=30))
            self.current_obsnight = ObsNight(date=night_id)
            self.current_obsrun.add_to(self.current_obsnight)
        else:
            self.current_obsnight = self.current_obsrun.get_from(night_id)
            self.ids.rawpath.text = self.current_obsnight.rawpath
            self.ids.outpath.text = self.current_obsnight.outpath
            self.ids.calpath.text = self.current_obsnight.calpath
            self.ids.fformat.text = self.current_obsnight.filestub
            self.set_filelist()
        for night in self.obsnight_list:
            self.rdb[night] = {night: self.current_obsrun.get_from(night)}
        self.target_list = self.current_obsnight.targets.keys()

    def pick_rawpath(self):
        popup = DirChooser()
        popup.bind(on_dismiss=lambda x: self.setpath("raw", popup.chosen_directory))
        popup.open()

    def setpath(self, which, dir):
        if which == "raw":
            self.current_obsnight = self.current_obsnight._replace(rawpath=dir)
            self.ids.rawpath.text = dir
        elif which == "out":
            self.current_obsnight = self.current_obsnight._replace(outpath=dir)
            self.ids.outpath.text = dir
        elif which == "cal":
            self.current_obsnight = self.current_obsnight._replace(calpath=dir)
            self.ids.calpath.text = dir

    def pick_outpath(self):
        popup = DirChooser()
        popup.bind(on_dismiss=lambda x: self.setpath("out", popup.chosen_directory))
        popup.open()

    def pick_calpath(self):
        popup = DirChooser()
        popup.bind(on_dismiss=lambda x: self.setpath("cal", popup.chosen_directory))
        popup.open()

    def check_filestub(self, stub):
        placeholder = "#"
        reg = placeholder + "+"
        if len(re.findall(reg, stub)) != 1:
            popup = AlertDialog(text="File format is not valid; must use '#' as placeholder only")
            popup.open()
            return
        self.current_obsnight = self.current_obsnight._replace(filestub=stub)

    def set_caltype(self, caltype):
        if caltype == "Flats (lamps ON)":
            cout, flist = self.current_obsnight.flaton if self.current_obsnight.flaton else ("Not yet created", "")
        elif caltype == "Flats (lamps OFF)":
            cout, flist = self.current_obsnight.flatoff if self.current_obsnight.flatoff else ("Not yet created", "")
        elif caltype == "Arc Lamps":
            cout, flist = self.current_obsnight.cals if self.current_obsnight.cals else ("Not yet created", "")
        self.ids.calfiles.text = flist
        self.ids.calout.text = cout

    def set_calfile(self, flist):
        caltype = self.ids.caltypes.text
        if caltype == "Flats (lamps ON)":
            flatfile = os.path.join(self.current_obsnight.calpath, self.current_obsnight.date + "-FlatON.fits")
            tmp = self.current_obsnight.flaton
            if tmp:
                tmp[1] = flist
            else:
                tmp = ["", flist]
            try:
                if FitsImage(flatfile).header["FILES"] == flist:
                    tmp[0] = flatfile
                    self.ids.calout.txt = flatfile
            except:
                pass
            self.current_obsnight = self.current_obsnight._replace(flaton=tmp)
        elif caltype == "Flats (lamps OFF)":
            flatfile = os.path.join(self.current_obsnight.calpath, self.current_obsnight.date + "-FlatOFF.fits")
            tmp = self.current_obsnight.flatoff
            if tmp:
                tmp[1] = flist
            else:
                tmp = ["", flist]
            try:
                if FitsImage(flatfile).header["FILES"] == flist:
                    tmp[0] = flatfile
            except:
                pass
            self.current_obsnight = self.current_obsnight._replace(flatoff=tmp)
        elif caltype == "Arc Lamps":
            flatfile = os.path.join(self.current_obsnight.calpath, self.current_obsnight.date + "-Wavecal.fits")
            tmp = self.current_obsnight.cals
            if tmp:
                tmp[1] = flist
            else:
                tmp = ["", flist]
            try:
                if FitsImage(flatfile).header["FILES"] == flist:
                    tmp[0] = flatfile
            except:
                pass
            self.current_obsnight = self.current_obsnight._replace(cals=tmp)

    def make_cals(self):
        if not self.current_obsnight.rawpath:
            return
        caltype = self.ids.caltypes.text
        flist = self.ids.calfiles.text
        self.waiting.open()
        if caltype == "Flats (lamps ON)":
            t = Thread(
                target=self.imstack_wrapper,
                args=(self.current_obsnight.flaton, flist, self.current_obsnight.date + "-FlatON.fits"),
            )
            t.start()
        elif caltype == "Flats (lamps OFF)":
            t = Thread(
                target=self.imstack_wrapper,
                args=(self.current_obsnight.flatoff, flist, self.current_obsnight.date + "-FlatOFF.fits"),
            )
            t.start()
        elif caltype == "Arc Lamps":
            t = Thread(
                target=self.imstack_wrapper,
                args=(self.current_obsnight.cals, flist, self.current_obsnight.date + "-Wavecal.fits"),
            )
            t.start()

    def imstack_wrapper(self, target, flist, outp):
        raw = self.current_obsnight.rawpath
        cal = self.current_obsnight.calpath
        stub = self.current_obsnight.filestub
        imstack = parse_filestring(flist, os.path.join(raw, stub))
        imstack.medcombine(output=os.path.join(cal, outp))
        target[:] = [outp, flist]
        self.ids.calfiles.text = flist
        self.ids.calout.text = outp
        self.waiting.dismiss()

    def save_night(self):
        tmp = self.current_obsrun.nights
        tmp[self.current_obsnight.date] = self.current_obsnight
        self.current_obsrun = self.current_obsrun._replace(nights=tmp)
        for night in self.obsnight_list:
            self.rdb[night] = {night: self.current_obsrun.get_from(night)}
        self.rdb.store_sync()

    def set_target(self):
        target_id = self.ids.targs.text
        self.current_target = self.current_obsnight.targets[target_id]
        self.set_filelist()

    def add_target(self):
        popup = AddTarget(instrumentlist=self.instrument_list)
        popup.open()
        popup.bind(on_dismiss=lambda x: self.update_targets(popup.target_args) if popup.target_args else None)

    def update_targets(self, targs):
        targs["images"] = parse_filestring(
            targs["filestring"], os.path.join(self.current_obsnight.rawpath, self.current_obsnight.filestub)
        )
        targs["dither"] = targs["images"].dithers
        self.current_target = ObsTarget(**targs)
        tmp = self.current_obsnight.targets
        tmp[self.current_target.targid] = self.current_target
        self.current_obsnight = self.current_obsnight._replace(targets=tmp)
        self.target_list = self.current_obsnight.targets.keys()
        self.ids.targs.text = self.current_target.targid
        self.set_filelist()
        self.rdb[self.current_obsnight.date] = {self.current_obsnight.date: self.current_obsnight}

    def set_filelist(self):
        self.ids.obsfiles.clear_widgets()
        self.file_list = []
        for f, dither in zip(self.current_target.images, self.current_target.dither):
            tmp = ObsfileInsert(obsfile=f, dithertype=dither)
            self.file_list.append(tmp)
            self.ids.obsfiles.add_widget(tmp)

    def save_target(self):
        self.current_target = self.current_target._replace(
            dither=[x.dithertype for x in self.file_list], notes=self.ids.tnotes.text
        )
        # just make sure everything is propagating correctly
        self.current_obsnight.targets[self.current_target.targid] = self.current_target
        self.current_obsrun.nights[self.current_obsnight.date] = self.current_obsnight
        for night in self.obsnight_list:
            self.rdb[night] = self.current_obsrun.get_from(night)
        self.target_list = self.current_obsnight.targets.keys()