Ejemplo n.º 1
0
def test_julian2num():
    mdates._reset_epoch_test_example()
    mdates.set_epoch('0000-12-31')
    # 2440587.5 is julian date for 1970-01-01T00:00:00
    # https://en.wikipedia.org/wiki/Julian_day
    assert mdates.julian2num(2440588.5) == 719164.0
    assert mdates.num2julian(719165.0) == 2440589.5
    # set back to the default
    mdates._reset_epoch_test_example()
    mdates.set_epoch('1970-01-01T00:00:00')
    assert mdates.julian2num(2440588.5) == 1.0
    assert mdates.num2julian(2.0) == 2440589.5
def testrow(row, currenttime, mindeg, toolate, tooearly, TimePre, TimePost):
    testime = float(row[6])
    now2 = dates.date2num(currenttime)
    testtime = dates.julian2num(testime)
    tester1 = False
    if now2 >= testtime:
        res = False
    else:
        if row[4] < mindeg:
            res = False
        elif row[12] < mindeg:
            res = False
        else:
            ht = int(toolate[0:2])
            mt = int(toolate[3:5])
            time = jd2gd(float(row[14]))[1]
            if time[-2:] == "AM":
                h = int(time[0:2])
                m = int(time[3:5]) + TimePost  # the additional 20 is for post transit observations
                if m > 60:
                    m = m - 60
                    h = h + 1
                if h == ht:
                    if m <= mt:
                        tester1 = True
                    else:
                        res = False
                elif h < ht:
                    tester1 = True
                else:
                    res = False
                if tester1 == True:
                    tester1 = False
                    ht = int(tooearly[0:2])
                    mt = int(tooearly[3:5])
                    time = jd2gd(float(row[6]))[1]
                    if time[-2:] == "AM":
                        h = int(time[0:2])
                        m = int(time[3:5]) - TimePre  # the additional 20 is for post transit observations
                        if m < 0:
                            m = m + 60
                            h = h - 1
                        if h == ht:
                            if m >= mt:
                                tester1 = True
                            else:
                                res = False
                        elif h > ht:
                            tester1 = True
                        else:
                            res = False
                        if tester1 == True:
                            res = True
                    else:
                        res = False
            else:
                res = False
    return res
Ejemplo n.º 3
0
def doy2date(year, doy):
    """
    Convert day of year to date if year is known
    """
    date_0 = datetime
    jul_0 = dates.num2julian(dates.date2num(date_0.date(year, 1, 1)))
    date = dates.num2date(dates.julian2num(jul_0 + doy -
                                           1))  #jul2date(jul_0+doy-1)

    return date
Ejemplo n.º 4
0
def na_back_tree(
        data_root=RAW_DATA_ROOT,
        start=None,
        stop=None,
        calibration=None,
        photometry=None,
        show=False,
        ccddata_cls=FwRedCorData,  # less verbose
        **kwargs):
    dirs_dates = get_dirs_dates(data_root, start=start, stop=stop)
    dirs, _ = zip(*dirs_dates)
    if len(dirs) == 0:
        log.warning('No directories found')
        return
    if calibration is None:
        calibration = Calibration(reduce=True)
    if photometry is None:
        photometry = Photometry(precalc=True, **kwargs)

    to_plot_list = []
    na_back_list = []
    for d in dirs:
        nb = na_back_directory(d,
                               calibration=calibration,
                               photometry=photometry,
                               ccddata_cls=ccddata_cls,
                               **kwargs)
        if nb == {}:
            continue
        na_back_list.extend(nb['na_back_list'])
        del nb['na_back_list']
        to_plot_list.append(nb)

    # --> write to_plot_list
    df = pd.DataFrame(to_plot_list)
    plot_dates = julian2num(df['jd'])
    f = plt.figure()  #figsize=[8.5, 11])
    plt.suptitle(
        f"Na background {df['date'].iloc[0]} -- {df['date'].iloc[-1]}")
    plt.plot_date(plot_dates, df['biweight_back'], 'k.')
    plt.plot_date(plot_dates, df['biweight_back'] + df['mad_std_back'], 'kv')
    plt.plot_date(plot_dates, df['biweight_back'] - df['mad_std_back'], 'k^')
    #plt.errorbar(plot_dates, df['biweight_back'])
    plt.ylim([0, 0.07])
    plt.ylabel('electron/s/pix^2')
    plt.gcf().autofmt_xdate()  # orient date labels at a slant
    if show:
        plt.show()
    return to_plot_list
Ejemplo n.º 5
0
def jd2gd(juldat):
    """ Convert a numerial Julian date into a Gregorian date using Pylab.
        Timezone returned will be UTC.

       :EXAMPLES:
         ::

          print jd2gd(2454324.5)  #--> 2007-08-12 00:00:00
          print jd2gd(2451545)    #--> 2000-01-01 12:00:00

       :SEE ALSO: :func:`gd2jd`"""
    # 2008-08-26 14:03 IJC: Created    
    # 2011-01-22 16:24 IJC: Removed arbitrary (?) subtraction of 3442850 from 'd'
    import matplotlib.dates as dates
    d = dates.julian2num(juldat)
    gd = dates.num2date(d )

    return gd
Ejemplo n.º 6
0
def jd2gd(juldat):
    """ Convert a numerial Julian date into a Gregorian date using Pylab.
        Timezone returned will be UTC.

       :EXAMPLES:
         ::

          print jd2gd(2454324.5)  #--> 2007-08-12 00:00:00
          print jd2gd(2451545)    #--> 2000-01-01 12:00:00

       :SEE ALSO: :func:`gd2jd`"""
    # 2008-08-26 14:03 IJC: Created
    # 2011-01-22 16:24 IJC: Removed arbitrary (?) subtraction of 3442850 from 'd'
    import matplotlib.dates as dates
    d = dates.julian2num(juldat)
    gd = dates.num2date(d)

    return gd
def jd2gd(juldat):
    """ Convert a numerial Julian date into a Gregorian date using Pylab.
        Timezone returned will be UTC.

       EXAMPLES:
          print jd2gd(2454324.5)  --> 2007-08-12 00:00:00
          print jd2gd(2451545)    --> 2000-01-01 12:00:00

       SEE ALSO: gd2jd"""
    # 2008-08-26 14:03 IJC: Created
    strtest = str(juldat)[0] + str(juldat)[1]
    if not strtest == "24":
        juldattsrt = "24" + str(juldat)
        juldat = float(juldattsrt)

    d = dates.julian2num(juldat)
    # gd = dates.num2date(d - 3442850)
    gd = dates.num2date(d)
    Date = str(gd.month) + "/" + str(gd.day) + "/" + str(gd.year)[2:]
    hour = gd.hour
    if hour > 12:
        hrn = hour - 12
        hr = str(hrn)
        AMPM = "PM"
        if hrn < 10:
            hr = "0" + hr
    else:
        hr = str(hour)
        AMPM = "AM"
    if hour < 10:
        hr = "0" + hr
    if gd.minute < 10:
        mnH = gd.minute
        mn = "0" + str(mnH)
    else:
        mn = str(gd.minute)
    if gd.second < 10:
        scH = gd.second
        sc = "0" + str(scH)
    else:
        sc = str(gd.second)
    Time = hr + ":" + mn + ":" + sc + " " + AMPM

    return Date, Time
Ejemplo n.º 8
0
def checkVisPA(ra, dec, targetName=None, ephFileName=None, fig=None):
    """Check the visibility at a range of position angles.

    Parameters
    ----------
    ra: str
        The RA of the target in hh:mm:ss.s or dd:mm:ss.s or representing a float
    dec: str
        The Dec of the target in hh:mm:ss.s or dd:mm:ss.s or representing a float
    targetName: str
        The target name
    ephFileName: str
        The filename of the ephemeris file
    fig: bokeh.plotting.figure
        The figure to plot to

    Returns
    -------
    paGood : float
        The good position angle.
    paBad : float
        The bad position angle.
    gd : matplotlib.dates object
       The greogrian date.
    fig : bokeh.plotting.figure object
        The plotted figure.

    """
    if ephFileName is None:
        eph_file = 'data/contam_visibility/JWST_ephem_short.txt'
        ephFileName = pkg_resources.resource_filename('exoctk', eph_file)
    if ra.find(':') > -1:  # format is hh:mm:ss.s or  dd:mm:ss.s
        ra = convert_ddmmss_to_float(ra) * 15. * D2R
        dec = convert_ddmmss_to_float(dec) * D2R
    else:  # format is decimal
        ra = float(ra) * D2R
        dec = float(dec) * D2R

    # load ephemeris
    eclFlag = False
    eph = EPH.Ephemeris(ephFileName, eclFlag)

    # convert dates from MJD to Gregorian calendar dates
    mjd = np.array(eph.datelist)
    d = mdates.julian2num(mjd + 2400000.5)
    gd = mdates.num2date(d)

    # loop through dates and determine VIS and PAs (nominal, min, max)
    vis = np.empty(mjd.size, dtype=bool)
    paNom = np.empty(mjd.size)
    paMin = np.empty(mjd.size)
    paMax = np.empty(mjd.size)
    for i in range(mjd.size):

        # is it visible?
        vis[i] = eph.in_FOR(mjd[i], ra, dec)

        # nominal PA at this date
        pa = eph.normal_pa(mjd[i], ra, dec)

        # search for minimum PA allowed by roll
        pa0 = pa
        while eph.is_valid(mjd[i], ra, dec, pa0 - 0.002):
            pa0 -= 0.002

        # search for maximum PA allowed by roll
        pa1 = pa
        while eph.is_valid(mjd[i], ra, dec, pa1 + 0.002):
            pa1 += 0.002

        paNom[i] = (pa * R2D) % 360
        paMin[i] = (pa0 * R2D) % 360
        paMax[i] = (pa1 * R2D) % 360

    # does PA go through 360 deg?
    wrap = np.any(np.abs(np.diff(paNom[np.where(vis)[0]])) > 350)

    # Determine good and bad PA ranges
    # Good PAs
    i, = np.where(vis)
    pa = np.concatenate((paNom[i], paMin[i], paMax[i]))

    if wrap:
        pa = np.append(pa, (0., 360.))
    pa.sort()

    i1, = np.where(np.diff(pa) > 10)
    i0 = np.insert(i1 + 1, 0, 0)
    i1 = np.append(i1, -1)
    paGood = np.dstack((pa[i0], pa[i1])).round(1).reshape(-1, 2).tolist()

    # bad PAs (complement of the good PAs)
    paBad = []
    if paGood[0][0] > 0:
        paBad.append([0., paGood[0][0]])
    for i in range(1, len(paGood)):
        paBad.append([paGood[i - 1][1], paGood[i][0]])
    if paGood[-1][1] < 360.:
        paBad.append([paGood[-1][1], 360.])

    # Make a figure
    if fig is None or fig:
        tools = 'crosshair, reset, hover, save'
        radec = ', '.join([str(ra), str(dec)])
        fig = figure(tools=tools,
                     plot_width=800,
                     plot_height=400,
                     x_axis_type='datetime',
                     title=targetName or radec)

    # Do all figure calculations
    iBad, = np.where(vis == False)
    paMasked = np.copy(paNom)
    paMasked[iBad] = np.nan
    gdMasked = np.copy(gd)

    i = np.argmax(paNom)
    if paNom[i + 1] < 10:
        i += 1
    paMasked = np.insert(paMasked, i, np.nan)
    gdMasked = np.insert(gdMasked, i, gdMasked[i])

    i = np.argmax(paMin)
    goUp = paMin[i - 2] < paMin[i - 1]  # PA going up at wrap point?

    # Top part
    i0_top = 0 if goUp else i
    i1_top = i if goUp else paMin.size - 1
    paMaxTmp = np.copy(paMax)
    paMaxTmp[np.where(paMin > paMax)[0]] = 360

    # Bottom part
    i = np.argmin(paMax)
    i0_bot = i if goUp else 0
    i1_bot = paMin.size - 1 if goUp else i
    paMinTmp = np.copy(paMin)
    paMinTmp[np.where(paMin > paMax)[0]] = 0

    # Convert datetime to a number for Bokeh
    gdMaskednum = [
        datetime.date(2019, 6, 1) + datetime.timedelta(days=n)
        for n, d in enumerate(gdMasked)
    ]
    color = 'green'

    # Draw the curve and error
    try:
        fig.line(gdMaskednum,
                 paMasked,
                 legend_label='cutoff',
                 line_color=color)
    except AttributeError:
        fig.line(gdMaskednum, paMasked, legend='cutoff', line_color=color)

    # Top
    terr_y = np.concatenate(
        [paMin[i0_top:i1_top + 1], paMaxTmp[i0_top:i1_top + 1][::-1]])
    terr_x = np.concatenate(
        [gdMaskednum[i0_top:i1_top + 1], gdMaskednum[i0_top:i1_top + 1][::-1]])
    fig.patch(terr_x, terr_y, color=color, fill_alpha=0.2, line_alpha=0)

    # Bottom
    berr_y = np.concatenate(
        [paMinTmp[i0_bot:i1_bot + 1], paMax[i0_bot:i1_bot + 1][::-1]])
    berr_x = np.concatenate(
        [gdMaskednum[i0_bot:i1_bot + 1], gdMaskednum[i0_bot:i1_bot + 1][::-1]])
    fig.patch(berr_x, berr_y, color='red', fill_alpha=0.2, line_alpha=0)
    from bokeh.plotting import show
    show(fig)

    # Plot formatting
    fig.xaxis.axis_label = 'Date'
    fig.yaxis.axis_label = 'Aperture Position Angle (degrees)'

    return paGood, paBad, gd, fig
Ejemplo n.º 9
0
def na_back_directory(directory,
                      calibration=True,
                      read_pout=True,
                      write_pout=True,
                      write_plot=True,
                      create_outdir=True,
                      show=False,
                      **kwargs):
    rd = reduced_dir(directory, create=False)
    poutname = os.path.join(rd, 'Na_back.pout')
    pout = cached_pout(na_back_pipeline,
                       poutname=poutname,
                       read_pout=read_pout,
                       write_pout=write_pout,
                       create_outdir=create_outdir,
                       directory=directory,
                       **kwargs)
    if len(pout) == 0:
        log.debug(f'no Na background measurements found in {directory}')
        return {}
    _, pipe_meta = zip(*pout)
    na_back_list = [pm['Na_back'] for pm in pipe_meta]
    df = pd.DataFrame(na_back_list)
    df.sort_values('jd')
    just_date = df['date'].iloc[0]

    instr_mag = u.Magnitude(df['best_back'] * u.electron / u.s / u.pix**2)
    df['instr_mag'] = instr_mag

    #tdf = df.loc[df['airmass'] < 2.0]
    tdf = df.loc[df['airmass'] < 2.5]
    mean_back = np.mean(tdf['best_back'])
    std_back = np.std(tdf['best_back'])
    biweight_back = biweight_location(tdf['best_back'])
    mad_std_back = mad_std(tdf['best_back'])

    # https://stackoverflow.com/questions/20664980/pandas-iterate-over-unique-values-of-a-column-that-is-already-in-sorted-order
    # and
    # https://pandas.pydata.org/pandas-docs/stable/user_guide/groupby.html

    #https://matplotlib.org/stable/tutorials/intermediate/color_cycle.html
    offset_cycler = cycler(color=['r', 'g', 'b', 'y'])
    plt.rc('axes', prop_cycle=offset_cycler)

    f = plt.figure(figsize=[8.5, 11])
    plt.suptitle(f"Na background {just_date}")
    offset_groups = df.groupby(['raoff', 'decoff']).groups
    ax = plt.subplot(3, 1, 1)
    for offset_idx in offset_groups:
        gidx = offset_groups[offset_idx]
        gdf = df.iloc[gidx]
        plot_dates = julian2num(gdf['jd'])
        plt.plot_date(plot_dates,
                      gdf['best_back'],
                      label=f"dRA {gdf.iloc[0]['raoff']} "
                      f"dDEC {gdf.iloc[0]['decoff']} armin")
        plt.axhline(y=biweight_back, color='red')
        plt.axhline(y=biweight_back + mad_std_back,
                    linestyle='--',
                    color='k',
                    linewidth=1)
        plt.axhline(y=biweight_back - mad_std_back,
                    linestyle='--',
                    color='k',
                    linewidth=1)
        plt.text(0.5,
                 biweight_back + 0.1 * mad_std_back,
                 f'{biweight_back:.4f} +/- {mad_std_back:.4f}',
                 ha='center',
                 transform=ax.get_yaxis_transform())
        plt.xlabel('date')
        plt.ylabel('electron/s')
    ax.legend()

    ax = plt.subplot(3, 1, 2)
    for offset_idx in offset_groups:
        gidx = offset_groups[offset_idx]
        gdf = df.iloc[gidx]
        plt.plot(gdf['airmass'], gdf['instr_mag'], '.')
        #plt.axhline(y=biweight_back, color='red')
        #plt.axhline(y=biweight_back+mad_std_back,
        #            linestyle='--', color='k', linewidth=1)
        #plt.axhline(y=biweight_back-mad_std_back,
        #            linestyle='--', color='k', linewidth=1)
        plt.xlabel('Airmass')
        plt.ylabel('mag (electron/s/pix^2')

    ax = plt.subplot(3, 1, 3)
    for offset_idx in offset_groups:
        gidx = offset_groups[offset_idx]
        gdf = df.iloc[gidx]
        plt.plot(gdf['alt'], gdf['best_back'], '.')
        plt.axhline(y=biweight_back, color='red')
        plt.axhline(y=biweight_back + mad_std_back,
                    linestyle='--',
                    color='k',
                    linewidth=1)
        plt.axhline(y=biweight_back - mad_std_back,
                    linestyle='--',
                    color='k',
                    linewidth=1)
        plt.xlabel('Alt')
        plt.ylabel('electron/s')

    f.subplots_adjust(hspace=0.3)
    if write_plot is True:
        write_plot = os.path.join(rd, 'Na_back.png')
    if isinstance(write_plot, str):
        plt.savefig(write_plot, transparent=True)
    if show:
        plt.show()
    plt.close()

    # Problem discussed in  https://mail.python.org/pipermail/tkinter-discuss/2019-December/004153.html
    gc.collect()

    return {
        'date': just_date,
        'jd': np.floor(df['jd'].iloc[0]),
        'biweight_back': biweight_back,
        'mad_std_back': mad_std_back,
        'na_back_list': na_back_list
    }
Ejemplo n.º 10
0
def jul2date(jul_date):
    date1 = dates.num2date(dates.julian2num(jul_date))
    return '%d.%d.%d'%(date1.year, date1.month, date1.day)
Ejemplo n.º 11
0
def doy2date(year, doy):
    date_0 = datetime
    jul_0 = dates.num2julian( dates.date2num(date_0.date(year,1,1)) )
    date = dates.num2date(dates.julian2num(jul_0+doy-1)) #jul2date(jul_0+doy-1)
    return date
Ejemplo n.º 12
0
def jul2date2(jul_date):
    date1 = dates.num2date(dates.julian2num(jul_date))
    return date1
Ejemplo n.º 13
0
def checkVisPA(ra, dec, targetName=None, ephFileName=None, fig=None):
    """Check the visibility at a range of position angles

    Parameters
    ----------
    ra: float
        The RA of the target
    dec: float
        The Dec of the target
    targetName: str
        The target name
    ephFileName: str
        The filename of the ephemeris file
    fig: matplotlib.pyplot.figure, bokeh.plotting.figure
        The figure to plot to

    Returns
    -------
    paGood : float
        The good position angle.
    paBad : float
        The bad position angle.
    gd : matplotlib.dates object
       The greogrian date.
    fig : matplotlib.pyplot object
        The plotted figure.

    """
    if ephFileName is None:
        eph_file = 'data/contam_visibility/JWST_ephem_short.txt'
        ephFileName = pkg_resources.resource_filename('exoctk', eph_file)
    if ra.find(':') > -1:  # format is hh:mm:ss.s or  dd:mm:ss.s
        ra = convert_ddmmss_to_float(ra) * 15. * D2R
        dec = convert_ddmmss_to_float(dec) * D2R
    else:  # format is decimal
        ra = float(ra) * D2R
        dec = float(dec) * D2R

    # load ephemeris
    eclFlag = False
    eph = EPH.Ephemeris(ephFileName, eclFlag)

    # convert dates from MJD to Gregorian calendar dates
    mjd = np.array(eph.datelist)
    d = mdates.julian2num(mjd + 2400000.5)
    gd = mdates.num2date(d)

    # loop through dates and determine VIS and PAs (nominal, min, max)
    vis = np.empty(mjd.size, dtype=bool)
    paNom = np.empty(mjd.size)
    paMin = np.empty(mjd.size)
    paMax = np.empty(mjd.size)
    for i in range(mjd.size):

        # is it visible?
        vis[i] = eph.in_FOR(mjd[i], ra, dec)

        # nominal PA at this date
        pa = eph.normal_pa(mjd[i], ra, dec)

        # search for minimum PA allowed by roll
        pa0 = pa
        while eph.is_valid(mjd[i], ra, dec, pa0 - 0.002):
            pa0 -= 0.002

        # search for maximum PA allowed by roll
        pa1 = pa
        while eph.is_valid(mjd[i], ra, dec, pa1 + 0.002):
            pa1 += 0.002

        paNom[i] = (pa * R2D) % 360
        paMin[i] = (pa0 * R2D) % 360
        paMax[i] = (pa1 * R2D) % 360

    # does PA go through 360 deg?
    wrap = np.any(np.abs(np.diff(paNom[np.where(vis)[0]])) > 350)

    # Determine good and bad PA ranges
    # Good PAs
    i, = np.where(vis)
    pa = np.concatenate((paNom[i], paMin[i], paMax[i]))

    if wrap:
        pa = np.append(pa, (0., 360.))
    pa.sort()

    i1, = np.where(np.diff(pa) > 10)
    i0 = np.insert(i1 + 1, 0, 0)
    i1 = np.append(i1, -1)
    paGood = np.dstack((pa[i0], pa[i1])).round(1).reshape(-1, 2).tolist()

    # bad PAs (complement of the good PAs)
    paBad = []
    if paGood[0][0] > 0:
        paBad.append([0., paGood[0][0]])
    for i in range(1, len(paGood)):
        paBad.append([paGood[i - 1][1], paGood[i][0]])
    if paGood[-1][1] < 360.:
        paBad.append([paGood[-1][1], 360.])

    # Make a figure
    if fig is None or fig == True:
        fig = plt.gcf()

    # Do all figure calculations
    iBad, = np.where(vis == False)
    paMasked = np.copy(paNom)
    paMasked[iBad] = np.nan
    gdMasked = np.copy(gd)

    i = np.argmax(paNom)
    if paNom[i + 1] < 10:
        i += 1
    paMasked = np.insert(paMasked, i, np.nan)
    gdMasked = np.insert(gdMasked, i, gdMasked[i])

    i = np.argmax(paMin)
    goUp = paMin[i - 2] < paMin[i - 1]  # PA going up at wrap point?

    # Top part
    i0_top = 0 if goUp else i
    i1_top = i if goUp else paMin.size - 1
    paMaxTmp = np.copy(paMax)
    paMaxTmp[np.where(paMin > paMax)[0]] = 360

    # Bottom part
    i = np.argmin(paMax)
    i0_bot = i if goUp else 0
    i1_bot = paMin.size - 1 if goUp else i
    paMinTmp = np.copy(paMin)
    paMinTmp[np.where(paMin > paMax)[0]] = 0

    # Add fits to matplotlib
    if isinstance(fig, matplotlib.figure.Figure):

        # Make axes
        ax = plt.axes()
        plt.title(targetName)

        # plot nominal PA
        plt.plot(gdMasked, paMasked, color='k')

        # plot ranges allowed through roll
        if wrap:
            i = np.argmax(paMin)
            goUp = paMin[i - 2] < paMin[i - 1]  # PA going up at wrap point?

            # top part
            plt.fill_between(gd[i0_top:i1_top + 1],
                             paMin[i0_top:i1_top + 1],
                             paMaxTmp[i0_top:i1_top + 1],
                             where=vis[i0_top:i1_top + 1],
                             lw=0,
                             facecolor='k',
                             alpha=0.5)

            # bottom part
            plt.fill_between(gd[i0_bot:i1_bot + 1],
                             paMinTmp[i0_bot:i1_bot + 1],
                             paMax[i0_bot:i1_bot + 1],
                             where=vis[i0_bot:i1_bot + 1],
                             lw=0,
                             facecolor='k',
                             alpha=0.5)

        else:
            plt.fill_between(gd,
                             paMin,
                             paMax,
                             where=vis,
                             lw=0,
                             facecolor='k',
                             alpha=0.5)

        plt.ylabel('Position Angle (degrees)')
        plt.xlim(min(gd), max(gd))
        ax.xaxis.set_major_locator(mdates.MonthLocator())
        ax.xaxis.set_major_formatter(mdates.DateFormatter("%b '%y"))
        ax.xaxis.set_minor_locator(mdates.DayLocator(list(range(1, 32, 5))))
        plt.ylim(0, 360)
        ax.yaxis.set_major_locator(MultipleLocator(25))
        ax.yaxis.set_minor_locator(MultipleLocator(5))
        plt.grid()
        for label in ax.get_xticklabels():
            label.set_rotation(45)

    # Or to bokeh!
    else:

        # Convert datetime to a number for Bokeh
        gdMaskednum = [
            datetime.date(2019, 6, 1) + datetime.timedelta(days=n)
            for n, d in enumerate(gdMasked)
        ]
        color = 'green'

        # Draw the curve and error
        fig.line(gdMaskednum, paMasked, legend='cutoff', line_color=color)

        # Top
        err_y = np.concatenate(
            [paMin[i0_top:i1_top + 1], paMaxTmp[i0_top:i1_top + 1][::-1]])
        err_x = np.concatenate([
            gdMaskednum[i0_top:i1_top + 1],
            gdMaskednum[i0_top:i1_top + 1][::-1]
        ])
        fig.patch(err_x, err_y, color=color, fill_alpha=0.2, line_alpha=0)

        # Bottom
        err_y = np.concatenate(
            [paMinTmp[i0_bot:i1_bot + 1], paMax[i0_bot:i1_bot + 1][::-1]])
        err_x = np.concatenate([
            gdMaskednum[i0_bot:i1_bot + 1],
            gdMaskednum[i0_bot:i1_bot + 1][::-1]
        ])
        fig.patch(err_x, err_y, color=color, fill_alpha=0.2, line_alpha=0)

        # Plot formatting
        fig.xaxis.axis_label = 'Date'
        fig.yaxis.axis_label = 'Position Angle (degrees)'

    return paGood, paBad, gd, fig
Ejemplo n.º 14
0
def conj_time_save_to_file(filename, sys_conj_time, r_mode, dps_mode, conjunction_crit, \
    global_s_time, global_e_time, date_format='jd', pickle_file = False, to_append = False):
    """ 	
	-filename:  		string		(doesn't include format)
	-sys_conj_time: 	dictionary
	-r_mode: 		string
	-dps_mode:		string
	-global_s_time: 	float
	-global_e_time: 	float
	-verbose:		bool
	
	# always write to txt file
	"""
    fns = []
    if pickle_file:
        if to_append:
            pkfile = open(filename + '.pickle', 'a+b')
        else:
            pkfile = open(filename + '.pickle', 'w')
        fns.append(filename + '.pickle')
        pickle.dump(sys_conj_time, pkfile)
        pkfile.close()
    if to_append:
        datafile = open(filename + '.txt', 'a+b')
    else:
        datafile = open(filename + '.txt', 'w')
    fns.append(filename + '.txt')
    if date_format == 'jd':
        global_s_time_str = str(global_s_time)
        global_e_time_str = str(global_e_time)
    else:
        global_s_time_str = str(dates.num2date(
            dates.julian2num(global_s_time)))
        global_e_time_str = str(dates.num2date(
            dates.julian2num(global_e_time)))
    datafile.write('Search for planet conjuction from time ' +
                   global_s_time_str + ' to ' + global_e_time_str + ': \n')
    datafile.write('*********************************\n')
    datafile.write('Planet radius : ' + r_mode + '\n')
    datafile.write(
        'Distance from the planet to (earth-star) line of sight : ' +
        dps_mode + '\n')
    datafile.write('*********************************\n')
    datafile.write('Criterion for conjunction (distance <= ?): ' +
                   conjunction_crit + '\n')
    datafile.write('*********************************\n')
    for sys_n in sorted(sys_conj_time.keys()):
        # datafile.write('System '+str(sys_n)+' (number of planets: '+ \
        #		str(sys_conj_time[sys_n]['n_planets'])+'): \n')
        sys_str = 'System '+str(sys_n)+' (number of planets: '+ \
           str(sys_conj_time[sys_n]['n_planets'])+'): \n'
        sys_str_print = 0
        for n_members in sorted(sys_conj_time[sys_n].keys()):
            if n_members == 'n_planets':
                continue
            # datafile.write('\t----------------\n')
            # datafile.write('\tSearching alignment of '+str(n_members)+' planets: \n')
            search_str = '\t----------------\n\tSearching alignment of ' + str(
                n_members) + ' planets: \n'
            search_str_print = 0
            for participants in sorted(sys_conj_time[sys_n][n_members].keys()):
                n_conjs = sys_conj_time[sys_n][n_members][participants][
                    'n_conjs']
                if n_conjs <= 0:
                    continue
                else:
                    if sys_str_print == 0:
                        datafile.write(sys_str)
                        sys_str_print = 1
                    if search_str_print == 0:
                        datafile.write(search_str)
                        search_str_print = 1
                datafile.write('\t\t----------------\n')
                datafile.write('\t\tParticipants: ' + str(participants) +
                               ': \n')
                start_times = sys_conj_time[sys_n][n_members][participants][
                    'start_points']
                end_times = sys_conj_time[sys_n][n_members][participants][
                    'end_points']
                mid_times = sys_conj_time[sys_n][n_members][participants][
                    'mid_points']
                s_ang_sep = sys_conj_time[sys_n][n_members][participants][
                    's_ang_sep']
                e_ang_sep = sys_conj_time[sys_n][n_members][participants][
                    'e_ang_sep']
                conj_crit = sys_conj_time[sys_n][n_members][participants][
                    'conj_crit']
                conjunction_period = sys_conj_time[sys_n][n_members][
                    participants]['conjunction_period']
                non_conjunction_period = sys_conj_time[sys_n][n_members][
                    participants]['non_conjunction_period']
                p_pers = sys_conj_time[sys_n][n_members][participants][
                    'participants_periods']
                p_radii = sys_conj_time[sys_n][n_members][participants][
                    'participants_radii']
                p_teqs = sys_conj_time[sys_n][n_members][participants][
                    'participants_teqs']
                s_angs = sys_conj_time[sys_n][n_members][participants][
                    's_angs']
                e_angs = sys_conj_time[sys_n][n_members][participants][
                    'e_angs']
                incomplete_flag = sys_conj_time[sys_n][n_members][
                    participants]['incomplete_flag']
                notes = sys_conj_time[sys_n][n_members][participants]['notes']

                datafile.write('\t\tConjunctions start at: \n')
                if date_format == 'jd':
                    datafile.write('\t\t\t' +
                                   str([x + 2454900
                                        for x in start_times]) + '\n')
                else:
                    for x in start_times:
                        datafile.write('\t\t\t')
                        datafile.write(
                            str(dates.num2date(dates.julian2num(x +
                                                                2454900))) +
                            '\n')
                datafile.write('\t\tConjunctions end at: \n')
                if date_format == 'jd':
                    datafile.write('\t\t\t' +
                                   str([x + 2454900
                                        for x in end_times]) + '\n')
                else:
                    for x in end_times:
                        if x < 0:
                            x_str = '0'
                        else:
                            x_str = str(
                                dates.num2date(dates.julian2num(x + 2454900)))
                        datafile.write('\t\t\t' + x_str + '\n')
                datafile.write('\t\t>>> Mid time: \n')
                if date_format == 'jd':
                    datafile.write('\t\t\t' +
                                   str([x + 2454900
                                        for x in mid_times]) + '\n')
                else:
                    for x in mid_times:
                        datafile.write('\t\t\t')
                        datafile.write(
                            str(dates.num2date(dates.julian2num(x +
                                                                2454900))) +
                            '\n')
                datafile.write(
                    '\t\t  Conjunction Criterion (unit: Solar Radius): \n')
                datafile.write('\t\t\t' + str(conj_crit) + '\n')
                datafile.write('\t\t  Number of Conjunctions: \n')
                datafile.write('\t\t\t' + str(n_conjs) + '\n')
                datafile.write(
                    '\t\t  Maximum separation among planets when conjunction starts (unit: Solar Radius): \n'
                )
                datafile.write('\t\t\t' + str(s_ang_sep) + '\n')
                datafile.write(
                    '\t\t  Maximum separation among planets when conjunction ended (unit: Solar Radius): \n'
                )
                datafile.write('\t\t\t' + str(e_ang_sep) + '\n')
                datafile.write('\t\t  Conjunction durations (hours): \n')
                datafile.write('\t\t\t' +
                               str([p * 24.0
                                    for p in conjunction_period]) + '\n')
                datafile.write(
                    '\t\t  Time period between conjunctions (hours): \n')
                datafile.write('\t\t\t' +
                               str([p * 24.0
                                    for p in non_conjunction_period]) + '\n')
                datafile.write('\t\t  Period of participants (days): \n')
                datafile.write('\t\t\t' + str(p_pers) + '\n')
                datafile.write(
                    '\t\t  Radii of participants (unit: Solar Radius):\n')
                datafile.write('\t\t\t' + str(p_radii) + '\n')
                datafile.write(
                    '\t\t  Equilibrium temperature of participants (unit: Solar Radius):\n'
                )
                datafile.write('\t\t\t' + str(p_teqs) + '\n')
                datafile.write(
                    '\t\t  Position (angular) of participants at start time(unit: radian): \n'
                )
                datafile.write('\t\t\t' + str(s_angs) + '\n')
                datafile.write(
                    '\t\t  Position (angular) of participants at end time(unit: radian): \n'
                )
                datafile.write('\t\t\t' + str(e_angs) + '\n')
                if incomplete_flag:
                    datafile.write(
                        '\t\tNote: there are incomplete conjunctions recorded!\n'
                    )
                for note_item in notes:
                    datafile.write('\t\t\t' + note_item + '\n')
                datafile.write('\t\t----------------\n')
            if search_str_print:
                datafile.write('\t----------------\n')
        if sys_str_print:
            datafile.write('\n------------------------------------\n')
    datafile.close()
    return fns
Ejemplo n.º 15
0
def checkVisPA(ra, dec, targetName=None, ephFileName=pkg_resources.resource_filename('ExoCTK', 'data/contam_visibility/JWST_ephem_short.txt'), save=False, fig=''):
    
    if ra.find(':')>-1:  #format is hh:mm:ss.s or  dd:mm:ss.s  
        ra = convert_ddmmss_to_float(ra) * 15. * D2R
        dec = convert_ddmmss_to_float(dec) * D2R
    else: #format is decimal
        ra = float(ra) * D2R
        dec = float(dec) * D2R

    #load ephemeris
    eclFlag = False
    eph = EPH.Ephemeris(ephFileName, eclFlag)
    
    #convert dates from MJD to Gregorian calendar dates
    mjd = np.array(eph.datelist)
    d = mdates.julian2num(mjd+2400000.5)
    gd = mdates.num2date(d)

    #loop through dates and determine VIS and PAs (nominal, min, max)
    vis = np.empty(mjd.size,dtype=bool)
    paNom, paMin, paMax = np.empty(mjd.size), np.empty(mjd.size), np.empty(mjd.size)
    for i in range(mjd.size):
        
        #is it visible?
        vis[i] = eph.in_FOR(mjd[i],ra,dec)
        
        #nominal PA at this date
        pa = eph.normal_pa(mjd[i],ra,dec)

        #search for minimum PA allowed by roll
        pa0 = pa
        while eph.is_valid(mjd[i],ra,dec,pa0-0.002):
            pa0 -= 0.002
        
        #search for maximum PA allowed by roll
        pa1 = pa
        while eph.is_valid(mjd[i],ra,dec,pa1+0.002):
            pa1 += 0.002

        paNom[i] = (pa*R2D)%360
        paMin[i] = (pa0*R2D)%360
        paMax[i] = (pa1*R2D)%360

    #does PA go through 360 deg?
    wrap = np.any(np.abs(np.diff(paNom[np.where(vis)[0]])) > 350)

    #Determine good and bad PA ranges
    #Good PAs
    i, = np.where(vis)
    pa = np.concatenate((paNom[i],paMin[i],paMax[i]))
    
    if wrap: 
        pa = np.append(pa,(0.,360.))
    pa.sort()
    
    i1, = np.where(np.diff(pa)>10)
    i0 = np.insert(i1+1,0,0)
    i1 = np.append(i1,-1)
    paGood = np.dstack((pa[i0],pa[i1])).round(1).reshape(-1,2).tolist()

    #bad PAs (complement of the good PAs)
    paBad = []
    if paGood[0][0]>0:
        paBad.append([0.,paGood[0][0]])
    for i in range(1,len(paGood)):
        paBad.append([paGood[i-1][1],paGood[i][0]])
    if paGood[-1][1]<360.:
        paBad.append([paGood[-1][1],360.])

    #print results to file
    """
    if save:
        fName='visibilityPA-'+targetName+'.txt'
        fic=open(fName,'w')

        fic.write('#Date    MJD          VIS?  PAnom   PArange\n')
        for i in range(vis.size):
            tmp1='{:7.3f}'.format(paNom[i]) if vis[i] else 7*'-'
            tmp2='{:7.3f}--{:7.3f}'.format(paMin[i],paMax[i]) if vis[i] else 16*'-'
            #fic.write(gd[i].strftime("%y-%m-%d")+' {:f} {:5s} {:7.3f} {:7.3f}--{:7.3f} \n'.format(mjd[i],str(vis[i]),paNom[i],paMin[i],paMax[i]))
            fic.write(gd[i].strftime("%y-%m-%d")+' {:f} {:5s} {} {} \n'.format(mjd[i],str(vis[i]),tmp1,tmp2))

        fic.write("\n")
        fic.write("Accessible PA ranges: ")
        fic.write(','.join([str(x) for x in paGood]))
        fic.write("\n")
        fic.write("Non-accessible PA ranges: ")
        fic.write(','.join([str(x) for x in paBad]))
        fic.write("\n")
        fic.close()
    """
    # Make a figure
    if not fig or fig==True:
        fig = plt.gcf()
        
    # Do all figure calculations
    iBad, = np.where(vis==False)
    paMasked = np.copy(paNom)
    paMasked[iBad] = np.nan
    gdMasked = np.copy(gd)

    i = np.argmax(paNom)
    if paNom[i+1]<10: 
        i+=1
    paMasked = np.insert(paMasked,i,np.nan)
    gdMasked = np.insert(gdMasked,i,gdMasked[i])

    i = np.argmax(paMin)
    goUp = paMin[i-2]<paMin[i-1] #PA going up at wrap point?

    # Top part
    i0_top = 0 if goUp else i
    i1_top = i if goUp else paMin.size-1
    paMaxTmp = np.copy(paMax)
    paMaxTmp[np.where(paMin>paMax)[0]] = 360
    
    # Bottom part
    i = np.argmin(paMax)
    i0_bot = i if goUp else 0
    i1_bot = paMin.size-1 if goUp else i 
    paMinTmp = np.copy(paMin)
    paMinTmp[np.where(paMin>paMax)[0]] = 0

    # Add fits to matplotlib
    if isinstance(fig, matplotlib.figure.Figure):

        # Make axes
        ax = plt.axes()
        plt.title(targetName)
        
        #plot nominal PA
        plt.plot(gdMasked,paMasked,color='k')
        
        #plot ranges allowed through roll
        if wrap:
            i = np.argmax(paMin)
            goUp = paMin[i-2]<paMin[i-1] #PA going up at wrap point?
            
            #top part
            plt.fill_between(gd[i0_top:i1_top+1],paMin[i0_top:i1_top+1],paMaxTmp[i0_top:i1_top+1],where=vis[i0_top:i1_top+1],lw=0,facecolor='k',alpha=0.5)
            
            #bottom part
            plt.fill_between(gd[i0_bot:i1_bot+1],paMinTmp[i0_bot:i1_bot+1],paMax[i0_bot:i1_bot+1],where=vis[i0_bot:i1_bot+1],lw=0,facecolor='k',alpha=0.5)
            
        else:
            plt.fill_between(gd,paMin,paMax,where=vis,lw=0,facecolor='k',alpha=0.5)

        plt.ylabel('Position Angle (degrees)')
        plt.xlim(min(gd),max(gd))
        ax.xaxis.set_major_locator(mdates.MonthLocator())
        ax.xaxis.set_major_formatter(mdates.DateFormatter("%b '%y"))
        ax.xaxis.set_minor_locator(mdates.DayLocator(list(range(1,32,5))))
        plt.ylim(0,360)
        ax.yaxis.set_major_locator(MultipleLocator(25))
        ax.yaxis.set_minor_locator(MultipleLocator(5))
        plt.grid()
        for label in ax.get_xticklabels():
            label.set_rotation(45)
        
    # Or to bokeh!
    else:
        
        # Convert datetime to a number for Bokeh
        gdMaskednum = [datetime.date(2019, 6, 1)+datetime.timedelta(days=n) for n,d in enumerate(gdMasked)]
        color = 'green'

        # Draw the curve and error
        fig.line(gdMaskednum, paMasked, legend='cutoff', line_color=color)
        
        # Top
        err_y = np.concatenate([paMin[i0_top:i1_top+1],paMaxTmp[i0_top:i1_top+1][::-1]])
        # err_x = np.concatenate([[d.timestamp() for d in gd[i0_top:i1_top+1]],[d.timestamp() for d in gd[i0_top:i1_top+1]][::-1]])
        err_x = np.concatenate([gdMaskednum[i0_top:i1_top+1],gdMaskednum[i0_top:i1_top+1][::-1]])
        fig.patch(err_x, err_y, color=color, fill_alpha=0.2, line_alpha=0)

        # Bottom
        err_y = np.concatenate([paMinTmp[i0_bot:i1_bot+1],paMax[i0_bot:i1_bot+1][::-1]])
        # err_x = np.concatenate([[d.timestamp() for d in gd[i0_bot:i1_bot+1]],[d.timestamp() for d in gd[i0_bot:i1_bot+1]][::-1]])
        err_x = np.concatenate([gdMaskednum[i0_bot:i1_bot+1],gdMaskednum[i0_bot:i1_bot+1][::-1]])
        fig.patch(err_x, err_y, color=color, fill_alpha=0.2, line_alpha=0)
        
        # Plot formatting
        fig.xaxis.axis_label = 'Date'
        fig.yaxis.axis_label = 'Position Angle (degrees)'
            
    return paGood, paBad, gd, fig
Ejemplo n.º 16
0
    def checkVisPA(ra, dec, targetName=None, save=False):
        if ra.find(':') > -1:  #format is hh:mm:ss.s or  dd:mm:ss.s
            ra = convert_ddmmss_to_float(ra) * 15. * D2R
            dec = convert_ddmmss_to_float(dec) * D2R
        else:  #format is decimal
            ra = float(ra) * D2R
            dec = float(dec) * D2R

        #load ephemeris
        ephFileName, eclFlag = os.path.join(os.path.dirname(
            ExoCTK.__file__), 'data/tor/JWST_ephem_short.txt'), False
        eph = EPH.Ephemeris(ephFileName, eclFlag)
        #convert dates from MJD to Gregorian calendar dates
        mjd = np.array(eph.datelist)
        d = mdates.julian2num(mjd + 2400000.5)
        gd = mdates.num2date(d)

        #loop through dates and determine VIS and PAs (nominal, min, max)
        vis = np.empty(mjd.size, dtype=bool)
        paNom, paMin, paMax = np.empty(mjd.size), np.empty(mjd.size), np.empty(
            mjd.size)
        for i in range(mjd.size):
            vis[i] = eph.in_FOR(mjd[i], ra, dec)  #is it visible?
            pa = eph.normal_pa(mjd[i], ra, dec)  #nominal PA at this date

            #search for minimum PA allowed by roll
            pa0 = pa
            while eph.is_valid(mjd[i], ra, dec, pa0 - 0.002):
                pa0 -= 0.002
            #search for maximum PA allowed by roll
            pa1 = pa
            while eph.is_valid(mjd[i], ra, dec, pa1 + 0.002):
                pa1 += 0.002

            paNom[i] = (pa * R2D) % 360
            paMin[i] = (pa0 * R2D) % 360
            paMax[i] = (pa1 * R2D) % 360

        #does PA go through 360 deg?
        wrap = np.any(np.abs(np.diff(paNom[np.where(vis)[0]])) > 350)

        #Determine good and bad PA ranges
        #Good PAs
        i, = np.where(vis)
        pa = np.concatenate((paNom[i], paMin[i], paMax[i]))
        if wrap: pa = np.append(pa, (0., 360.))
        pa.sort()
        i1, = np.where(np.diff(pa) > 10)
        i0 = np.insert(i1 + 1, 0, 0)
        i1 = np.append(i1, -1)
        paGood = np.dstack((pa[i0], pa[i1])).round(1).reshape(-1, 2).tolist()

        #bad PAs (complement of the good PAs)
        paBad = []
        if paGood[0][0] > 0: paBad.append([0., paGood[0][0]])
        for i in range(1, len(paGood)):
            paBad.append([paGood[i - 1][1], paGood[i][0]])
        if paGood[-1][1] < 360.: paBad.append([paGood[-1][1], 360.])

        #print results to file
        """
		if save:
			fName='visibilityPA-'+targetName+'.txt'
			fic=open(fName,'w')

			fic.write('#Date    MJD          VIS?  PAnom   PArange\n')
			for i in range(vis.size):
				tmp1='{:7.3f}'.format(paNom[i]) if vis[i] else 7*'-'
				tmp2='{:7.3f}--{:7.3f}'.format(paMin[i],paMax[i]) if vis[i] else 16*'-'
				#fic.write(gd[i].strftime("%y-%m-%d")+' {:f} {:5s} {:7.3f} {:7.3f}--{:7.3f} \n'.format(mjd[i],str(vis[i]),paNom[i],paMin[i],paMax[i]))
				fic.write(gd[i].strftime("%y-%m-%d")+' {:f} {:5s} {} {} \n'.format(mjd[i],str(vis[i]),tmp1,tmp2))

			fic.write("\n")
			fic.write("Accessible PA ranges: ")
			fic.write(','.join([str(x) for x in paGood]))
			fic.write("\n")
			fic.write("Non-accessible PA ranges: ")
			fic.write(','.join([str(x) for x in paBad]))
			fic.write("\n")
			fic.close()
		"""

        #make the plot
        fig = plt.figure()
        ax = plt.axes()
        plt.title(targetName)

        #plot nominal PA
        iBad, = np.where(vis == False)
        paMasked = np.copy(paNom)
        paMasked[iBad] = np.nan
        gdMasked = np.copy(gd)
        if wrap:
            i = np.argmax(paNom)
            if paNom[i + 1] < 10: i += 1
            paMasked = np.insert(paMasked, i, np.nan)
            gdMasked = np.insert(gdMasked, i, gdMasked[i])
        plt.plot(gdMasked, paMasked, color='k')
        # 		plt.xticks(rotation = 'vertical')

        #plot ranges allowed through roll
        if wrap:
            i = np.argmax(paMin)
            goUp = paMin[i - 2] < paMin[i - 1]  #PA going up at wrap point?
            #top part
            i0 = 0 if goUp else i
            i1 = i if goUp else paMin.size - 1
            paMaxTmp = np.copy(paMax)
            paMaxTmp[np.where(paMin > paMax)[0]] = 360
            plt.fill_between(gd[i0:i1 + 1],
                             paMin[i0:i1 + 1],
                             paMaxTmp[i0:i1 + 1],
                             where=vis[i0:i1 + 1],
                             lw=0,
                             facecolor='k',
                             alpha=0.5)
            #bottom part
            i = np.argmin(paMax)
            i0 = i if goUp else 0
            i1 = paMin.size - 1 if goUp else i
            paMinTmp = np.copy(paMin)
            paMinTmp[np.where(paMin > paMax)[0]] = 0
            plt.fill_between(gd[i0:i1 + 1],
                             paMinTmp[i0:i1 + 1],
                             paMax[i0:i1 + 1],
                             where=vis[i0:i1 + 1],
                             lw=0,
                             facecolor='k',
                             alpha=0.5)
        else:
            plt.fill_between(gd,
                             paMin,
                             paMax,
                             where=vis,
                             lw=0,
                             facecolor='k',
                             alpha=0.5)

        plt.ylabel('Position Angle (degrees)')
        plt.xlim(min(gd), max(gd))
        ax.xaxis.set_major_locator(mdates.MonthLocator())
        ax.xaxis.set_major_formatter(mdates.DateFormatter("%b '%y"))
        ax.xaxis.set_minor_locator(mdates.DayLocator(list(range(1, 32, 5))))
        plt.ylim(0, 360)
        ax.yaxis.set_major_locator(MultipleLocator(25))
        ax.yaxis.set_minor_locator(MultipleLocator(5))
        plt.grid()
        for label in ax.get_xticklabels():
            label.set_rotation(45)
        if save:
            # 			fname=tmpDir+'/visibilityPA-'+targetName+'.png'
            png = mpld3.fig_to_html(fig)

        return png
Ejemplo n.º 17
0
def conj_time_save_to_file(filename, sys_conj_time, r_mode, dps_mode, conjunction_crit, \
				global_s_time, global_e_time, date_format='jd', pickle_file = False, to_append = False):
	""" 	
	-filename:  		string		(doesn't include format)
	-sys_conj_time: 	dictionary
	-r_mode: 		string
	-dps_mode:		string
	-global_s_time: 	float
	-global_e_time: 	float
	-verbose:		bool
	
	# always write to txt file
	"""
	fns = []
	if pickle_file:
		if to_append:
			pkfile = open(filename+'.pickle', 'a+b')
		else:
			pkfile = open(filename+'.pickle', 'w')
		fns.append(filename+'.pickle')
		pickle.dump(sys_conj_time, pkfile)
		pkfile.close()
	if to_append:
		datafile = open(filename+'.txt','a+b')
	else:
		datafile = open(filename+'.txt','w')
	fns.append(filename+'.txt')
	if date_format == 'jd':
		global_s_time_str = str(global_s_time)
		global_e_time_str = str(global_e_time)
	else:
		global_s_time_str = str(dates.num2date(dates.julian2num(global_s_time)))
		global_e_time_str = str(dates.num2date(dates.julian2num(global_e_time)))
	datafile.write('Search for planet conjuction from time '+global_s_time_str+' to '+global_e_time_str+': \n')
	datafile.write('*********************************\n')
	datafile.write('Planet radius : ' + r_mode +'\n')
	datafile.write('Distance from the planet to (earth-star) line of sight : '+ dps_mode + '\n')
	datafile.write('*********************************\n')
	datafile.write('Criterion for conjunction (distance <= ?): '+conjunction_crit+'\n')
	datafile.write('*********************************\n')
	for sys_n in sorted(sys_conj_time.keys()):
	        # datafile.write('System '+str(sys_n)+' (number of planets: '+ \
		#		str(sys_conj_time[sys_n]['n_planets'])+'): \n')
		sys_str = 'System '+str(sys_n)+' (number of planets: '+ \
					str(sys_conj_time[sys_n]['n_planets'])+'): \n'
		sys_str_print = 0
		for n_members in sorted(sys_conj_time[sys_n].keys()):
			if n_members == 'n_planets':
				continue
			# datafile.write('\t----------------\n')
			# datafile.write('\tSearching alignment of '+str(n_members)+' planets: \n')
			search_str = '\t----------------\n\tSearching alignment of '+str(n_members)+' planets: \n'
			search_str_print = 0
			for participants in sorted(sys_conj_time[sys_n][n_members].keys()):
				n_conjs = sys_conj_time[sys_n][n_members][participants]['n_conjs']
				if n_conjs <= 0:
					continue
				else:
					if sys_str_print == 0:
						datafile.write(sys_str)
						sys_str_print = 1
					if search_str_print == 0:
						datafile.write(search_str)
						search_str_print = 1
				datafile.write('\t\t----------------\n')
				datafile.write('\t\tParticipants: '+ str(participants)+': \n')
				start_times = sys_conj_time[sys_n][n_members][participants]['start_points']
				end_times = sys_conj_time[sys_n][n_members][participants]['end_points']
				mid_times = sys_conj_time[sys_n][n_members][participants]['mid_points']
				s_ang_sep = sys_conj_time[sys_n][n_members][participants]['s_ang_sep']
				e_ang_sep = sys_conj_time[sys_n][n_members][participants]['e_ang_sep']
				conj_crit = sys_conj_time[sys_n][n_members][participants]['conj_crit']
				conjunction_period = sys_conj_time[sys_n][n_members][participants]['conjunction_period']
				non_conjunction_period = sys_conj_time[sys_n][n_members][participants]['non_conjunction_period']
				p_pers = sys_conj_time[sys_n][n_members][participants]['participants_periods']
				p_radii = sys_conj_time[sys_n][n_members][participants]['participants_radii']
				p_teqs = sys_conj_time[sys_n][n_members][participants]['participants_teqs']
				s_angs = sys_conj_time[sys_n][n_members][participants]['s_angs']
				e_angs = sys_conj_time[sys_n][n_members][participants]['e_angs']
				incomplete_flag = sys_conj_time[sys_n][n_members][participants]['incomplete_flag']
				notes = sys_conj_time[sys_n][n_members][participants]['notes']

				datafile.write('\t\tConjunctions start at: \n')
				if date_format == 'jd':
					datafile.write('\t\t\t'+str([x+2454900 for x in start_times])+'\n')
				else:
					for x in start_times:
						datafile.write('\t\t\t')
						datafile.write(str(dates.num2date(dates.julian2num(x+2454900)))+'\n')
				datafile.write('\t\tConjunctions end at: \n')
				if date_format =='jd':
					datafile.write('\t\t\t'+str([x+2454900 for x in end_times])+'\n')
				else:	
					for x in end_times:
						if x < 0:
							x_str = '0'
						else:
							x_str =str(dates.num2date(dates.julian2num(x+2454900)))
						datafile.write('\t\t\t'+x_str+'\n')
				datafile.write('\t\t>>> Mid time: \n')
				if date_format == 'jd':
					datafile.write('\t\t\t'+str([x+2454900 for x in mid_times])+'\n')
				else:
					for x in mid_times:
						datafile.write('\t\t\t')
						datafile.write(str(dates.num2date(dates.julian2num(x+2454900)))+'\n')
				datafile.write('\t\t  Conjunction Criterion (unit: Solar Radius): \n')
				datafile.write('\t\t\t'+str(conj_crit)+'\n')
				datafile.write('\t\t  Number of Conjunctions: \n')
				datafile.write('\t\t\t'+str(n_conjs)+'\n')
				datafile.write('\t\t  Maximum separation among planets when conjunction starts (unit: Solar Radius): \n')
				datafile.write('\t\t\t'+str(s_ang_sep)+'\n')
				datafile.write('\t\t  Maximum separation among planets when conjunction ended (unit: Solar Radius): \n')
				datafile.write('\t\t\t'+str(e_ang_sep)+'\n')
				datafile.write('\t\t  Conjunction durations (hours): \n')
				datafile.write('\t\t\t'+str([p*24.0 for p in conjunction_period])+'\n')
				datafile.write('\t\t  Time period between conjunctions (hours): \n')
				datafile.write('\t\t\t'+str([p*24.0 for p in non_conjunction_period])+'\n')
				datafile.write('\t\t  Period of participants (days): \n')
				datafile.write('\t\t\t'+str(p_pers)+'\n')
				datafile.write('\t\t  Radii of participants (unit: Solar Radius):\n')
				datafile.write('\t\t\t'+str(p_radii)+'\n')
				datafile.write('\t\t  Equilibrium temperature of participants (unit: Solar Radius):\n')
				datafile.write('\t\t\t'+str(p_teqs)+'\n')
				datafile.write('\t\t  Position (angular) of participants at start time(unit: radian): \n')
				datafile.write('\t\t\t'+str(s_angs)+'\n')
				datafile.write('\t\t  Position (angular) of participants at end time(unit: radian): \n')
				datafile.write('\t\t\t'+str(e_angs)+'\n')
				if incomplete_flag:
					datafile.write('\t\tNote: there are incomplete conjunctions recorded!\n')
				for note_item in notes:
					datafile.write('\t\t\t'+note_item+'\n')
				datafile.write('\t\t----------------\n')
			if search_str_print:
				datafile.write('\t----------------\n')
		if sys_str_print:
			datafile.write('\n------------------------------------\n')
	datafile.close()
	return fns