def do_calibration_40b(i, obstime_utc, telescope_position, csvfile, total_wait, next_cal, mins_per_beam): calib_sun_dist = 30. current_lst = Time(obstime_utc).sidereal_time('apparent', westerbork().lon) # Consider HA limits for shadowing: # https://old.astron.nl/radio-observatory/astronomers/wsrt-guide-observations/3-telescope-parameters-and-array-configuration # Note ha_limit[1:2] depend on length of calibration! syswait = 2.0 # minutes obstime = (mins_per_beam + syswait) * 40. - syswait # minutes sun_position = get_sun(Time(obstime_utc, scale='utc')) if (i == 4): next_cal = 'flux' print(next_cal) if next_cal == 'flux': calibrators = flux_cal names = flux_names type_cal = 'Flux' ha_limit = [-5.0, 5.0 - obstime / 60., 0.4] # Entry 2 is hardcoded for 5 min per beam if next_cal == 'pol': calibrators = pol_cal names = pol_names type_cal = 'Polarization' ha_limit = [-3.3, 3.3 - obstime / 60., -1.0] # Entry 2 is hardcoded for 5 min per beam is_cal_up = np.array([ (current_lst.hour - calibrators[0].ra.hour > ha_limit[0]) and (current_lst.hour - calibrators[0].ra.hour < ha_limit[1]), (current_lst.hour - calibrators[1].ra.hour > ha_limit[0]) and (current_lst.hour - calibrators[1].ra.hour < ha_limit[2]) ]) is_sundist_okay = np.array([ sun_position.separation(calibrators[0]).value > calib_sun_dist, sun_position.separation(calibrators[1]).value > calib_sun_dist ]) calib_wait = 0 new_obstime_utc = obstime_utc # Wait for calibrator to be at least an hour above the observing horizon, or not shadowed. while not np.any(is_cal_up * is_sundist_okay ): # and (calib_wait < 6. * 60.): # and (not is3c286): calib_wait += dowait new_obstime_utc = wait_for_rise(new_obstime_utc, waittime=dowait) new_lst = Time(new_obstime_utc).sidereal_time('apparent', westerbork().lon) is_cal_up = [(new_lst.hour - calibrators[0].ra.hour > ha_limit[0]) and (new_lst.hour - calibrators[0].ra.hour < ha_limit[1]), (new_lst.hour - calibrators[1].ra.hour > ha_limit[0]) and (new_lst.hour - calibrators[1].ra.hour < ha_limit[2])] n = np.where(is_cal_up)[0][0] ##### EDITABLE: Can change the number of hours the program will wait for a calibrator ##### if calib_wait != 0 and calib_wait < 4.0 * 60: total_wait += calib_wait n = np.where(is_cal_up)[0][0] print("\tCalibrator not up, waiting {} minutes until LST: {}.".format( calib_wait, str(new_lst))) # The commented part is hopefully obsolete with the new calibrator.py and observing strategy, but there's still a bad starting point in the sky # elif calib_wait >= 4.0 * 60: elif calib_wait >= 8.0 * 60: after_cal = obstime_utc - datetime.timedelta(minutes=syswait) new_telescope_position = telescope_position i -= 1 # If can't do any pol at beginning, first must be a flux cal # (if statement untested; trying to fix skipping pol cal when this happens in the middle!): if i == 1: next_cal = 'flux' print( "Must wait {} hours for calibrator to rise. Instead, go directly to target." .format(calib_wait / 60.)) print( "\tIf this appears anywhere other than beginning of scheduling block, probably need to expanding " "options in pointing file.") # break return i, after_cal, new_telescope_position, total_wait, next_cal slew_seconds = calc_slewtime( [telescope_position.ra.radian, telescope_position.dec.radian], [calibrators[n].ra.radian, calibrators[n].dec.radian]) if slew_seconds < calib_wait * 60.: new_obstime_utc = obstime_utc + datetime.timedelta(minutes=calib_wait) else: new_obstime_utc = obstime_utc + datetime.timedelta( seconds=slew_seconds) # Calculate appropriate observe time for the calibrator and observe it. obstime = ( mins_per_beam + syswait ) * 40. - syswait # <mins_per_beam> minutes per beam, 2 min wait if n == 1: obstime = ( 5.0 + syswait ) * 40. - syswait # force 5 minutes per beam, 2 min wait on calibs with natural gap before target after_cal = observe_calibrator(new_obstime_utc, obstime=obstime) if i == 1: write_to_csv(csvfile, 'imaging_start', calibrators[n], new_obstime_utc - datetime.timedelta(minutes=3.0), new_obstime_utc - datetime.timedelta(minutes=2.0)) write_to_csv(csvfile, names[n], calibrators[n], new_obstime_utc, after_cal) print("Scan {} observed {} calibrator {}.".format(i, type_cal, names[n])) check_sun = sun_position.separation(calibrators[n]) if check_sun.value < calib_sun_dist: print("\tWARNING: {} is THIS close to Sun: {:5.2f}".format( names[n], check_sun)) new_telescope_position = calibrators[n] # Set up for next calibrator if next_cal == 'flux': next_cal = 'pol' else: next_cal = 'flux' return i, after_cal, new_telescope_position, total_wait, next_cal
def main(): args = parse_args() print(args.beams) beam_range = args.beams.split(',') beams = range(int(beam_range[0]), int(beam_range[1]) + 1) freqchunks = args.bin_num date = args.date print(beams) basedir = args.basedir with open(args.task_ids) as f: task_id = f.read().splitlines() np.warnings.filterwarnings('ignore') # Find calibrator position calib = SkyCoord.from_name(args.calibname) cell_size = 100. / 3600. # Put all the output from drift_scan_auto_corr.ipynb in a unique folder per source, per set of drift scans. datafiles, posfiles = [], [] for i in range(len(task_id)): datafiles.append('{}{}/{}_exported_data_frequency_split.csv'.format( basedir, task_id[i], task_id[i])) posfiles.append('{}{}/{}_hadec.csv'.format(basedir, task_id[i], task_id[i])) datafiles.sort() posfiles.sort() # Put calibrator into apparent coordinates (because that is what the telescope observes it in.) test = calib.transform_to('fk5') calibnow = test.transform_to( FK5(equinox='J{}'.format(task_id2equinox(task_id[0])))) # Read data from tables data_tab, hadec_tab = [], [] print("\nReading in all the data...") for file, pos in zip(datafiles, posfiles): data_tab.append(Table.read(file, format='csv')) # list of tables hadec_tab.append(Table.read(pos, format='csv')) # list of tables print("Making beam maps: ") for beam in beams: print(beam) for f in range(freqchunks): x, y, z_xx, z_yy = [], [], [], [] for data, hadec in zip(data_tab, hadec_tab): hadec_start = SkyCoord(ra=hadec['ha'], dec=hadec['dec'], unit=(u.rad, u.rad)) time_mjd = Time(data['time'] / (3600 * 24), format='mjd') time_mjd.delta_ut1_utc = 0 # extra line to compensate for missing icrs tables lst = time_mjd.sidereal_time('apparent', westerbork().lon) HAcal = lst - calibnow.ra # in sky coords dHAsky = HAcal - hadec_start[beam].ra + ( 24 * u.hourangle) # in sky coords in hours dHAsky.wrap_at('180d', inplace=True) dHAphys = dHAsky * np.cos(hadec_start[beam].dec.deg * u.deg) # physical offset in hours x = np.append(x, dHAphys.deg) y = np.append( y, np.full(len(dHAphys.deg), hadec_start[beam].dec.deg)) z_xx = np.append( z_xx, data['auto_corr_beam_{}_freq_{}_xx'.format(beam, f)] - np.median(data['auto_corr_beam_{}_freq_{}_xx'.format( beam, f)])) z_yy = np.append( z_yy, data['auto_corr_beam_{}_freq_{}_yy'.format(beam, f)] - np.median(data['auto_corr_beam_{}_freq_{}_yy'.format( beam, f)])) # Create the 2D plane, do a cubic interpolation, and append it to the cube. tx = np.arange(min(x), max(x), cell_size) ty = np.arange(min(y), max(y), cell_size) XI, YI = np.meshgrid(tx, ty) gridcubx = interpolate.griddata( (x, y), z_xx, (XI, YI), method='cubic') # median already subtracted gridcuby = interpolate.griddata((x, y), z_yy, (XI, YI), method='cubic') # Find the reference pixel at the apparent coordinates of the calibrator ref_pixy = (calibnow.dec.deg - min(y)) / cell_size + 1 # FITS indexed from 1 ref_pixx = (-min(x)) / cell_size + 1 # FITS indexed from 1 ref_pixz = 1 # FITS indexed from 1 # Find the peak of the primary beam to normalize norm_xx = np.max(gridcubx[int(ref_pixy) - 3:int(ref_pixy) + 4, int(ref_pixx) - 3:int(ref_pixx) + 4]) norm_yy = np.max(gridcuby[int(ref_pixy) - 3:int(ref_pixy) + 4, int(ref_pixx) - 3:int(ref_pixx) + 4]) # Create 3D array with proper size for given scan set to save data as a cube if f == 0: cube_xx = np.zeros( (freqchunks, gridcubx.shape[0], gridcubx.shape[1])) cube_yy = np.zeros( (freqchunks, gridcuby.shape[0], gridcuby.shape[1])) db_xx = np.zeros( (freqchunks, gridcubx.shape[0], gridcubx.shape[1])) db_yy = np.zeros( (freqchunks, gridcuby.shape[0], gridcuby.shape[1])) cube_xx[f, :, :] = gridcubx / norm_xx cube_yy[f, :, :] = gridcuby / norm_yy # Convert to decibels db_xx[f, :, :] = np.log10(gridcubx / norm_xx) * 10. db_yy[f, :, :] = np.log10(gridcuby / norm_yy) * 10. stokesI = np.sqrt(0.5 * cube_yy**2 + 0.5 * cube_xx**2) squint = cube_xx - cube_yy wcs = WCS(naxis=3) #wcs.wcs.cdelt = np.array([-cell_size, cell_size, 12.207e3*1500]) ## I think this should be 1050, 12.207e3 is the width of 1 channel wcs.wcs.cdelt = np.array([-cell_size, cell_size, 12.207e3 * 1050]) wcs.wcs.ctype = ['RA---TAN', 'DEC--TAN', 'FREQ'] #wcs.wcs.crval = [calib.ra.to_value(u.deg), calib.dec.to_value(u.deg), 1219.609e6+(12.207e3*(500+1500/2))] # 1280e6+(12.207e3*(-(24576/2-14000)))] wcs.wcs.crval = [ calib.ra.to_value(u.deg), calib.dec.to_value(u.deg), 1280e6 + (12.207e3 * (-(24576 / 2 - 14000))) ] wcs.wcs.crpix = [ref_pixx, ref_pixy, ref_pixz] wcs.wcs.specsys = 'TOPOCENT' wcs.wcs.restfrq = 1.420405752e+9 header = wcs.to_header() hdux = fits.PrimaryHDU(cube_xx, header=header) hduy = fits.PrimaryHDU(cube_yy, header=header) hduI = fits.PrimaryHDU(stokesI, header=header) hdusq = fits.PrimaryHDU(squint, header=header) if not os.path.exists(basedir + 'fits_files/{}/'.format(date)): os.mkdir(basedir + 'fits_files/{}/'.format(date)) # Save the FITS files hdux.writeto(basedir + 'fits_files/{}/{}_{}_{:02}_xx.fits'.format( date, args.calibname.replace(" ", ""), date, beam), overwrite=True) hduy.writeto(basedir + 'fits_files/{}/{}_{}_{:02}_yy.fits'.format( date, args.calibname.replace(" ", ""), date, beam), overwrite=True) hduI.writeto(basedir + 'fits_files/{}/{}_{}_{:02}_I.fits'.format( date, args.calibname.replace(" ", ""), date, beam), overwrite=True) hdusq.writeto(basedir + 'fits_files/{}/{}_{}_{:02}_diff.fits'.format( date, args.calibname.replace(" ", ""), date, beam), overwrite=True)
'template' ] else: header = [ 'source', 'ra', 'ha', 'dec', 'date1', 'time1', 'date2', 'time2', 'int', 'type', 'weight', 'beam', 'switch_type', 'freqmode', 'centfreq', 'template' ] print("Will shift pointings if Sun is within {} degrees.".format( args.sun_distance)) # Estimate the telescope starting position as on the meridian (approximately parked) telescope_position = SkyCoord(ra=Time(args.starttime_utc).sidereal_time( 'apparent', westerbork().lon), dec='50d00m00s') current_lst = Time(args.starttime_utc).sidereal_time('apparent', westerbork().lon) next_cal = 'flux' if args.pol_cal_true: next_cal = 'pol' if (current_lst.hour - pol_cal[1].ra.hour > -5.0) and (current_lst.hour - pol_cal[1].ra.hour < 0.1): next_cal = 'pol' # Create a record of the positions planned to be observed so we can plot later. observed_pointings = [] # Keep track of idle time. total_wait = 0
def do_target_observation(i, obstime_utc, telescope_position, csvfile, total_wait): #, closest_field): # Get objects that are close to current observing horizon: current_lst = Time(obstime_utc).sidereal_time('apparent', westerbork().lon) proposed_ra = (current_lst + Longitude('6h')).wrap_at(360 * u.deg) test_slew_seconds = calc_slewtime( [telescope_position.ra.radian, telescope_position.dec.radian], [proposed_ra.radian, telescope_position.dec.radian]) avail_fields = apertif_fields[apertif_fields['weights'] > 0] availability = SkyCoord( np.array(avail_fields['hmsdms'] )).ra.hour - proposed_ra.hour - test_slew_seconds / 3600. availability[availability < -12.] += 24. sun_position = get_sun(Time(obstime_utc, scale='utc')) sun_okay = np.array( sun_position.separation(SkyCoord(avail_fields['hmsdms'])).value) targ_wait = 0. # minutes ##### EDITABLE: Will control the maximum wait time for a target before it gives up and looks for a calibrator ##### # wait_limit = 5.0 # hours wait_limit = 10.0 # hours new_obstime_utc = obstime_utc # First check what is *already* up. If nothing, then wait for something to rise. ##### If target is passing it's HA limit, adjust availability numbers (especially the second one) ##### while not np.any((availability < -0.02) & (availability > -0.40) & (sun_okay > args.sun_distance)): targ_wait += dowait new_obstime_utc = wait_for_rise(new_obstime_utc, waittime=dowait) new_lst = Time(new_obstime_utc).sidereal_time('apparent', westerbork().lon) proposed_ra = (new_lst + Longitude('6h')).wrap_at(360 * u.deg) availability = SkyCoord(np.array( avail_fields['hmsdms'])).ra.hour - proposed_ra.hour availability[availability < -12.] += 24. # print(availability, sun_okay > args.sun_distance, sun_okay) if (targ_wait != 0.) and (targ_wait <= wait_limit * 60.): total_wait += targ_wait print( "\tTarget not up (or sun issues), waiting {} minutes until LST: {}" .format(targ_wait, str(new_lst))) if targ_wait <= wait_limit * 60.: # Choose M101 field first if available or within a 1 hour wait AND (before this function) if users had requested it in args.repeat_m101 if 'M1403+5324' in avail_fields[(availability < -0.02) & (availability > -0.40)]['name']: first_field = avail_fields[avail_fields['name'] == 'M1403+5324'][0] print( "*** M1403+5324 OBSERVED! WAIT A MONTH TO SCHEDULE AGAIN! ***" ) elif 'M1403+5324' in avail_fields[(availability < 1.00) & (availability > -0.02)]['name']: m101_field = avail_fields[avail_fields['name'] == 'M1403+5324'][0] m101_availability = SkyCoord( m101_field['hmsdms']).ra.hour - proposed_ra.hour while not (m101_availability < -0.02) & (m101_availability > -0.40): targ_wait += dowait new_obstime_utc = wait_for_rise(new_obstime_utc, waittime=dowait) new_lst = Time(new_obstime_utc).sidereal_time( 'apparent', westerbork().lon) proposed_ra = (new_lst + Longitude('6h')).wrap_at(360 * u.deg) m101_availability = SkyCoord( m101_field['hmsdms']).ra.hour - proposed_ra.hour # m101_availability[m101_availability < -12] += 24 first_field = m101_field print( "*** M1403+5324 OBSERVED! WAIT A MONTH TO SCHEDULE AGAIN! ***" ) else: first_field = avail_fields[(availability < -0.02) & (availability > -0.40) & (sun_okay > args.sun_distance)][0] check_sun = sun_position.separation(SkyCoord( first_field['hmsdms'])) if check_sun.value < 50.: print("\tField is THIS close to Sun: {}".format(check_sun)) # NOTE SLEW TIME IS CALCULATED TO THE *OBSERVING* HORIZON, NOT TO THE NEW RA! # TELESCOPE SHOULD MOVE TO HORIZON AND WAIT!!! slew_seconds = calc_slewtime( [telescope_position.ra.radian, telescope_position.dec.radian], [ SkyCoord(first_field['hmsdms']).ra.radian, SkyCoord(first_field['hmsdms']).dec.radian ]) if slew_seconds < targ_wait * 60.: new_obstime_utc = obstime_utc + datetime.timedelta( minutes=targ_wait) else: new_obstime_utc = obstime_utc + datetime.timedelta( seconds=slew_seconds) after_target = observe_target(apertif_fields, new_obstime_utc, first_field['name'], obstime=11.5) write_to_csv(csvfile, first_field['name'], SkyCoord(first_field['hmsdms']), new_obstime_utc, after_target) print("Scan {} observed {}.".format(i, first_field['hmsdms'])) return i, after_target, SkyCoord(first_field['hmsdms']), total_wait else: print("\tNo target for {} hours. Go to a calibrator instead.".format( targ_wait / 60.)) i -= 1 return i, obstime_utc, telescope_position, total_wait
'template' ] else: header = [ 'source', 'ra', 'ha', 'dec', 'date1', 'time1', 'date2', 'time2', 'int', 'type', 'weight', 'beam', 'switch_type', 'freqmode', 'centfreq', 'template' ] print("Will shift pointings if Sun is within {} degrees.".format( args.sun_distance)) # Estimate the telescope starting position as on the meridian (approximately parked) telescope_position = SkyCoord(ra=Time(args.starttime_utc).sidereal_time( 'apparent', westerbork().lon), dec='50d00m00s') current_lst = Time(args.starttime_utc).sidereal_time('apparent', westerbork().lon) next_cal = 'flux' # Start on polarization calibrator rather than flux cal if user specified: if args.pol_cal_true: next_cal = 'pol' if (current_lst.hour - pol_cal[1].ra.hour > -5.0) and (current_lst.hour - pol_cal[1].ra.hour < 0.1): next_cal = 'pol' # Create a record of the positions planned to be observed so we can plot later. observed_pointings = [] # Keep track of idle time.
def do_calibration(i, obstime_utc, telescope_position, csvfile, total_wait): current_lst = Time(obstime_utc).sidereal_time('apparent', westerbork().lon) is3c147 = np.abs(current_lst.hour - flux_cal[0].ra.hour < 5.0) is_ctd93 = np.abs(current_lst.hour - pol_cal[2].ra.hour < 5.0) calib_wait = 0 # Wait for calibrator to be at least an hour above the horizon. while (not is3c147) and (not is_ctd93): calib_wait += dowait total_wait += dowait new_obstime_utc = wait_for_rise(obstime_utc, waittime=dowait) obstime_utc = new_obstime_utc current_lst = Time(obstime_utc).sidereal_time('apparent', westerbork().lon) is3c147 = np.abs(current_lst.hour - flux_cal[0].ra.hour) < 5.0 is_ctd93 = np.abs(current_lst.hour - pol_cal[2].ra.hour) < 5.0 if calib_wait != 0: print("\tCalibrator not up, waiting {} minutes until LST: {}.".format( calib_wait, str(current_lst))) # Observe the calibrator(s) that is (are) up: if is3c147: slew_seconds = calc_slewtime( [telescope_position.ra.radian, telescope_position.dec.radian], [flux_cal[0].ra.radian, flux_cal[0].dec.radian]) new_obstime_utc = obstime_utc + datetime.timedelta( seconds=slew_seconds) after_3c147 = observe_calibrator(new_obstime_utc, obstime=15) write_to_csv(csvfile, flux_names[0], flux_cal[0], new_obstime_utc, after_3c147) print("Scan {} observed {}.".format(i, flux_names[0])) sun_position = get_sun(Time(new_obstime_utc, scale='utc')) check_sun = sun_position.separation(flux_cal[0]) if check_sun.value < args.sun_distance: print("\tWARNING: {} is THIS close to Sun: {:5.2f}".format( flux_names[0], check_sun)) i += 1 slew_seconds = calc_slewtime( [flux_cal[0].ra.radian, flux_cal[0].dec.radian], [pol_cal[0].ra.radian, pol_cal[0].dec.radian]) new_obstime_utc = after_3c147 + datetime.timedelta( seconds=slew_seconds) after_3c138 = observe_calibrator(new_obstime_utc, obstime=15) write_to_csv(csvfile, pol_names[0], pol_cal[0], new_obstime_utc, after_3c138) print("Scan {} observed {}.".format(i, pol_names[0])) check_sun = sun_position.separation(pol_cal[0]) if check_sun.value < args.sun_distance: print("\tWARNING: {} is THIS close to Sun: {:5.2f}".format( pol_names[0], check_sun)) return i, after_3c138, pol_cal[0], total_wait else: slew_seconds = calc_slewtime( [telescope_position.ra.radian, telescope_position.dec.radian], [pol_cal[2].ra.radian, pol_cal[2].dec.radian]) new_obstime_utc = obstime_utc + datetime.timedelta( seconds=slew_seconds) after_ctd93 = observe_calibrator(new_obstime_utc, obstime=15) write_to_csv(csvfile, pol_names[2], pol_cal[2], new_obstime_utc, after_ctd93) print("Scan {} observed {}.".format(i, pol_names[2])) sun_position = get_sun(Time(new_obstime_utc, scale='utc')) check_sun = sun_position.separation(pol_cal[2]) if check_sun.value < args.sun_distance: print("\tWARNING: {} is THIS close to Sun: {:5.2f}".format( pol_names[2], check_sun)) return i, after_ctd93, pol_cal[2], total_wait
def do_target_observation(i, obstime_utc, telescope_position, csvfile, total_wait, closest_field): # Get first position or objects that are close to current observing horizon: current_lst = Time(obstime_utc).sidereal_time('apparent', westerbork().lon) proposed_ra = (current_lst + Longitude('1.5h')).wrap_at(360 * u.deg) avail_fields = timing_fields[timing_fields['weights'] > 0] if closest_field: availability = SkyCoord( timing_fields['hmsdms'][closest_field]).ra.hour - proposed_ra.hour else: availability = SkyCoord(np.array( avail_fields['hmsdms'])).ra.hour - proposed_ra.hour availability[availability < -12] += 24 targ_wait = 180 # to make sure ATDB has enough time to start a new observation while not np.any((availability < 0.5) & (availability > -0.5)): targ_wait += dowait total_wait += dowait new_obstimeUTC = wait_for_rise(obstime_utc, waittime=dowait) obstime_utc = new_obstimeUTC current_lst = Time(obstime_utc).sidereal_time('apparent', westerbork().lon) proposed_ra = (current_lst + Longitude('1.5h')).wrap_at(360 * u.deg) if closest_field: availability = SkyCoord(timing_fields['hmsdms'] [closest_field]).ra.hour - proposed_ra.hour else: availability = SkyCoord(np.array( avail_fields['hmsdms'])).ra.hour - proposed_ra.hour availability[availability < -12] += 24 if targ_wait != 180: print("\tTarget not up, waiting {} minutes until LST: {}".format( targ_wait, str(current_lst))) sun_position = get_sun(Time(obstime_utc, scale='utc')) moon_position = get_moon(Time(obstime_utc, scale='utc')) if closest_field: first_field = timing_fields[closest_field][0] check_sun = sun_position.separation(SkyCoord(first_field['hmsdms'])) check_moon = moon_position.separation(SkyCoord(first_field['hmsdms'])) if check_sun.value < args.sun_distance: print("\tWARNING: {} is THIS close to Sun: {:5.2f}".format( name, check_sun)) if check_moon.value < 0.5: print("\tWARNING: {} is within 0.5 deg of the Moon.".format(name)) else: first_field = random.choice(avail_fields[(availability < 0.5) & (availability > -0.5)]) check_sun = sun_position.separation(SkyCoord(first_field['hmsdms'])) check_moon = moon_position.separation(SkyCoord(first_field['hmsdms'])) while (check_sun.value < args.sun_distance) or (check_moon.value < 0.5): print( "\tSun or Moon too close to first pick; choose another target field" ) first_field = random.choice(avail_fields[(availability < 0.5) & (availability > -0.5)]) check_sun = sun_position.separation(SkyCoord( first_field['hmsdms'])) check_moon = moon_position.separation( SkyCoord(first_field['hmsdms'])) # NOTE SLEW TIME IS CALCULATED TO THE *OBSERVING* HORIZON, NOT TO THE NEW RA! # TELESCOPE SHOULD MOVE TO HORIZON AND WAIT!!! slew_seconds = calc_slewtime( [telescope_position.ra.radian, telescope_position.dec.radian], [ SkyCoord(first_field['hmsdms']).ra.radian, SkyCoord(first_field['hmsdms']).dec.radian ]) new_obstimeUTC = obstime_utc + datetime.timedelta( seconds=slew_seconds) + datetime.timedelta(seconds=targ_wait) after_target = observe_target(timing_fields, new_obstimeUTC, first_field['name'], obstime=3) write_to_csv(csvfile, first_field['name'], SkyCoord(first_field['hmsdms']), new_obstimeUTC, after_target, pulsar=False) print("Scan {} observed {}.".format(i, first_field['hmsdms'])) return i, after_target, SkyCoord(first_field['hmsdms']), total_wait
elif os.path.isfile(csv_filename) & os.path.isfile(args.previous_obs): print("Specified output file exists; appending schedule to previous file {}".format(csv_filename)) header = False elif os.path.isfile(csv_filename): print("Output file {} exists but not specified with '-p', so overwriting.".format(csv_filename)) os.remove(csv_filename) header = ['source', 'ra', 'ha', 'dec', 'date1', 'time1', 'date2', 'time2', 'int', 'type', 'weight', 'beam', 'switch_type', 'freqmode', 'centfreq', 'template'] else: header = ['source', 'ra', 'ha', 'dec', 'date1', 'time1', 'date2', 'time2', 'int', 'type', 'weight', 'beam', 'switch_type', 'freqmode', 'centfreq', 'template'] print("Will shift pointings if Sun is within {} degrees.".format(args.sun_distance)) # Estimate the telescope starting position as on the meridian (approximately parked) telescope_position = SkyCoord(ra=Time(args.starttime_utc).sidereal_time('apparent', westerbork().lon), dec='50d00m00s') current_lst = Time(args.starttime_utc).sidereal_time('apparent', westerbork().lon) next_cal = 'flux' if args.pol_cal_true: next_cal = 'pol' # if (current_lst.hour - pol_cal[1].ra.hour > -5.0) and (current_lst.hour - pol_cal[1].ra.hour < 0.1): # next_cal = 'pol' # Create a record of the positions planned to be observed so we can plot later. observed_pointings = [] # Keep track of idle time. total_wait = 0 # Do the observations: select calibrators and target fields, and write the output to a CSV file. # Also, writes out a record of what is observed, when, and if the telescope has to wait for objects to rise.
def do_calibration(i, obstime_utc, telescope_position, csvfile, total_wait): current_lst = Time(obstime_utc).sidereal_time('apparent', westerbork().lon) isB1933 = np.abs(current_lst.hour - psr_cal[0].ra.hour) < 5.0 isB0531 = np.abs(current_lst.hour - psr_cal[1].ra.hour) < 5.0 isB0329 = np.abs(current_lst.hour - psr_cal[2].ra.hour) < 5.0 isB0950 = np.abs(current_lst.hour - psr_cal[3].ra.hour) < 5.0 calib_wait = 180 # to make sure ATDB has enough time to start a new observation # Wait for calibrator to be at least an hour above the horizon. while (not isB1933) and (not isB0531) and (not isB0329) and (not isB0950): calib_wait += dowait total_wait += dowait new_obstime_utc = wait_for_rise(obstime_utc, waittime=dowait) obstime_utc = new_obstime_utc current_lst = Time(obstime_utc).sidereal_time('apparent', westerbork().lon) isB1933 = np.abs(current_lst.hour - psr_cal[0].ra.hour) < 5.0 isB0531 = np.abs(current_lst.hour - psr_cal[1].ra.hour) < 5.0 isB0329 = np.abs(current_lst.hour - psr_cal[2].ra.hour) < 5.0 isB0950 = np.abs(current_lst.hour - psr_cal[3].ra.hour) < 5.0 if calib_wait != 180: print("\tCalibrator not up, waiting {} minutes until LST: {}.".format( calib_wait, str(current_lst))) # Observe the calibrator(s) that is (are) up: if isB1933: name = psr_names[0] psr = psr_cal[0] elif isB0531: name = psr_names[1] psr = psr_cal[1] elif isB0329: name = psr_names[2] psr = psr_cal[2] elif isB0950: name = psr_names[3] psr = psr_cal[3] else: print( "\tError: No known test pulsar visible. This should not be possible" ) exit() sun_position = get_sun(Time(obstime_utc, scale='utc')) moon_position = get_moon(Time(obstime_utc, scale='utc')) check_sun = sun_position.separation(psr) check_moon = moon_position.separation(psr) if check_sun.value < args.sun_distance: # Can hard code this to a different value than target. print("\tWARNING: {} is THIS close to Sun: {:5.2f}".format( name, check_sun)) if check_moon.value < 0.5: print("\tWARNING: {} is within 0.5 deg of the Moon!".format(name)) slew_seconds = calc_slewtime( [telescope_position.ra.radian, telescope_position.dec.radian], [psr.ra.radian, psr.dec.radian]) new_obstime_utc = obstime_utc + datetime.timedelta(seconds=slew_seconds) after_psr = observe_calibrator(new_obstime_utc, obstime=5) write_to_csv(csvfile, name, psr, new_obstime_utc, after_psr, pulsar=True) print("Scan {} observed {}.".format(i, name)) return i, after_psr, psr, total_wait
if (dict(observations[i])['name'][0:2] != '3c') and ( dict(observations[i])['name'][0:2] != '3C') and ( dict(observations[i])['name'][0:2] != 'CT') ] # Adjust 'weights' field for objects that have been previously observed: for obs in timing_obs: if obs in fields['name']: i = np.where(timing_fields['name'] == obs) timing_fields['weights'][i] -= 1 else: print("Not querying ATDB for previous observations.") # Estimate the telescope starting position as on the meridian (approximately parked) telescope_position = SkyCoord(ra=Time(args.starttime_utc).sidereal_time( 'apparent', westerbork().lon), dec='50d00m00s') # Create a record of the positions planned to be observed so we can plot later. observed_pointings = [] print("\nStarting observations! UTC: " + str(args.starttime_utc)) print("Calculating schedule for the following " + str(args.schedule_length) + " days.\n") # Keep track of observing efficiency total_wait = 0 # Could expand code to include the option of picking the field to start with. closest_field = None # Open & prepare CSV file to write parset parameters to, in format given by V.M. Moss.
def main(): args = parse_args() # User supplied **UTC** start time: start_obstime_utc = args.starttime_utc current_lst = Time(start_obstime_utc).sidereal_time('apparent', westerbork().lon) # User supplied calibrator: calib_name = args.calib drift_cal = SkyCoord.from_name(calib_name) # Convert to apparent coordinates for setting up the observations test = drift_cal.transform_to('fk5') drift_cal = test.transform_to(FK5(equinox='J'+str(Time(start_obstime_utc).decimalyear))) print("\n##################################################################") print("Calibrator is: {}".format(calib_name)) print("Calibrator position is: {} in J{:7.2f} coordinates".format(drift_cal.to_string('hmsdms'), Time(start_obstime_utc).decimalyear)) print("\t in degrees: {} {}".format(drift_cal.ra.deg, drift_cal.dec.deg)) print("Starting LST is :", current_lst) wrap = 0 * u.hourangle if (current_lst-drift_cal.ra).value > 12.0: wrap = 24 * u.hourangle if (current_lst-drift_cal.ra).value < -12.0: wrap = -24 * u.hourangle print("Starting HA of calibrator is: {}".format(current_lst-drift_cal.ra-wrap)) if np.abs((current_lst-drift_cal.ra-wrap).hourangle) > 6.: print("CALIBRATOR IS NOT ACTUALLY UP (but calculations are still right).") print("") beams = read_beams() rows = np.array(unique(beams, keys='dDec')) diff = rows[0][1] - rows[1][1] print("Starting observations! UTC: {}".format(args.starttime_utc)) # Calculate the starting position of the beams and the length of the drift # (Do for multiple options which will print if ags.verbose = True): for n in range(1,5): # Only include explicit drift through beam 0 if only drifting through peak. if n > 1: r_nozero = np.delete(rows, 3) else: r_nozero = rows dec_cen = [] dec_row = [] ra_start = [] ha_start = [] ha_end = [] drift_time = [] # Add drifts at the start if n > 1: # for i in range(n + 0, 0, -1): # changed from n-1 # dec_row.append(drift_cal.dec.deg + rows[0][1] + (diff) / (n-1) * i) # dec_cen.append(drift_cal.dec.deg - rows[0][1] - (diff) / (n-1) * i) for i in range(n + 2, 0, -1): # Regular density of scans outside first row dec_row.append(drift_cal.dec.deg + rows[0][1] + (diff) / (n) * i) dec_cen.append(drift_cal.dec.deg - rows[0][1] - (diff) / (n) * i) # Drift starts at high RA, low HA ha_start.append(np.min(beams[np.where(beams['dDec'] == rows[0][1])]['dHA'])) ha_end.append(np.max(beams[np.where(beams['dDec'] == rows[0][1])]['dHA'])) ra_start.append(drift_cal.ra.deg + (ha_start[-1] - 0.9) / np.cos(dec_row[-1] * u.deg)) drift_time.append((np.abs(ha_end[-1] - ha_start[-1] + 1.8) / np.cos((dec_row[-1]) * u.deg)) * 12. / 180. * 60. * u.min) # Do drifts for all the beams for r in r_nozero[:-1]: for i in range(n): dec_row.append(drift_cal.dec.deg + r[1] - (diff) / n * i) dec_cen.append(drift_cal.dec.deg - r[1] + (diff) / n * i) ha_start.append(np.min(beams[np.where(beams['dDec'] == r[1])]['dHA'])) ha_end.append(np.max(beams[np.where(beams['dDec'] == r[1])]['dHA'])) ra_start.append(drift_cal.ra.deg + (ha_start[-1] - 0.9) / np.cos(dec_row[-1] * u.deg)) drift_time.append((np.abs(ha_end[-1] - ha_start[-1] + 1.8) / np.cos((dec_row[-1]) * u.deg)) * 12. / 180. * 60. * u.min) # Add drifts at the end if n > 1: for i in range(0, n+3): # changed from n-1 dec_row.append(drift_cal.dec.deg + rows[-1][1] - (diff) / (n) * i) dec_cen.append(drift_cal.dec.deg - rows[-1][1] + (diff) / (n) * i) # Drift starts at high RA, low HA ha_start.append(np.min(beams[np.where(beams['dDec'] == rows[-1][1])]['dHA'])) ha_end.append(np.max(beams[np.where(beams['dDec'] == rows[-1][1])]['dHA'])) ra_start.append(drift_cal.ra.deg + (ha_start[-1] - 0.75) / np.cos(dec_row[-1] * u.deg)) drift_time.append((np.abs(ha_end[-1] - ha_start[-1] + 1.5) / np.cos((dec_row[-1]) * u.deg)) * 12. / 180. * 60. * u.min) start_pos = SkyCoord(ra=np.array(ra_start), dec=dec_cen, unit='deg') if args.verbose and (int(args.drifts_per_beam) != n): print("Drift time: {}".format([drift_time[i].value for i in range(len(drift_time))])) print("Number of drifts/beam (approx): {}.".format(n)) print("Total time: {}.\n".format(np.ceil(sum(drift_time) + 2. * (len(drift_time)-1) * u.min))) if (args.verbose and int(args.drifts_per_beam) == n) or (int(args.drifts_per_beam) == n): print("Drift time: {}".format([drift_time[i].value for i in range(len(drift_time))])) print("Number of drifts/beam (approx): {}.".format(n)) print("Total time: {}.\n".format(np.ceil(sum(drift_time) + 2. * (len(drift_time)-1) * u.min))) # Plot and save the drifts for the one actually requested: fig,ax=plt.subplots(figsize=(9, 6)) ax.scatter(drift_cal.ra.deg, drift_cal.dec.deg, c='red', s=20) ax.scatter(drift_cal.ra.deg + beams['dHA'] / np.cos((drift_cal.dec.deg + beams['dDec']) * u.deg), drift_cal.dec.deg + beams['dDec'], s=10, marker='o', facecolor='black') ax.scatter(drift_cal.ra.deg + beams['dHA'] / np.cos((drift_cal.dec.deg + beams['dDec']) * u.deg), drift_cal.dec.deg + beams['dDec'], s=3000, marker='o', color="none", edgecolors='k') ax.scatter(ra_start, dec_row, s=10, marker='*', facecolor='brown') for i in range(len(dec_cen)): # ax.plot([ra_start[i], ra_start[i] + (ha_end[i] - ha_start[i] + 1.2) / np.cos((dec_row[i]) * u.deg)], ax.plot([ra_start[i], ra_start[i] + drift_time[i] / u.min / 60. /12. * 180.], [dec_row[i], dec_row[i]]) xlims = ax.get_xlim() plt.xlim(xlims[1]+0.25,xlims[0]-0.25) ax.set_xlabel("RA [deg]", fontsize=20) ax.set_ylabel("DEC [deg]", fontsize=20) figfilename = calib_name.replace(' ', '') + '_driftscan.png' plt.savefig(figfilename, dpi=200, bbox_inches='tight') # Open & prepare CSV file to write parset parameters to, in format given by V.M. Moss. # Don't worry about slew time because 2 minute wait will always be longer. with open(calib_name.replace(' ','') + "_drift" + args.starttime_utc.strftime("%Y%m%d") + args.output + ".csv", "w") as csvfile: csvfile.write('source,ra,ha,dec,date1,time1,date2,time2,int,type,weight,beam,switch_type,freqmode,centfreq,template\n') for i in range(len(dec_cen)): sidereal_t = Time(start_obstime_utc).sidereal_time('apparent', westerbork().lon) wrap = 0 * u.hourangle if (sidereal_t - drift_cal.ra).value > 12.0 : wrap = 24 * u.hourangle if (sidereal_t - drift_cal.ra).value < -12.0 : wrap = -24 * u.hourangle telescope_position_hadec = sidereal_t - start_pos[i].ra - wrap end_obstime_utc = do_drift(start_obstime_utc, drift_time[i].value) date1, time1 = start_obstime_utc.strftime('%Y-%m-%d'), start_obstime_utc.strftime('%H:%M:%S') date2, time2 = end_obstime_utc.strftime('%Y-%m-%d'), end_obstime_utc.strftime('%H:%M:%S') offset = (drift_cal.dec.deg - dec_cen[i]) * 60. # units in arcmins sign = '+' if int(offset) >= 0 else '-' csvfile.write('{}drift{}{:02},,{:.6f},{:.6f},{},{},{},{},10,T,compound,0,system,300,1280,{}\n'.format(calib_name.replace(' ',''), sign, int(np.abs(offset)),telescope_position_hadec.deg, dec_cen[i], date1, time1, date2, time2, '/opt/apertif/share/parsets/parset_start_observation_atdb_SubbandPhaseCorrection.template')) start_obstime_utc = end_obstime_utc + datetime.timedelta(minutes=2.0) print(end_obstime_utc) # Don't add the last 2 minutes to write out the end time because we don't care about the delay for the data writer. print("Assuming {} drifts, ending observations! UTC: {}".format(args.drifts_per_beam,end_obstime_utc)) print("CSV file written to {}".format(csvfile.name)) print("PNG file written to {}".format(figfilename)) print("##################################################################\n")
def do_target_observation(i, obstime_utc, telescope_position, csvfile, total_wait): #, closest_field): # Get objects that are close to current observing horizon: current_lst = Time(obstime_utc).sidereal_time('apparent', westerbork().lon) proposed_ra = (current_lst + Longitude('6h')).wrap_at(360 * u.deg) test_slew_seconds = calc_slewtime( [telescope_position.ra.radian, telescope_position.dec.radian], [proposed_ra.radian, telescope_position.dec.radian]) avail_fields = apertif_fields[apertif_fields['weights'] > 0] availability = SkyCoord( np.array(avail_fields['hmsdms'] )).ra.hour - proposed_ra.hour + test_slew_seconds / 3600. availability[availability < -12] += 24 targ_wait = 0 # minutes wait_limit = 7.0 # hours new_obstime_utc = obstime_utc # First check what is *already* up. If nothing, then wait for something to rise. while not np.any((availability < 0.00) & (availability > -0.48)): targ_wait += dowait new_obstime_utc = wait_for_rise(new_obstime_utc, waittime=dowait) current_lst = Time(new_obstime_utc).sidereal_time( 'apparent', westerbork().lon) proposed_ra = (current_lst + Longitude('6h')).wrap_at(360 * u.deg) availability = SkyCoord(np.array( avail_fields['hmsdms'])).ra.hour - proposed_ra.hour availability[availability < -12] += 24 if (targ_wait != 0) and (targ_wait <= wait_limit * 60): total_wait += targ_wait print("\tTarget not up, waiting {} minutes until LST: {}".format( targ_wait, str(current_lst))) if targ_wait <= wait_limit * 60: # Choose M101 field first if available or within a 1 hour wait AND (before this function) if users had requested it in args.repeat_m101 if 'M1403+5324' in avail_fields[(availability < 0.00) & (availability > -0.48)]['name']: first_field = avail_fields[avail_fields['name'] == 'M1403+5324'][0] print( "*** M1403+5324 OBSERVED! WAIT A MONTH TO SCHEDULE AGAIN! ***" ) elif 'M1403+5324' in avail_fields[(availability < 1.00) & (availability > 0)]['name']: m101_field = avail_fields[avail_fields['name'] == 'M1403+5324'][0] m101_availability = SkyCoord( m101_field['hmsdms']).ra.hour - proposed_ra.hour while not (m101_availability < 0.00) & (m101_availability > -0.48): targ_wait += dowait new_obstime_utc = wait_for_rise(new_obstime_utc, waittime=dowait) current_lst = Time(new_obstime_utc).sidereal_time( 'apparent', westerbork().lon) proposed_ra = (current_lst + Longitude('6h')).wrap_at(360 * u.deg) m101_availability = SkyCoord( m101_field['hmsdms']).ra.hour - proposed_ra.hour # m101_availability[m101_availability < -12] += 24 first_field = m101_field print( "*** M1403+5324 OBSERVED! WAIT A MONTH TO SCHEDULE AGAIN! ***" ) else: first_field = avail_fields[(availability < 0.00) & (availability > -0.48)][0] sun_position = get_sun(Time(new_obstime_utc, scale='utc')) moon_position = get_moon(Time(new_obstime_utc, scale='utc')) # print("Sun position: {}".format(sun_position)) check_sun = sun_position.separation(SkyCoord(first_field['hmsdms'])) check_moon = moon_position.separation(SkyCoord(first_field['hmsdms'])) if check_sun.value < args.sun_distance: first_field = avail_fields[(availability < 0.0) & (availability > -0.48)][-1] check_sun = sun_position.separation(SkyCoord( first_field['hmsdms'])) print("\tShifted pointings. New field is THIS close to Sun: {}". format(check_sun)) # NOTE SLEW TIME IS CALCULATED TO THE *OBSERVING* HORIZON, NOT TO THE NEW RA! # TELESCOPE SHOULD MOVE TO HORIZON AND WAIT!!! slew_seconds = calc_slewtime( [telescope_position.ra.radian, telescope_position.dec.radian], [ SkyCoord(first_field['hmsdms']).ra.radian, SkyCoord(first_field['hmsdms']).dec.radian ]) if slew_seconds < targ_wait * 60.: new_obstime_utc = obstime_utc + datetime.timedelta( minutes=targ_wait) else: new_obstime_utc = obstime_utc + datetime.timedelta( seconds=slew_seconds) after_target = observe_target(apertif_fields, new_obstime_utc, first_field['name'], obstime=11.5) write_to_csv(csvfile, first_field['name'], SkyCoord(first_field['hmsdms']), new_obstime_utc, after_target) print("Scan {} observed {}.".format(i, first_field['hmsdms'])) return i, after_target, SkyCoord(first_field['hmsdms']), total_wait else: print("\tNo target for {} hours. Go to a calibrator instead.".format( targ_wait / 60.)) print( "\tNo target for {} hours. NEED TO EXPAND TARGET OPTIONS AND RERUN!" .format(targ_wait / 60.)) return i, obstime_utc + datetime.timedelta( days=100), telescope_position, total_wait
def main(): args = parse_args() np.warnings.filterwarnings('ignore') # Find calibrator position calib = SkyCoord.from_name(args.calibname) # Put all the output from drift_scan_auto_corr.ipynb in a unique folder per source, per set of drift scans. datafiles = glob(args.root + '*exported_data.csv') datafiles.sort() posfiles = glob(args.root + '*hadec.csv') posfiles.sort() # Put calibrator into apparent coordinates (because that is what the telescope observes it in.) test = calib.transform_to('fk5') calibnow = test.transform_to(FK5(equinox='J{}'.format(taskid2equinox(args.taskid)))) corr_im = [] diff_im = [] for beam in range(40): print(beam, end=' ') # Create the vectors which contain all data from all scans for a given beam which has been specified above. x, y, z_xx, z_yy = [], [], [], [] for file, pos in zip(datafiles, posfiles): data = Table.read(file, format='csv') hadec = Table.read(pos, format='csv') hadec_start = SkyCoord(ra=hadec['ha'], dec=hadec['dec'], unit=(u.rad, u.rad)) # From ALTA (same as above) time_mjd = Time(data['time'] / (3600 * 24), format='mjd') lst = time_mjd.sidereal_time('apparent', westerbork().lon) HAcal = lst - calibnow.ra # in sky coords dHAsky = HAcal - hadec_start[beam].ra + (24 * u.hourangle) # in sky coords in hours dHAsky.wrap_at('180d', inplace=True) dHAphys = dHAsky * np.cos(hadec_start[beam].dec.deg * u.deg) # physical offset in hours x = np.append(x, dHAphys.deg) y = np.append(y, np.full(len(dHAphys.deg), hadec_start[beam].dec.deg)) z_xx = np.append(z_xx, data['auto_corr_beam_' + str(beam) + '_xx'] - np.median( data['auto_corr_beam_' + str(beam) + '_xx'])) z_yy = np.append(z_yy, data['auto_corr_beam_' + str(beam) + '_yy'] - np.median( data['auto_corr_beam_' + str(beam) + '_yy'])) # # Add a fake drift that goes to zero power at 1 deg above last scan # x=np.append(x,dHAphys.deg) # y=np.append(y,np.full(len(dHAphys.deg),max(y)+1.0)) # z_xx=np.append(z_xx,np.full(len(dHAphys.deg),1)) # z_yy=np.append(z_yy,np.full(len(dHAphys.deg),1)) # # Add a fake drift that goes to zero power at 1 deg below first scan # x=np.append(x,dHAphys.deg) # y=np.append(y,np.full(len(dHAphys.deg),min(y)-1.0)) # z_xx=np.append(z_xx,np.full(len(dHAphys.deg),1)) # z_yy=np.append(z_yy,np.full(len(dHAphys.deg),1)) # Create the 2D grid and do a cubic interpolation cell_size = 105. / 3600. tx = np.arange(min(x), max(x), cell_size) ty = np.arange(min(y), max(y), cell_size) XI, YI = np.meshgrid(tx, ty) gridcubx = interpolate.griddata((x, y), z_xx, (XI, YI), method='cubic') # median already subtracted gridcuby = interpolate.griddata((x, y), z_yy, (XI, YI), method='cubic') # Find the reference pixel at the apparent coordinates of the calibrator ref_pixy = (calibnow.dec.deg - min(y)) / cell_size ref_pixx = (-min(x)) / cell_size # Find the peak of the primary beam to normalize norm_xx = np.max(gridcubx[int(ref_pixy)-3:int(ref_pixy)+4, int(ref_pixx)-3:int(ref_pixx)+4]) norm_yy = np.max(gridcuby[int(ref_pixy) - 3:int(ref_pixy) + 4, int(ref_pixx) - 3:int(ref_pixx) + 4]) if beam == 0: norm0_xx = np.max(gridcubx[int(ref_pixy) - 3:int(ref_pixy) + 4, int(ref_pixx) - 3:int(ref_pixx) + 4]) norm0_yy = np.max(gridcuby[int(ref_pixy) - 3:int(ref_pixy) + 4, int(ref_pixx) - 3:int(ref_pixx) + 4]) # Convert to decibels db_xx = np.log10(gridcubx/norm_xx) * 10. db_yy = np.log10(gridcuby/norm_yy) * 10. # db0_xx = np.log10(gridcubx/norm0_xx) * 10. # db0_yy = np.log10(gridcuby/norm0_yy) * 10. wcs = WCS(naxis=2) wcs.wcs.cdelt = np.array([-cell_size, cell_size]) wcs.wcs.ctype = ['RA---TAN', 'DEC--TAN'] wcs.wcs.crval = [calib.ra.to_value(u.deg), calib.dec.to_value(u.deg)] wcs.wcs.crpix = [ref_pixx, ref_pixy] header = wcs.to_header() hdux_db = fits.PrimaryHDU(db_xx, header=header) hduy_db = fits.PrimaryHDU(db_yy, header=header) hdux = fits.PrimaryHDU(gridcubx/norm_xx, header=header) hduy = fits.PrimaryHDU(gridcuby/norm_yy, header=header) # hdulx = fits.HDUList([hdux]) # hduly = fits.HDUList([hduy]) # Save the FITS files hdux_db.writeto(args.root + '{}_{}_{:02}xx_db.fits'.format(args.calibname.replace(" ", ""), args.taskid[:-3], beam), overwrite=True) hduy_db.writeto(args.root + '{}_{}_{:02}yy_db.fits'.format(args.calibname.replace(" ", ""), args.taskid[:-3], beam), overwrite=True) hdux.writeto(args.root + '{}_{}_{:02}xx.fits'.format(args.calibname.replace(" ", ""), args.taskid[:-3], beam), overwrite=True) hduy.writeto(args.root + '{}_{}_{:02}yy.fits'.format(args.calibname.replace(" ", ""), args.taskid[:-3], beam), overwrite=True) fig1 = plt.figure(figsize=(6, 9)) ax1 = fig1.add_subplot(2, 1, 1, projection=wcs.celestial) ax1.grid(lw=1, color='white') ax1.set_title("Beam {:02} - XX Correlation - Cubic".format(beam)) ax1.set_ylabel("Declination [J2000]") ax1.set_xlabel("Right Ascension [J2000]") im1 = ax1.imshow(gridcubx/norm0_xx, vmax=0.10, vmin=-0.03, cmap='magma', animated=True) ax2 = fig1.add_subplot(2, 1, 2, projection=wcs.celestial) ax2.grid(lw=1, color='white') ax2.set_title("Beam {:02} - YY Correlation - Cubic".format(beam)) ax2.set_ylabel("Declination [J2000]") ax2.set_xlabel("Right Ascension [J2000]") im2 = ax2.imshow(gridcuby/norm0_yy, vmax=0.10, vmin=-0.03, cmap='magma', animated=True) corr_im.append([im1, im2]) plt.savefig(args.root + '{}_{}_{:02}db0_reconstructed.png'.format(args.calibname.replace(" ", ""), args.taskid, beam)) plt.close('all') # Plot the difference between XX and YY for every beam diffcub = gridcubx/norm_xx - gridcuby/norm_yy fig2 = plt.figure(figsize=(10, 9)) ax1 = fig2.add_subplot(1, 1, 1, projection=wcs.celestial) ax1.grid(lw=1, color='white') ax1.set_title("Beam {:02} - Difference (XX$-$YY)".format(beam)) ax1.set_ylabel("Declination [J2000]") ax1.set_xlabel("Right Ascension [J2000]") ax1.scatter(ref_pixx, ref_pixy, marker='x', color='black') im3 = ax1.imshow(diffcub, vmin=-0.1, vmax=0.1) plt.colorbar(im3) diff_im.append([im3]) plt.savefig(args.root + '{}_{}_{:02}_difference.png'.format(args.calibname.replace(" ", ""), args.taskid, beam)) plt.close('all') if args.make_gifs: make_gifs(args.root)