예제 #1
0
    def target_observable(self, Nights, constraints, delta_midnight=None):
        """
            Calculates for which times during the time span of Nights, the target is observable under the given constraints.
            LATER : Could include plotting of target observability.

            Parameters
            ----------
            Nights : class
                Nights at Paranal for which to compute if the target is observable.
            constraints : list
                list of Astroplan constraints to constrain the observability.
            delta_midnight : numpy.linspace, Obtional
                grid of timesteps within 24 hours for which the observation should be calculated.

        """
        if delta_midnight == None:
            # defines number of timesteps per 24 hours
            delta_midnight = np.linspace(-12, 12, 1000) * u.hour

        print(self.name + ' is getting processed')
        for date in Nights.date:
            """ Check if Nights object has attribute nights to calculate observability of target """
            if hasattr(Nights, 'night'):
                k = list.index(Nights.date, date)
                night = Nights.night[k]
            else:
                Nights.Calculate_nights_paranal(delta_midnight)
                night = Nights.night[k]

            """ Check if target observable """
            tar_obs = astroplan.is_event_observable(
                constraints=constraints, observer=paranal, target=self.Coordinates, times=night)
            if any(tar_obs[0] == True):
                print(
                    '{} Target is observable without any primary eclipse'.format(self.name))
                for n, tar in enumerate(tar_obs[0]):
                    if tar == True:
                        moon_target_sep, moon_phase, airmass, obs_altazs = fun.airmass_moon_sep_obj_altaz(
                            self, night[n])
                        self.target_observable.append({
                            'Name': self.name,
                            'Effective Temperature': self.star_Teff,
                            'J-magnitude': self.star_jmag,
                            'Object observable?': tar,
                            'Obs Data': {'time': night[n],
                                         'airmass': airmass,
                                         'moon sep': moon_target_sep[0],
                                         'moon phase': moon_phase,
                                         'az': obs_altazs.az,
                                         'alt': obs_altazs.alt
                                         }})
예제 #2
0
    def __init__(self, d, Max_Delta_days, LoadFromPickle=0):
        """
            Calculates the nights at paranal for a certain start date ''d'' and end date, reached after ''Max_Delta_days''.
            Retrieves the sun coordinates for each night from astroplan to determine the night times.
    
            Parameters
            ----------
            d : datetime.date
                Start date from which the nights at paranal are computed.
    
            Max_Delta_days : int
                Time span for which the nights at paranal are computed.
    
            LoadFromPickle : int
                If ''LoadFromPickle'' = 1, checks if Night data for given time span is available.
        """
        dt = datetime.timedelta(days=1)
        d_end = d + dt * Max_Delta_days
        self.Max_Delta_days = Max_Delta_days
        if LoadFromPickle == 1:
            """ Check if there exist pkl files with night data for the preferred range, if not: initializes empty lists for Nights instance """
            try:
                d_str = d.isoformat()  # start date from which the nights in paranal are calculated
                filename = 'Nights_paranal_{}_{}d.pkl'.format(
                    d_str, self.Max_Delta_days)
                nights = fun.pickled_items(filename)
                self.start = nights.__next__()
                self.end = nights.__next__()
                self.Max_Delta_days = nights.__next__()
                self.date = nights.__next__()
                self.night = nights.__next__()
                self.loaded = 1
            except Exception as e:
                print(e)
                self.loaded = 0
                d_str = d.isoformat()  # start date from which the nights in paranal are calculated
                filename = 'Nights_paranal_{}_{}d.pkl'.format(
                    d_str, self.Max_Delta_days)
                print('No Night data found for {}, computing nights...'.format(filename))

        self.start = d
        self.end = d_end
        self.Max_Delta_days = (d_end - d).days
        self.date = []
        # self.night = []
        self.loaded = 0

        for k in range(self.Max_Delta_days):
            date = self.start + dt * k  # list with datetime objects for the midnights in question
            self.date.append(date)
예제 #3
0
def load_Eclipses_from_file(filename, Max_Delta_days, path = None):
    """
        Loads Eclipses class objects from pickled file with ''filename''.

        Parameters
        ----------
        filename : str
            Name of file containing the pickled Eclipses class object data.

        Max_Delta_days : int
            Days for which the eclipses got computed, necessary to initialize Eclipses class.

        Returns
        -------
        Eclipses_List : list
            Contains all Eclipses class objects that have been loaded from the file.

    """
    Eclipses_List = []

    def att_identifier(att):
        if type(att) == int:
            Planet.num_eclipses = att
        elif type(att) == FixedTarget:
            Planet.Coordinates = att
        elif type(att) == astroplan.periodic.EclipsingSystem:
            Planet.Planets_eclipse = att
        else:
            return att
    
    if path == None: 
        planet = fun.pickled_items(filename)
    else:
        planet = fun.pickled_items(filename, path)
    att = None
    while True:
        Planet = Eclipses(Max_Delta_days)
        try:
            if att != None:
                print(att)
                Planet.name = att
            else:
                Planet.name = next(planet)

            Planet.epoch = next(planet)
            Planet.tranmid_err = next(planet)
            Planet.period = next(planet)
            Planet.period_err = next(planet)
            Planet.transit_duration = next(planet)
            Planet.eccentricity = next(planet)
            Planet.star_Teff = next(planet)
            Planet.star_jmag = next(planet)
            Planet.pl_radj = next(planet)
            att = None
            while att == None:
                att = next(planet)
                att = att_identifier(att)

            target_observable = att

            eclipse_observable = next(planet)

            att = None
            while att == None:
                att = next(planet)
                att = att_identifier(att)

            Planet.eclipse_observable.extend(eclipse_observable)
            Planet.target_observable.extend(target_observable)
            Eclipses_List.append(Planet)
        except StopIteration:
            print('Eclipses_List has been loaded from {}'.format(filename))
            logging.info(
                'Eclipses_List has bin loaded from {}'.format(filename))
            Planet.eclipse_observable.extend(eclipse_observable)
            Planet.target_observable.extend(target_observable)
            Eclipses_List.append(Planet)
            break

    return Eclipses_List
예제 #4
0
    def Observability(self, obs_time, Nights, constraints): #check_eclipse, check_target=0, delta_midnight=None
        """
            Calculates if the Transit and the target are observable for each date during the given timespan in ''Nights'' under
            the given ''constraints'' and writes it as dict objects into ''~self.eclipse_observable'' or ''~self.target_observable''.

            Parameters
            ----------
            obs_time : astropy.time.Time
                Contains the datetime as Time format after which the possible observations should be found.

            Nights : class Nights
                Containing night data of paranal, see Nights documentation.

            constraints : class astroplan.Constraint
                Constraints under which the observational events should get constrained.

            check_eclipse : int
                If ''check_eclipse'' =  1, checks if transits/eclipses are observable.

            check_target : int, optional
                If ''check_target'' = 1, checks if target is observable during the given nights. The default is 0.

            delta_midnight : numpy.linspace, obtional
                array containing a grid of timesteps for which the nights datetimes should get computed. Default is None

        """
        Planet_next_eclipse_Times = self.Planets_eclipse.next_primary_eclipse_time(
            obs_time, n_eclipses=self.num_eclipses)
        print(self.name + ' is getting processed')
        # n_max = np.ceil(1/self.period_err)
        # for date in Nights.date:

        #     if check_target == 1:
        #         """ Check if Nights object has attribute nights to calculate observability of target """
        #         if hasattr(Nights, 'night'):
        #             k = list.index(Nights.date, date)
        #             night = Nights.night[k]
        #         else:
        #             Nights.Calculate_nights_paranal(delta_midnight)
        #             night = Nights.night[0]
        Planet_Eclipes_NIGHTs_All = []
        for n, planet_next_eclipse_by_date in enumerate(Planet_next_eclipse_Times):
            """ Loop over all eclipses coming up in the given timespan of object planet """
            
            """ 
                Barycentric light travel time correction, since mid transit times are in barycentric frame. 
                Need to transform time to geocentric frame: 
            """
            planet_next_eclipse_by_date.location = paranal.location
            ltt_bary = planet_next_eclipse_by_date.light_travel_time(self.Coordinates.coord)
            planet_next_eclipse_by_date = planet_next_eclipse_by_date - ltt_bary # barycentric correction, 
            # the minus comes from that we transform from the barycentric into the geocentric frame.
            
            # Check which eclipse can be observed in which night
            # if date == planet_next_eclipse_by_date.datetime.date():

            # if check_eclipse == 1:

            Planet_next_eclipse_per_night_MID = planet_next_eclipse_by_date
            Planet_next_eclipse_per_night_BEGIN = Planet_next_eclipse_per_night_MID - \
                self.transit_duration / 2
            Planet_next_eclipse_per_night_END = Planet_next_eclipse_per_night_MID + \
                self.transit_duration / 2
            
            Planet_Eclipse_ERROR = (np.sqrt(self.tranmid_err.sec**2+(n+1)**2*self.period_err.to_value(u.second)**2)*u.second).to(u.hour)
            Planet_Eclipes_NIGHT = [Planet_next_eclipse_per_night_BEGIN, Planet_next_eclipse_per_night_MID,
                                    Planet_next_eclipse_per_night_END]  # Begin, midpoint and end of transit

            # Planet_Eclipes_NIGHTs_All = Planet_Eclipes_NIGHTs_All + Planet_Eclipes_NIGHT
            
            """ Computes observability of the Transit """
            ecl_obs = astroplan.is_event_observable(
                constraints=constraints, observer=paranal, target=self.Coordinates, times=Planet_Eclipes_NIGHT)
            
            # ecl_obs_test = astroplan.is_event_observable(
            #     constraints=constraints, observer=paranal, target=self.Coordinates, times=Planet_Eclipes_NIGHTs_All)
            
            # for k in range(int(len(ecl_obs_test[0])/3)):
            #     flag_not_obs = False
            #     for n in range(3):
            #         if ecl_obs_test[0][n+k] == False:
            #             flag_not_obs = True
            #     if not flag_not_obs:
            #         Planet_Eclipes_NIGHT_obs = [Planet_Eclipes_NIGHTs_All[0+k], Planet_Eclipes_NIGHTs_All[1+k], Planet_Eclipes_NIGHTs_All[2+k]]
                
            if all(ecl_obs[0] == True):
                print('{} total Eclipse is observable'.format(self.name))
                airmass_moon_sep_obj_altaz_RESULT = [
                    fun.airmass_moon_sep_obj_altaz(self, tim) for tim in Planet_Eclipes_NIGHT] #HERE Planet_Eclipes_NIGHT_obs
                moon_target_sep = [
                    out[0] for out in airmass_moon_sep_obj_altaz_RESULT]
                moon_phase = [out[1]
                              for out in airmass_moon_sep_obj_altaz_RESULT]
                airmass = [out[2]
                           for out in airmass_moon_sep_obj_altaz_RESULT]
                obs_altazs = [out[3]
                              for out in airmass_moon_sep_obj_altaz_RESULT]
                # print(moon_target_sep, moon_phase, airmass, obs_altazs)
                self.eclipse_observable.append({
                    'Name': self.name,
                    'Radius R_J': self.pl_radj,
                    'Transit Midpoint Time': Planet_next_eclipse_per_night_MID, #Planet_Eclipes_NIGHT_obs[1],
                    'Transit Midpoint Time uncertainty [h]': Planet_Eclipse_ERROR,
                    'Primary eclipse observable?': ecl_obs[0][0],
                    'Transit Duration [h]': self.transit_duration.to(u.hour),
                    'Effective Temperature K': self.star_Teff,
                    'J-magnitude': self.star_jmag,
                    'Eclipse Begin': {'time': Planet_next_eclipse_per_night_BEGIN, #Planet_Eclipes_NIGHT_obs[0] ,
                                      'airmass': airmass[0],
                                      'moon sep': moon_target_sep[0][0],
                                      'moon phase': moon_phase[0],
                                      'az': obs_altazs[0].az,
                                      'alt': obs_altazs[0].alt
                                      },
                    'Eclipse Mid': {'time': Planet_next_eclipse_per_night_MID, #Planet_Eclipes_NIGHT_obs[1] ,
                                    'airmass': airmass[1],
                                    'moon sep': moon_target_sep[1][0],
                                    'moon phase': moon_phase[1],
                                    'az': obs_altazs[1].az,
                                    'alt': obs_altazs[1].alt
                                    },
                    'Eclipse End': {'time': Planet_next_eclipse_per_night_END, #Planet_Eclipes_NIGHT_obs[2],
                                    'airmass': airmass[2],
                                    'moon sep': moon_target_sep[2][0],
                                    'moon phase': moon_phase[2],
                                    'az': obs_altazs[2].az,
                                    'alt': obs_altazs[2].alt
                                    }})
예제 #5
0
    def Calculate_nights_paranal(self, delta_midnight, observatory=paranal, WriteToPickle=0):
        """
            Calculates the nights at ''observatory'', default=paranal for a certain start date and end date. Retrieves the sun coordinates
            for each night from astroplan.

            Parameters
            ----------
            delta_midnight : numpy.linspace
                array containing a grid of timesteps for which the nights datetimes should get computed.

            observatory : astroplan.Observer (optional)
                contains EarthLocation and timezone info about the observer at, default is paranal.

            WriteToPickle : int
                Object Nights gets written into a pickle file.

            Returns
            -------
            self.dates : list
                Contains datetime.date objects for each night between d and d_end.

            self.coords : list
                Contains dict with sun coordinates for each time in Nights.night.

            self.night : list
                Contains lists with nighttimes for each night. The number timesteps for each nights is defined in
                delta_midnight.

        """

        if self.loaded == 1:
            """ If the nights at paranal with startdate d could be loaded from file, yield: """
            print(
                'Nights loaded from file, continueing with processing planets for observability')
        else:

            """ All times are in UTC respectively """
            print('Calculating the nights of paranal from the {} until the {}'.format(
                self.start, self.end))
            self.night = []
            midnight = datetime.time(0, 0, 0)
            for date in self.date:

                # list with datetime objects for the midnights in question
                midnight_datetime = datetime.datetime.combine(date, midnight)
                # Time object for each midnight gets created in UTC, midnight in UTC.
                midnight_at_site_UTC = observatory.datetime_to_astropy_time(
                    midnight_datetime)

                Night_paranal = midnight_at_site_UTC + delta_midnight  # in UTC
                # compute frame AltAz for get_sun
                frame_24_h_paranal = AltAz(
                    obstime=Night_paranal, location=observatory.location)
                sunaltazs_24_h = get_sun(
                    Night_paranal).transform_to(frame_24_h_paranal)

                night = []
                for n, _ in enumerate(delta_midnight):
                    """ Calculates the night times for each night """
                    if sunaltazs_24_h[n].alt < -18 * u.deg:
                        night.append(str(sunaltazs_24_h[n].obstime.value))
                self.night.append(Time(night))
                

            if WriteToPickle == 1:
                """Write Nights_paranal_table to file"""

                d = self.start
                d = d.isoformat()  # start date from which the nights in paranal are calculated
                filename = 'Nights_paranal_{}_{}d.pkl'.format(
                    d, self.Max_Delta_days)
                fun.pickle_dumper_objects(filename, self)
        during the transit. The Number of exposures possible is added to the list eclipse_observable and eclipse_mid_observable
        for comparison. Each exposure is optimised to have NDIT between 16 and 32 with a minimum S/N = 100. The resulting S/N ratios
        of each exposure are used to compute the overall median. More values like DIT, NDIT, SN of each exposure for each transit
        could be stored as well, but this has not been implemented yet. If one gets stuck in this loop due to internet connection or
        unexpected errors, one may rerun the code from here, instead of rerunning everything again.
        """

        for planet in Eclipses_List:
            if planet.name == 'WASP-163 b':  #Work around for planets which are missing data but did not get filtered. Get the name of the planet that was last called and enter it here. Can contain several names.
                Eclipses_List.remove(planet)

        for planet in Eclipses_List:
            for eclipse in planet.eclipse_observable:
                try:

                    minimum_SN_tot = fun.req_SN(planet.pl_radj,
                                                planet.star_Teff)
                    if minimum_SN_tot >= 450:
                        minimum_SN = 100
                    else:
                        minimum_SN = np.sqrt(minimum_SN_tot**2 / 20)

                    fun.SN_estimate_num_of_exp(eclipse, planet, snr=minimum_SN)
                except Warning as w:
                    print(w)
                    print(
                        'Something went wrong in:{}:{}, taking next observation...'
                        .format(planet.name, eclipse['Transit Midpoint Time']))
                    logging.exception(w)
                    logging.error(
                        'Something went wrong in:{}:{}, taking next observation...'
                        .format(planet.name, eclipse['Transit Midpoint Time']))
Eclipses_List_new = []
for filename in filenames_pickles:
    Eclipses_List = load_Eclipses_from_file(
        filename,
        Max_Delta_days,
        path=
        '/Users/jonaszbinden/Desktop/Target Selection Paper/Results/P108_metric_2D/original_files/'
    )
    time.sleep(3)
    for name in name_list:
        for planet in Eclipses_List:
            if planet.name == name:
                print(planet.name, 'here')
                Eclipses_List_new.append(planet)
Eclipses_List_new.pop(-2)
delta_midnight = np.linspace(-12, 12, 1000) * u.hour
Nights_paranal = Nights(d, Max_Delta_days, LoadFromPickle=0)
Nights_paranal.Calculate_nights_paranal(delta_midnight)
beg_end_night = []
for night in Nights_paranal.night:
    beg_end_night.append({'beg': night[0], 'end': night[-1]})

ranking, df_gen, df_frame, _ = fun.data_sorting_and_storing(Eclipses_List_new,
                                                            write_to_csv=1)
ranked_events, Obs_events = fun.postprocessing_events(d, Max_Delta_days,
                                                      Nights,
                                                      Eclipses_List_new)
fun.xlsx_writer(filename, df_gen, df_frame, Obs_events)
ranking = fun.plotting_transit_data(d, Max_Delta_days, ranking,
                                    Eclipses_List_new, Nights, ranked_events)