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
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
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
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: :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
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
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 }
def jul2date(jul_date): date1 = dates.num2date(dates.julian2num(jul_date)) return '%d.%d.%d'%(date1.year, date1.month, date1.day)
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
def jul2date2(jul_date): date1 = dates.num2date(dates.julian2num(jul_date)) return date1
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
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
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
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
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