def riseset(self, crd, ev="5deg"): a = self.rise(crd, ev) if isinstance(a, str): a = a.split() return { "rise": { "last": a[0], "utc": a[0] }, "set" : { "last": a[1], "utc": a[1] }, "solved": False } ofe = self.measure(self._framestack["epoch"], "utc") if not is_measure(ofe): ofe = self.epoch('utc', 'today') x = a.copy() for k in x.keys(): x[k] = self.measure(self.epoch("last", dq.totime(a[k]), off=self.epoch("r_utc", (dq.quantity(ofe["m0"]) + dq.quantity("0.5d")))), "utc") return { "rise": { "last": self.epoch("last", dq.totime(a["rise"])), "utc": x["rise"] }, "set": { "last": self.epoch("last", dq.totime(a["set"])), "utc": x["set"] }, "solved" : True }
def enu2itrf(self, antennas=None, lon=None, lat=None): """ Converts a list of ENU positions to ITRF positions. Requires a reference positions (lon,lat) in radians. Returns the ITRF reference position and the ITRF list of positions. """ dm = pyrap.measures.measures() antennas = self.antennas if antennas is None else antennas lon = lon or self.lon lat = lat or self.lat # convtert reference position to itrf system refpos_wgs84 = dm.position('wgs84', dq.quantity(lon, 'rad'), dq.quantity(lat, 'rad')) refpos = dm.measure(refpos_wgs84, 'itrf') lon,lat,rad = [ refpos[x]['value'] for x in 'm0 m1 m2'.split() ] xyz0 = rad*numpy.array( [math.cos(lat)*math.cos(lon), math.cos(lat)*math.sin(lon), math.sin(lat)]) # 3x3 transformation matrix. Each row is a normal vector, i.e the rows are (dE,dN,dU) xform = numpy.array([ [-math.sin(lon), math.cos(lon), 0], [-math.cos(lon)*math.sin(lat), -math.sin(lon)*math.sin(lat), math.cos(lat)], [math.cos(lat)*math.cos(lon), math.cos(lat)*math.sin(lon), math.sin(lat)] ]) antennas = numpy.array(antennas) xyz = xyz0[numpy.newaxis,:] + antennas.dot(xform) return xyz0,xyz
def get_time_range(start_time,end_time,timestep,time_in_sec,TIME_OFFSET=0): if HAS_PYRAP: try: start_time = qu.quantity(start_time).get_value() end_time = qu.quantity(end_time).get_value() print ('**** specified start and end time ', start_time, end_time) reference_time = start_time * 86400.0 - TIME_OFFSET st = reference_time - timestep et = end_time * 86400.0 + timestep + TIME_OFFSET #print "getting string",reference_time str_start_time = obtain_observation_year_month_day_hms(reference_time) timerange= [st, et] except: print ('no time range given') print ('exiting') return -1,-1,-1 elif HAS_EPHEM: if time_in_sec: dublin_start = start_time / 86400.0 -15019.5 dublin_end = end_time / 86400.0 -15019.5 start_time = ephem.julian_date(ephem.Date(dublin_start)) - 2400000.5 end_time = ephem.julian_date(ephem.Date(dublin_end)) - 2400000.5 else: start_time = ephem.julian_date(ephem.Date(start_time)) - 2400000.5 end_time = ephem.julian_date(ephem.Date(end_time)) - 2400000.5 print ('ephem start and end time ', start_time, end_time) reference_time = start_time * 86400.0 - TIME_OFFSET st = reference_time - timestep et = end_time * 86400.0 + timestep + TIME_OFFSET str_start_time = obtain_observation_year_month_day_hms(reference_time) timerange= [st, et] else: print ('unable to get time range so exiting!') return -1,-1,-1 return timerange,str_start_time,reference_time
def print_facet_centre_list(facet_centres, num_facet_centres): if num_facet_centres != 0: print "REQUESTED FACET CENTRES:" for i, c in enumerate(facet_centres): print "\tFACET %d RA: %s DEC: %s" % ( i, quantity(c[0], "arcsec").get("deg"), quantity(c[1], "arcsec").get("deg"), )
def direction(self, rf='', v0='0..', v1='90..', off=False): loc = { 'type': 'direction' , 'refer': rf} loc['m0'] = dq.quantity(v0) loc['m1'] = dq.quantity(v1) if is_measure(off): if not off['type'] == "direction": raise TypeError('Illegal offset type specified.') loc["offset"] = off return self.measure(loc, rf)
def get_elev(t,ra,dec): pointing_s = me.direction('SUN') pointing_o = me.direction('j2000',qa.quantity(ra,'deg'),qa.quantity(dec,'deg')) tt = qa.quantity(t,'d') tt1 = me.epoch('utc',tt) me.doframe(tt1) obj_elev = me.measure(pointing_o,'azel')['m1']['value']*180/np.pi sun_elev = me.measure(pointing_s,'azel')['m1']['value']*180/np.pi return obj_elev, sun_elev
def earthmagnetic(self, rf='', v0='0G', v1='0..', v2='90..', off=False): loc = { 'type': "earthmagnetic", 'refer': rf } loc['m0'] = dq.quantity(v0) loc['m1'] = dq.quantity(v1) loc['m2'] = dq.quantity(v2) if is_measure(off): if not off['type'] == "earthmagnetic": raise TypeError('Illegal offset type specified.') loc["offset"] = off return self.measure(loc, rf)
def todoppler(self, rf, v0, rfq=False): if is_measure(rfq) and rfq['type'] == 'frequency': rfq = dq.from_dict(rfq['m0']) if is_measure(v0): if v0['type'] == 'radialvelocity': return self.todop(v0, dq.to_dict(dq.quantity(1.,'Hz'))) elif v0['type'] == 'frequency' and isinstance(rfq, dq._quanta.Quantity) \ and rfq.conforms(dq.quantity('Hz')): return self.todop(v0, dq.to_dict(rfq)) else: raise TypeError('Illegal Doppler or rest frequency specified') else: raise TypeError('Illegal Frequency specified')
def parallactic_angles(times, antenna_positions, field_centre): """ Computes parallactic angles per timestep for the given reference antenna position and field centre. Arguments: times: ndarray Array of unique times with shape (ntime,), obtained from TIME column of MS table antenna_positions: ndarray of shape (na, 3) Antenna positions, obtained from POSITION column of MS ANTENNA sub-table field_centre : ndarray of shape (2,) Field centre, should be obtained from MS PHASE_DIR Returns: An array of parallactic angles per time-step """ import pyrap.quanta as pq try: # Create direction measure for the zenith zenith = pm.direction('AZEL','0deg','90deg') except AttributeError as e: if pm is None: raise ImportError("python-casacore import failed") raise # Create position measures for each antenna reference_positions = [pm.position('itrf', *(pq.quantity(x,'m') for x in pos)) for pos in antenna_positions] # Compute field centre in radians fc_rad = pm.direction('J2000', *(pq.quantity(f,'rad') for f in field_centre)) return np.asarray([ # Set current time as the reference frame pm.do_frame(pm.epoch("UTC", pq.quantity(t, "s"))) and [ # Set antenna position as the reference frame pm.do_frame(rp) and pm.posangle(fc_rad, zenith).get_value("rad") for rp in reference_positions ] for t in times])
def parallactic_angles(field_centre, antenna_positions, times): """ Computes parallactic angles per timestep for the given reference antenna position and field centre. Arguments: field_centre : ndarray of shape (2,) Field centre, should be obtained from MS PHASE_DIR antenna_positions: ndarray of shape (na, 3) Antenna positions, obtained from POSITION column of MS ANTENNA sub-table times: ndarray Array of unique times with shape (ntime,), obtained from TIME column of MS table Returns: An array of parallactic angles per time-step """ import pyrap.measures import pyrap.quanta as pq pm = pyrap.measures.measures() ntime = times.shape[0] na = antenna_positions.shape[0] # Create direction measure for the zenith zenith = pm.direction('AZEL','0deg','90deg') # Create position measures for each antenna reference_positions = [pm.position('itrf', *(pq.quantity(x,'m') for x in pos)) for pos in antenna_positions] # Compute field centre in radians fc_rad = pm.direction('J2000', *(pq.quantity(f,'rad') for f in field_centre)) parallactic_angles = np.asarray([ # Set antenna position as the reference frame pm.do_frame(rp) and # Set current time as the reference frame pm.do_frame(pm.epoch("UTC",pq.quantity(t,"s"))) and # Now compute the parallactic angle pm.posangle(fc_rad, zenith).get_value("rad") for t in times for rp in reference_positions]) return parallactic_angles.reshape(ntime, na)
def on_mouse_move(self,widget,event): if self._low_res_image != None: sbrMain = self._builder.get_object("sbrMain") sbrMain.remove_all(sbrMain.get_context_id("CursorPos")) handle = self._builder.get_object("cvsLowRes") handle.queue_draw() rect = handle.get_allocation() img_height = self._low_res_image.get_height() img_width = self._low_res_image.get_width() self._l_pos = int(event.x/float(rect.width) * img_width) self._m_pos = int(event.y/float(rect.height) * img_height) sbrMain.push(sbrMain.get_context_id("CursorPos"),"Pixel position: (x,y) = (%d,%d), (ra,dec) = (%s,%s)" % (self._l_pos, self._m_pos, quantity(quantity(self._phase_centres[self._field_id,0,0],"rad").get_value("arcsec") + (-self._l_pos + img_width/2)*self._img_cell_l,"arcsec").get("deg").formatted("[+-]dd.mm.ss.t.."), quantity(quantity(self._phase_centres[self._field_id,0,1],"rad").get_value("arcsec") + (-self._m_pos + img_height/2)*self._img_cell_m,"arcsec").get("deg").formatted("[+-]dd.mm.ss.t..")))
def printJones(stnName,obsTimes,srcDir,freqs,model): print "Frequency","Time","J00","J01","J10","J11" for freq in freqs: Jn=getJonesByAntFld(model,obsTimes,stnName,srcDir,freq) #plotJonesGnuplot(quantity(obsTimes.get_value()[0],obsTimes.get_unit()).formatted("YMD"),stepTime.seconds,Jn) for ti in range(0,len(obsTimes.get_value() )): print freq, quantity(obsTimes.get_value()[ti],obsTimes.get_unit()).formatted("YMD"), Jn[ti,0,0], Jn[ti,0,1],Jn[ti,1,0],Jn[ti,1,1]
def plotJones(stnName,obsTimes,freqs): #frequencys=np.linspace(0,100e6,512) #freqs=frequencys[150:350] timespy=[datetime.fromtimestamp(quantity(t,'d').to_unix_time()) for t in obsTimes.get_value()] freq=freqs[0] Jn=getJonesByAntFld(model,obsTimes,stnName,srcDir,freq) p_ch = np.abs(Jn[:,0,0].squeeze())**2+np.abs(Jn[:,0,1].squeeze())**2 q_ch = np.abs(Jn[:,1,1].squeeze())**2+np.abs(Jn[:,1,0].squeeze())**2 #For testing purposes: #p_ch = np.real(Jn[:,0,1].squeeze()) #q_ch = np.real(Jn[:,0,1].squeeze()) #In dB: p_ch = 10*np.log10(p_ch) q_ch = 10*np.log10(q_ch) plt.figure() plt.subplot(211) plt.plot(timespy, p_ch) plt.title('p channel') #plt.clim(-9, -3) plt.subplot(212) plt.plot(timespy, q_ch) plt.title('q-channel') #plt.clim(-9, -3) plt.xlabel('Time') plt.show()
def updateMSmetadata(msfile): #Update history to show that this script has modified original data tms = pt.table(msfile,readonly=False,ack=False) th = pt.table(tms.getkeyword('HISTORY'), readonly=False, ack=False) nr=th.nrows() th.addrows(1) tr=th.row() tr.put(nr,{'TIME': quantity('today').get('s').get_value(), 'OBSERVATION_ID':0, 'MESSAGE': 'Applied polarization modifications', 'PRIORITY': 'NORMAL', 'ORIGIN': '%s: version = %s' % (__file__,__version__), 'OBJECT_ID':0, 'APPLICATION':__file__, 'CLI_COMMAND':sys.argv, 'APP_PARAMS': ['']}) if not options.linear: #Change metadata information to be circular feeds feed = pt.table(tms.getkeyword('FEED'),readonly=False,ack=False) for tpart in feed.iter('ANTENNA_ID'): tpart.putcell('POLARIZATION_TYPE',0,['R','L']) polariz = pt.table(tms.getkeyword('POLARIZATION'),readonly=False,ack=False) polariz.putcell('CORR_TYPE',0,[5,6,7,8]) tms.close()
def insert_grid_points(survey, filename, calibrator=False): with open(filename, 'r') as f: lines = f.readlines() for line in lines: split_string = line.split(None, 3) name = split_string[0] ra = quantity(split_string[1]).get_value('rad') dec = quantity(split_string[2].replace(":", ".", 2)).get_value('rad') if len(split_string) == 4: description = split_string[3].strip() else: description = "" f = Field.objects.create( name=name, ra=ra, dec=dec, description=description, survey=survey, calibrator=calibrator )
def epoch(self, rf='', v0='0.0d', off=False): loc = { 'type': 'epoch' , 'refer': rf} loc['m0'] = dq.quantity(v0) if is_measure(off): if not off['type'] == "epoch": raise TypeError('Illegal offset type specified.') loc["offset"] = off return self.measure(loc, rf)
def tofrequency(self, rf, v0, rfq): if is_measure(rfq) and rfq['type'] == 'frequency': rfq = dq.from_dict(rfq['m0']) if is_measure(v0) and v0['type'] == 'doppler' \ and isinstance(rfq, dq._quanta.Quantity) \ and rfq.conforms(dq.quantity('Hz')): return self.doptofreq(v0, rf, dq.to_dict(rfq)) else: raise TypeError('Illegal Doppler or rest frequency specified')
def GiveStrDate(tt): time_start = qa.quantity(tt, 's') me = pm.measures() dict_time_start_MDJ = me.epoch('utc', time_start) time_start_MDJ=dict_time_start_MDJ['m0']['value'] JD=time_start_MDJ+2400000.5-2415020 d=ephem.Date(JD) return d.datetime().isoformat().replace("T","/")
def doppler(self, rf='', v0='0', off=False): loc = { 'type': "doppler", 'refer': rf, 'm0': dq.quantity(v0) } if is_measure(off): if not off['type'] == "doppler": raise TypeError('Illegal offset type specified.') loc["offset"] = off return self.measure(loc, rf)
def on_click(self,widget,event): if self._busy_loading: message = Gtk.MessageDialog(self._builder.get_object("frmMain"),0,Gtk.MessageType.INFO,Gtk.ButtonsType.OK,"Busy synthesizing low res image... please hang on") message.run() message.destroy() return if self._busy_faceting: message = Gtk.MessageDialog(self._builder.get_object("frmMain"),0,Gtk.MessageType.INFO,Gtk.ButtonsType.OK,"Already busy faceting... please hang on") message.run() message.destroy() return if self._low_res_image != None: self._busy_faceting = True self._builder.get_object("cvsLowRes").queue_draw() self.__change_visibilities() model = self._builder.get_object("lstFacetingProperties") itr = model.get_iter(0) facet_size_l = int(model.get_value(itr,1)) itr = model.iter_next(itr) facet_size_m = int(model.get_value(itr,1)) itr = model.iter_next(itr) facet_cell_l = float(model.get_value(itr,1)) itr = model.iter_next(itr) facet_cell_m = float(model.get_value(itr,1)) itr = model.iter_next(itr) conv_support = int(model.get_value(itr,1)) itr = model.iter_next(itr) conv_oversample = int(model.get_value(itr,1)) rect = self._builder.get_object("cvsLowRes").get_allocation() img_height = self._low_res_image.get_height() img_width = self._low_res_image.get_width() facet_ra = quantity(self._phase_centres[self._field_id,0,0],"rad").get_value("arcsec") + (-int(event.x/float(rect.width) * img_width) + img_width/2)*self._img_cell_l facet_dec = quantity(self._phase_centres[self._field_id,0,1],"rad").get_value("arcsec") + (-int(event.y/float(rect.height) * img_height) + img_height/2)*self._img_cell_m facet_centres = np.array([[facet_ra,facet_dec]],dtype=np.float32) cmd_string = ("python bullseye.py \"%s\" --output_prefix \"%s\" --output_format png --npix_l %d --npix_m %d --cell_l %d" " --cell_m %d --pol %s --conv_sup %d --conv_oversamp %d --facet_centres \(%f,%f\) --field_id %d --average_all 1" % ( self._ms_name,self.FACET_TMP_FILE_NAME,facet_size_l,facet_size_m,facet_cell_l, facet_cell_m,self._polarization,conv_support,conv_oversample, int(facet_ra),int(facet_dec),self._field_id)) threading.Thread(target=self.cmd_call,args=(cmd_string,self.on_finished_faceting)).start()
def updatehistory(outms): """ Update history to show that this script has modified original data """ tc = pt.table(outms,readonly=False) th = pt.table(tc.getkeyword('HISTORY'), readonly=False, ack=False) nr=th.nrows() th.addrows(1) tr=th.row() tr.put(nr,{'TIME': quantity('today').get('s').get_value(), 'OBSERVATION_ID':0,'MESSAGE': ' ', 'PRIORITY': ' ', 'ORIGIN': ' ','OBJECT_ID':0, 'APPLICATION':'mslin2circ','CLI_COMMAND':[''],'APP_PARAMS': ['']})
def getvalue(self, v): if not is_measure(v): raise TypeError('Incorrect input type for getvalue()') import re rx = re.compile("m\d+") out = [] v.keys().sort() for key in v.keys(): if re.match(rx, key): out.append(dq.quantity(v.get(key))) return out
def rise(self, crd, ev='5deg'): if not is_measure(crd): raise TypeError('No rise/set coordinates specified') ps = self._getwhere() self._fillnow() hd = self.measure(crd, "hadec") c = self.measure(crd, "app") evq = dq.quantity(ev) hdm1 = dq.from_dict(hd["m1"]) psm1 = dq.from_dict(ps["m1"]) ct = (dq.quantity(ev) - dq.sin(hdm1) * dq.sin(psm1)) / (dq.cos(hdm1) * dq.cos(psm1)) if ct.get_value() >= 1: return "below below" if ct.get_value() <= -1: return "above above" a = dq.acos(ct) return { "rise": dq.norm(dq.quantity(c["m0"]), 0) - a, "set" : dq.norm(dq.quantity(c["m0"]), 0) + a }
def checkintervals(mss): """Checks the intervals of each measurement set""" intervals=[] print("Measurement Set\t\t\tTime Interval\t\tStart\t\tEnd") print("-----------------------------------------------------------------------------------------------") for i in mss: temp=pt.table(i, ack=False) t=temp.getcol('INTERVAL')[0] intervals.append(t) temp.close() #Open table again to get start and end tomes temp=pt.table(i, ack=False) tempst,tempend=temp.getcol("TIME")[[0,-1]] print("{0}\t{1}s\t{2}\t{3}".format(i, t, datetime.utcfromtimestamp(quantity('{0}s'.format(tempst)).to_unix_time()), datetime.utcfromtimestamp(quantity('{0}s'.format(tempend)).to_unix_time()))) intervals=np.array(intervals) uniq=np.unique(intervals) if len(uniq) > 1: return False, uniq else: return True, uniq
def printJones(args,model): stnName=args[0] bTime = datetime.strptime(args[1], "%Y-%m-%d %H:%M:%S") duration =timedelta(0,float(args[2])) stepTime =timedelta(0,float(args[3])) ra=args[4]+'rad' dec=args[5]+'rad' freq=args[6] eTime = bTime+duration Times=[] for ti in range(0,duration.seconds/stepTime.seconds): Times.append( (quantity((bTime+ti*stepTime).isoformat())).get_value() ) #obsTimes.append(beginTime+ti*stepTime) obsTimes=quantity(Times,'d') srcDir=measures().direction('J2000', ra,dec) Jn=getJonesByAntFld(model,obsTimes,stnName,srcDir,freq) #plotJonesGnuplot(quantity(obsTimes.get_value()[0],obsTimes.get_unit()).formatted("YMD"),stepTime.seconds,Jn) for ti in range(0,duration.seconds/stepTime.seconds): print obsTimes.get_value()[ti],Jn[ti,0,0].real,Jn[ti,0,0].imag,Jn[ti,0,1].real,Jn[ti,0,1].imag,Jn[ti,1,0].real,Jn[ti,1,0].imag,Jn[ti,1,1].real,Jn[ti,1,1].imag
def getAzEl(pointing,time,position,ha_limit=-1000): if HAS_PYRAP: if ha_limit==-1000: azel=radec2azel(pointing[0],pointing[1],time=str(time)+'s',pos=position); az=azel['m0']['value'] el=azel['m1']['value'] else: me=measures() p=me.position("ITRF",str(position[0])+'m',str(position[1])+'m',str(position[2])+'m') t=me.epoch("UTC",qu.quantity(str(time)+'s')) phasedir=me.direction('J2000',str(pointing[0])+'rad',str(pointing[1])+'rad') me.doframe(p) me.doframe(t) hadec=me.measure(phasedir,"HADEC") if abs(hadec['m0']['value'])>ha_limit: print "below horizon",tab.taql('calc ctod($time s)')[0],degrees(hadec['m0']['value']),degrees(hadec['m1']['value']) return 999,999 else: azel=me.measure(phasedir,"AZEL") az=azel['m0']['value']; el=azel['m1']['value']; elif HAS_EPHEM: if ha_limit!=-1000: print "limiting on HA/DEC not implemented for PyEphem yet, ignoring" location_lat, location_lon, location_height = ITRFToWGS84(position[0], position[1], position[2]) location = ephem.Observer() # convert geodetic latitude to geocentric # flattening, f, defined above for WGS84 stuff geodet_lat = math.radians(location_lat) tan_geocentric_latitude = math.tan(geodet_lat) * (1 - f) **2 geocentric_latitude = GeodeticToGeocentricLat(geodet_lat, location_height) location.lat = geocentric_latitude location.lon = math.radians(location_lon) location.elevation = location_height location.pressure = 0.0 # convert to Dublin Julian Date for PyEphem location.date = time/86400.0 - 15019.5 lst = location.sidereal_time() equatorial = ephem.Equatorial(str(12.0 * math.degrees(pointing[0])/180),str(math.degrees(pointing[1]))) body = ephem.FixedBody() body._ra = equatorial.ra body._dec = equatorial.dec body._epoch = equatorial.epoch body.compute(location) az = math.degrees(body.az) * math.pi / 180.0 el = math.degrees(body.alt) * math.pi / 180.0 else: print ('failure to get azimuth and elevation! Exiting!') return -1,-1 return az,el
def obtain_observation_year_month_day_hms(start_time): if HAS_PYRAP: #print "getting time", str(start_time)+'s' date_list = qu.quantity(str(start_time)+'s').formatted("YMD").split("/") year = int(date_list[0]) month = int(date_list[1]) day = int(date_list[2]) time_list=date_list[3].split(":") return (year, month, day,int(time_list[0]),int(time_list[1]),float(time_list[2])) else: julian_day = (start_time / 86400.0) + 2400000.5 year, month, day, hour, minute, second = get_ymdh_from_JD(julian_day) return (year, month, day,hour, minute, second)
def init_times(self): if not list(self.direction): print "cannot init, set direction first" if not list(self.times): print "cannot init, set times first" self.delayxyz=[[] for i in self.direction] self.phasexyz=[[] for i in self.direction] self.k=[[] for i in self.direction] for ist in range(self.stationcenter.shape[0]): print "getting station",ist,"from",self.stationcenter.shape[0] for i in range(len(self.direction)): self.delayxyz[i].append([]) self.phasexyz[i].append([]) self.k[i].append([]) pos=self.stationcenter[ist] p = me.position('ITRF',str(pos[0])+'m',str(pos[1])+'m',str(pos[2])+'m') me.do_frame(p); ra=str(self.refdir[0])+'rad' dec=str(self.refdir[1])+'rad' phasedir=me.direction('J2000',ra,dec) delaydir=[] for idir,dir in enumerate(self.direction): ra=str(dir[0])+'rad' dec=str(dir[1])+'rad' delaydir.append(me.direction('J2000',ra,dec)) for itm,time in enumerate(self.times): t=me.epoch("UTC",qa.quantity(str(time)+'s')) me.do_frame(t) itrfdir = me.measure(phasedir,'ITRF') coslon=np.cos(itrfdir['m0']['value']) coslat=np.cos(itrfdir['m1']['value']) sinlon=np.sin(itrfdir['m0']['value']) sinlat=np.sin(itrfdir['m1']['value']) phasexyz=np.array([coslat*coslon,coslat*sinlon,sinlat]) for idir,dir in enumerate(self.direction): itrfdelaydir = me.measure(delaydir[idir],'ITRF') coslon=np.cos(itrfdelaydir['m0']['value']) coslat=np.cos(itrfdelaydir['m1']['value']) sinlon=np.sin(itrfdelaydir['m0']['value']) sinlat=np.sin(itrfdelaydir['m1']['value']) delayxyz=np.array([coslat*coslon,coslat*sinlon,sinlat]) k=delayxyz-phasexyz self.delayxyz[idir][-1].append(delayxyz) self.phasexyz[idir][-1].append(phasexyz) self.k[idir][-1].append(k) self.delayxyz=np.array(self.delayxyz) self.phasexyz=np.array(self.phasexyz) self.k=np.array(self.k) self.initiated=True
def azel2radec(az,el,time, pos): me=measures(); if type(az)!=str: az=str(az)+'rad'; if type(el)!=str: el=str(el)+'rad'; phasedir=me.direction('AZEL',az,el) t=me.epoch("UTC",qu.quantity(time)); me.do_frame(t); p = me.position('ITRF',str(pos[0])+'m',str(pos[1])+'m',str(pos[2])+'m') me.do_frame(p); radec = me.measure(phasedir,'RADEC'); return radec;
def radec2azel(ra,dec,time, pos): me=measures(); if type(ra)!=str: ra=str(ra)+'rad'; if type(dec)!=str: dec=str(dec)+'rad'; phasedir=me.direction('J2000',ra,dec) t=me.epoch("UTC",qu.quantity(time)); me.do_frame(t); p = me.position('ITRF',str(pos[0])+'m',str(pos[1])+'m',str(pos[2])+'m') me.do_frame(p); azel = me.measure(phasedir,'azel'); return azel;
ax = fig.add_subplot(111) ax.set_xlabel(r'Time [day]') # toplabel in months #ax.set_(r'') types = np.dtype({ 'names': ['name', 'ra', 'dec'], 'formats': ['S100', 'S100', 'S100'] }) data = np.loadtxt(sys.argv[1], comments='#', usecols=(0, 1, 2), unpack=False, dtype=types) me = pm.measures() position = me.position('wgs84', qa.quantity(3826600.961, 'm'), qa.quantity(460953.402, 'm'), qa.quantity(5064881.136, 'm')) # superterp me.doframe(position) y = 1 for obj in data: print("Work on: ", obj['name']) rah, ram, ras = obj['ra'].split(':') ra = cm.hmstora(float(rah), float(ram), float(ras)) # in deg decd, decm, decs = obj['dec'].split(':') dec = cm.dmstodec(float(decd), float(decm), float(decs)) # in deg for d in range(360): # count how many h the source is at elev>30 when sun is at elev<0 observable = 0 for h in range(24):
def __init__(self, parameters): print "\033[94mPython MyATerm constructor\033[0m" print parameters.keys() #self.img = pyrap.images.image('beam.img').getdata()[0,0,:,:] # Read the necessary parameters from the parameterset. ms = str(parameters["ms"]) beamname = str(parameters['beamname']) support = int(str(parameters['SpheSupport'])) print "Reading beam patterns with prefix: ", beamname # 8 FITS files (4 pol each for real & imag parts) per station per frequency # HDUs are ordered as xx_re, xx_im, xy_re, xy_im, yx_re, yx_im, yy_re, yy_im hdulist = [] # Holds all the images for one station for pol in ['_xx', '_xy', '_yx', '_yy']: for comp in ['_re', '_im']: temphdu = pyfits.open(beamname + pol + comp + '.fits')[0] # Extract the first HDU hdulist.append(temphdu) # Get the frequency range from the FITS header. hdu0 = hdulist[0] nfreq = hdu0.header['NAXIS3'] dim = float(hdu0.header['NAXIS1']) # Assume this is a square image. self.Im_per_station = 8 self.pa_step = 5 # Expose this as a parameter to the user. self.freqlist = [] # in Hertz if 'GFREQ1' in hdu0.header: for keyindex in range(1, nfreq + 1): self.freqlist.append(hdu0.header['GFREQ%i' % keyindex]) else: #for keyindex in range(1,nfreq+1): #self.freqlist.append( pass # Compute a set of angles by which the beams need to be rotated every timestamp. dm = measures() field = 0 # this is used as the FIELD_ID - assume this to be zero for now; this is the field whose observed times we need from the MS. zenith = dm.direction('AZEL', '0deg', '90deg') tab = pt.table('TEST.MS') antpos = pt.table(tab.getkeyword("ANTENNA")).getcol("POSITION") ra, dec = pt.table(tab.getkeyword("FIELD")).getcol( "PHASE_DIR", field, 1)[0][0] # make position measure from antenna 0 pos0 = dm.position('itrf', *[dq.quantity(x, 'm') for x in antpos[0]]) dm.do_frame(pos0) # make direction measure from field centre fld = dm.direction('J2000', dq.quantity(ra, "rad"), dq.quantity(dec, "rad")) tab = tab.query("FIELD_ID==%d" % field) # get unique times times = numpy.array( sorted(set(tab.getcol("TIME")[~tab.getcol("FLAG_ROW")]))) pa_times = [(dm.do_frame(dm.epoch("UTC", dq.quantity(t, "s"))) and (dm.posangle(fld, zenith).get_value("deg"), t)) for t in times] pa_times = sorted(pa_times) start_pa = pa_times[0][0] pa_filtered = [pa_times[0]] for tup in pa_times: if tup[0] - start_pa < self.pa_step: continue pa_filtered.append(tup) start_pa = tup[0] print pa_filtered # Downsample / Interpolate (upsample?) the beam patterns to the support function size. import time t1 = time.time() print 'Start time: ', t1 self.beams = [] '''for polcomp in range(0,self.Im_per_station): for freq in range(0,nfreq): hdulist[polcomp].data[freq,:,:] = scipy.ndimage.zoom(hdulist[polcomp].data[freq,:,:] tempbeam = hdulist[polcomp].data[freq,:,:] #print tempbeam.shape temprotbeam = scipy.ndimage.rotate(tempbeam,p_angles[i]) #print "Temprotbeam dimensions: ", temprotbeam.shape aterms[polcomp,freq,:,:]= scipy.ndimage.zoom(temprotbeam,support/float(temprotbeam.shape[0]))''' self.times_filtered = [] for pa_t in pa_filtered: print "pa_t: ", pa_t print "printed" aterms = numpy.zeros( (self.Im_per_station, nfreq, support, support)) for polcomp in range(0, self.Im_per_station): for freq in range(0, nfreq): tempbeam = hdulist[polcomp].data[freq, :, :] temprotbeam = tempbeam #scipy.ndimage.rotate(tempbeam,pa_t[0]) aterms[polcomp, freq, :, :] = temprotbeam[ 0:support, 0: support] #scipy.ndimage.zoom(temprotbeam,support/float(temprotbeam.shape[0])) self.beams.append((pa_t[1], aterms)) self.times_filtered.append(pa_t[1]) t2 = time.time() print 'Stop time: ', t2 print "Time to pre-compute a-terms: ", (t2 - t1) / 60.0, " minutes."
# # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # #usage: extractbeam.py imagename import pyrap.images as pim from pyrap import quanta import sys for img in sys.argv[1:]: this_pim = pim.image(img) info_dict = this_pim.info()['imageinfo']['restoringbeam'] # get beam info bpar_ma = quanta.quantity(info_dict['major']).get_value('arcsec') bpar_mi = quanta.quantity(info_dict['minor']).get_value('arcsec') bpar_pa = quanta.quantity(info_dict['positionangle']).get_value('deg') print '\n{0} - Beam: maj {1:0.3f} (arcsec), min {2:2.3f} (arcsec), pa {3:0.2f} (deg)'.format( img, bpar_ma, bpar_mi, bpar_pa)
def main(ms_input, min_separation = 30, outputimage = None): """ Print seperation of the phase reference center of an input MS Parameters ---------- ms_input : str String from the list (map) of the calibrator MSs Returns ------- 0 --just for printing """ msname = input2strlist_nomapfile(ms_input)[0] # Create a measures object me = pm.measures() # Open the measurement set and the antenna and pointing table ms = pt.table(msname) # Get the position of the first antenna and set it as reference frame ant_table = pt.table(msname + '::ANTENNA') ant_no = 0 pos = ant_table.getcol('POSITION') x = qa.quantity( pos[ant_no,0], 'm' ) y = qa.quantity( pos[ant_no,1], 'm' ) z = qa.quantity( pos[ant_no,2], 'm' ) position = me.position( 'wgs84', x, y, z ) me.doframe( position ) ant_table.close() # Get the first pointing of the first antenna field_table = pt.table(msname + '::FIELD') field_no = 0 direction = field_table.getcol('PHASE_DIR') ra = direction[ ant_no, field_no, 0 ] dec = direction[ ant_no, field_no, 1 ] targets.insert(0, {'name' : 'Pointing', 'ra' : ra, 'dec' : dec}) field_table.close() # Get a ordered list of unique time stamps from the measurement set time_table = pt.taql('select TIME from $1 orderby distinct TIME', tables = [ms]) time = time_table.getcol('TIME') time1 = time/3600.0 time1 = time1 - pylab.floor(time1[0]/24)*24 ra_qa = qa.quantity( targets[0]['ra'], 'rad' ) dec_qa = qa.quantity( targets[0]['dec'], 'rad' ) pointing = me.direction('j2000', ra_qa, dec_qa) separations = [] print('SEPARATION from A-Team sources') print('------------------------------') print('The minimal accepted distance to an A-Team source is: ' + str(min_separation) + ' deg.') for target in targets: t = qa.quantity(time[0], 's') t1 = me.epoch('utc', t) me.doframe(t1) if 'ra' in target.keys(): ra_qa = qa.quantity( target['ra'], 'rad' ) dec_qa = qa.quantity( target['dec'], 'rad' ) direction = me.direction('j2000', ra_qa, dec_qa) else : direction = me.direction(target['name']) separations.append(me.separation(pointing, direction)) # Loop through all time stamps and calculate the elevation of the pointing el = [] for t in time: t_qa = qa.quantity(t, 's') t1 = me.epoch('utc', t_qa) me.doframe(t1) a = me.measure(direction, 'azel') elevation = a['m1'] el.append(elevation['value']/pylab.pi*180) el = numpy.array(el) pylab.plot(time1, el) if target['name'] != 'Pointing': print(target['name'] + ': ' + str(me.separation(pointing, direction))) if int(float(min_separation)) > int(float(str(me.separation(pointing, direction)).split(' deg')[0])): print('WARNING: The A-Team source ' + target['name'] + ' is closer than ' + str(min_separation) + ' deg to the phase reference center. Calibration might not perform as expected.') print('------------------------------') pylab.title('Pointing Elevation') pylab.title('Elevation') pylab.ylabel('Elevation (deg)'); pylab.xlabel('Time (h)'); pylab.legend( [ target['name'] + '(' + separation.to_string() + ')' for target, separation in zip(targets, separations) ]) if outputimage != None: inspection_directory = os.path.dirname(outputimage) if not os.path.exists(inspection_directory) and inspection_directory != '': os.makedirs(inspection_directory) print('Directory ' + inspection_directory + ' created.') elif inspection_directory != '': print('Directory ' + inspection_directory + ' already exists.') print('Plotting A-Team elevation to: ' + outputimage) pylab.savefig(outputimage) sys.exit(0)
def main(args): # Generate lists of input images and check that they exist images = [] avgpbs = [] psf_fwhm = [] # resolution frequency = [] # frequency of images (should be equal?) imagesbase = args.images.split(',') for base in imagesbase: images.append(base + '.' + args.extension) if not os.path.exists(images[-1]): print "Error: Image", images[-1], "does not exist" return 1 avgpbs.append(base + '.' + args.avgpbext) if not os.path.exists(avgpbs[-1]): print "Error: PB image", avgpbs[-1], "does not exist" return 1 # Collect weights and invert if requested if args.weights == '': weights = np.ones(len(images)) else: weights = np.array(args.weights.split(',')).astype('float') if args.invertwt: weights = 1. / weights if len(weights) != len(images): print "Error: List of weights is not the same length as list of images." return 1 print "Combining images" formstr = '{0:45s} {1:45s} {2:s} {3:s} {4:s} {5:s}' print formstr.format("-----", "--------", "------------", "-------", "-------", "------") print formstr.format("Image", "PB image", "Norm. weight", "Maj(ac)", "Min(ac)", "PA(deg)") print formstr.format("-----", "--------", "------------", "-------", "-------", "------") for i in range(len(images)): this_pim = pim.image(images[i]) info_dict = this_pim.info()['imageinfo']['restoringbeam'] # get beam info bpar_ma = quanta.quantity(info_dict['major']).get_value('deg') bpar_mi = quanta.quantity(info_dict['minor']).get_value('deg') bpar_pa = quanta.quantity(info_dict['positionangle']).get_value('deg') psf_fwhm.append([bpar_ma, bpar_mi, bpar_pa]) frequency.append( this_pim.info()['coordinates']['spectral2']['restfreq']) print '{0:45.45s} {1:45.45s} {2:0.2f} {3:0.2f} {4:0.2f} {5:0.2f}'.format( images[i], avgpbs[i], weights[i] / sum(weights), bpar_ma * 60, bpar_mi * 60, bpar_pa) psf_fwhm = np.array(psf_fwhm) frequency = np.array(frequency) mean_psf_fwhm = np.mean(psf_fwhm, axis=0) mean_frequency = np.mean(frequency) print '\nmean Beam: {0:0.3f} maj (arcmin), {1:2.3f} min (arcmin), {2:0.2f} pa (deg)'.format( mean_psf_fwhm[0] * 60, mean_psf_fwhm[1] * 60, mean_psf_fwhm[2]) print '(Frequency (MHz):', mean_frequency * 1e-6 if np.max(mean_frequency - frequency) / mean_frequency > 1e-6: print '\n\nWARNING.\nAre you using images from different bands?' print 'Frequencies (Hz):', frequency # Initialize some vectors declims = [] # store the limits of the declination axes ralims = [] # store the limits of the r.a. axes rainc = [] # store the r.a. increments in case they differ decinc = [] # store the dec increments in case they differ pims = [] # stores the pyrap images of the data ppbs = [] # stores the pyrap images of the pb images # Get image frames for input images for im, pb in zip(images, avgpbs): image = pim.image(im) sptcoords = image.coordinates().get_coordinate('spectral') nc = sptcoords.get_axis_size() assert (sptcoords.get_image_axis() == 0) # Get Stokes axis. Ensure we are working with the Stokes parameter requested. stkcoords = image.coordinates().get_coordinate('stokes') assert (stkcoords.get_image_axis() == 1) if stkcoords.get_axis_size() == 1: assert (stkcoords.get_stokes()[0] == args.stokes) else: stks = stkcoords.get_stokes().index(args.stokes) image = image.subimage(blc=(0, stks), trc=(nc - 1, stks), dropdegenerate=False) ns = 1 dircoords = image.coordinates().get_coordinate('direction') nx = dircoords.get_axis_size(axis=1) ny = dircoords.get_axis_size(axis=0) inc = dircoords.get_increment() ref = dircoords.get_referencepixel() val = dircoords.get_referencevalue() ra_axis = (range(nx) - ref[1]) * inc[1] + val[1] dec_axis = (range(ny) - ref[0]) * inc[0] + val[0] rainc.append(inc[1]) decinc.append(inc[0]) declims.append(min(dec_axis)) declims.append(max(dec_axis)) mean_ra = np.mean(ra_axis) ralims.append((min(ra_axis) - mean_ra) * np.cos(val[0]) + mean_ra) ralims.append((max(ra_axis) - mean_ra) * np.cos(val[0]) + mean_ra) pims.append(image) ppbs.append(pim.image(pb)) # Generate the mosaic coordinate frame master_dec = np.arange(min(declims), max(declims), min(decinc)) if max(ralims) - min(ralims) > 5. * np.pi / 3.: # crossed RA=0 print "Warning: I think the mosaic crosses RA=0, treating the coordinates as such." #ralims[ralims>np.pi] -= 2.*np.pi for i in range(len(ralims)): if ralims[i] > np.pi: ralims[i] = ralims[i] - 2. * np.pi master_ra = np.arange(max(ralims), min(ralims), max(rainc)) if args.verbose: print "Found ra,dec pixel increments (arcsec):" print np.array(rainc) * 206265. print np.array(decinc) * 206265. ma = pims[-1].coordinates() ma['direction'].set_referencepixel( [len(master_dec) / 2, len(master_ra) / 2]) ma['direction'].set_increment([min(decinc), max(rainc)]) ma['direction'].set_referencevalue( [master_dec[len(master_dec) / 2], master_ra[len(master_ra) / 2]]) if args.NCP: print 'Setting NCP projection is not yet working ....' #ma['direction'].set_projection('ZEA') # Initialize the arrays for the output image, sensitivity, and weights master_im = np.zeros((len(master_dec), len(master_ra))) master_weight = np.zeros((len(master_dec), len(master_ra))) master_sens = np.zeros((len(master_dec), len(master_ra))) # Reproject the images onto the master grid, weight and normalize for i in range(len(pims)): im = pims[i].regrid([2, 3], ma, outshape=(nc, ns, len(master_dec), len(master_ra))) pb = ppbs[i].regrid([2, 3], ma, outshape=(nc, ns, len(master_dec), len(master_ra))) imdata = np.squeeze(im.getdata()) pbdata = np.squeeze(pb.getdata()) newim = imdata newpb = pbdata newwt = (weights[i] * newpb)**2 master_im += newim * newwt master_sens += newpb * newwt master_weight += newwt inds = master_weight != 0. master_im[inds] /= master_weight[inds] master_sens[inds] /= master_weight[inds] # Show image if requested if args.plotimg: plt.imshow(master_im, vmin=0., vmax=0.5) plt.show() # Write fits files arrax = np.zeros((1, 1, len(master_im[:, 0]), len(master_im[0, :]))) arrax[0, 0, :, :] = master_im # Open new casa image for mosaic new_pim = pim.image('', shape=(1, 1, len(master_dec), len(master_ra)), coordsys=ma) new_pim.putdata(arrax) # Write fits new_pim.tofits(args.outfits, overwrite=True) # Same for sensitivity new_pim_sens = pim.image('', shape=(1, 1, len(master_dec), len(master_ra)), coordsys=ma) arrax[0, 0, :, :] = master_sens new_pim_sens.putdata(arrax) # new_pim_sens.tofits(args.sensfits, overwrite=True) # need to add new beam info (not sure if this is possible with pyrap) hdu = pyfits.open(args.outfits, mode='update') header = hdu[0].header header.update('BMAJ', mean_psf_fwhm[0]) header.update('BMIN', mean_psf_fwhm[1]) header.update('BPA', mean_psf_fwhm[2]) header.update('BUNIT', pims[-1].info()['unit']) header.update('RESTFRQ', mean_frequency) header.update('RESTFREQ', mean_frequency) newhdu = pyfits.PrimaryHDU(data=hdu[0].data, header=header) newhdu.writeto(args.outfits, clobber=True) return
def main(args): if args.plotimg: import pylab as plt # Generate lists of input images and check that they exist images = [] facets = [] psf_fwhm = [] # resolution frequency = [] # frequency of images (should be equal?) basestring = args.basestring imlist = glob.glob(basestring + '*.image') images = [i for i in imlist if not ('nm' in i)] #construct image, facet number list images = [] fields = [] fnumbers = [] p = re.compile('imfield(\d)_cluster(.*)\.') for i in imlist: if 'nm' in i: continue m = p.match(i) if m is None: print 'failed to match', i assert (m is not None) images.append(i) fields.append(m.group(1)) fnumbers.append(m.group(2)) fnumberset = set(fnumbers) for f in fnumberset: fieldlist = [] for i, (field, facet) in enumerate(zip(fields, fnumbers)): if f == facet: fieldlist.append((field, i)) while len(fieldlist) > 1: # more than one field for the same facet... delfield, i = min(fieldlist) print 'de-duplicating', images[i] del (images[i]) del (fields[i]) del (fnumbers[i]) del (fieldlist[fieldlist.index((delfield, i))]) # now we have a non-redundant list for i in range(len(images)): print i, images[i], fields[i], fnumbers[i] # get the facet mask for fn in fnumbers: facets.append('templatemask_' + fn + '.masktmp') if not os.path.exists(facets[-1]): print "Error: facet image", facets[-1], "does not exist" return 1 formstr = '{0:45s} {1:45s} {2:s} {3:s} {4:s} {5:s}' print formstr.format("-----", "--------", "------------", "-------", "-------", "------") print formstr.format("Image", "FC image", "Norm. weight", "Maj(ac)", "Min(ac)", "PA(deg)") print formstr.format("-----", "--------", "------------", "-------", "-------", "------") for i in range(len(images)): this_pim = pim.image(images[i]) info_dict = this_pim.info()['imageinfo']['restoringbeam'] # get beam info bpar_ma = quanta.quantity(info_dict['major']).get_value('deg') bpar_mi = quanta.quantity(info_dict['minor']).get_value('deg') bpar_pa = quanta.quantity(info_dict['positionangle']).get_value('deg') psf_fwhm.append([bpar_ma, bpar_mi, bpar_pa]) frequency.append( this_pim.info()['coordinates']['spectral2']['restfreq']) print '{0:45.45s} {1:45.45s} {2:0.2f} {3:0.2f} {4:0.2f} {5:0.2f}'.format( images[i], facets[i], 0, bpar_ma * 60, bpar_mi * 60, bpar_pa) psf_fwhm = np.array(psf_fwhm) frequency = np.array(frequency) mean_psf_fwhm = np.mean(psf_fwhm, axis=0) mean_frequency = np.mean(frequency) print '\nmean Beam: {0:0.3f} maj (arcmin), {1:2.3f} min (arcmin), {2:0.2f} pa (deg)'.format( mean_psf_fwhm[0] * 60, mean_psf_fwhm[1] * 60, mean_psf_fwhm[2]) print '(Frequency (MHz):', mean_frequency * 1e-6 if np.max(mean_frequency - frequency) / mean_frequency > 1e-6: print '\n\nWARNING.\nAre you using images from different bands?' print 'Frequencies (Hz):', frequency time.sleep(2) # give user time to see this ... # Initialize some vectors declims = [] # store the limits of the declination axes #ralims = [] # store the limits of the r.a. axes raleft = [] raright = [] rainc = [] # store the r.a. increments in case they differ decinc = [] # store the dec increments in case they differ pims = [] # stores the pyrap images of the data pfcs = [] # stores the pyrap images of the facet images # Get image frames for input images for im, fa in zip(images, facets): image = pim.image(im) sptcoords = image.coordinates().get_coordinate('spectral') nc = sptcoords.get_axis_size() # assert(sptcoords.get_image_axis() == 0) # Get Stokes axis. Ensure we are working with the Stokes parameter requested. stkcoords = image.coordinates().get_coordinate('stokes') # assert(stkcoords.get_image_axis() == 1) if stkcoords.get_axis_size() == 1: assert (stkcoords.get_stokes()[0] == args.stokes) else: stks = stkcoords.get_stokes().index(args.stokes) image = image.subimage(blc=(0, stks), trc=(nc - 1, stks), dropdegenerate=False) ns = 1 dircoords = image.coordinates().get_coordinate('direction') nx = dircoords.get_axis_size(axis=1) ny = dircoords.get_axis_size(axis=0) c = [] c.append(image.toworld((0, 0, 0, 0))) c.append(image.toworld((0, 0, 0, nx))) c.append(image.toworld((0, 0, ny, 0))) c.append(image.toworld((0, 0, ny, nx))) c = np.array(c) for i in range(4): if c[i, 3] < 0: c[i, 3] += 2 * np.pi inc = dircoords.get_increment() ref = dircoords.get_referencepixel() val = dircoords.get_referencevalue() # wsclean image header is weird if val[1] < 0: val[1] += 2 * np.pi ra_axis = (range(nx) - ref[1]) * inc[1] + val[1] dec_axis = (range(ny) - ref[0]) * inc[0] + val[0] rainc.append(inc[1]) decinc.append(inc[0]) declims.append(np.min(c[:, 2])) declims.append(np.max(c[:, 2])) #mean_ra = np.mean(ra_axis) #ralims.append((min(ra_axis)-mean_ra)*np.cos(val[0])+mean_ra) #ralims.append((max(ra_axis)-mean_ra)*np.cos(val[0])+mean_ra) #raleft.append((ra_axis[0]-mean_ra)*np.cos(val[0])+mean_ra) #raright.append((ra_axis[-1]-mean_ra)*np.cos(val[0])+mean_ra) raleft.append(np.max(c[:, 3])) raright.append(np.min(c[:, 3])) print im, raleft[-1], raright[-1], rainc[-1] pims.append(image) pfcs.append(pim.image(fa)) # Generate the mosaic coordinate frame if not args.NCP: print('Using the regular mosaic mode.') master_dec = np.arange(min(declims), max(declims), min(decinc)) if max(raleft) - min(raright) > 5. * np.pi / 3.: # crossed RA=0 print "Warning: I think the mosaic crosses RA=0, treating the coordinates as such." ##ralims[ralims>np.pi] -= 2.*np.pi #for i in range(len(ralims)): # if ralims[i]>np.pi: ralims[i] = ralims[i]-2.*np.pi for i in range(len(raright)): raright[i] = raright[i] - 2. * np.pi master_ra = np.arange(max(raleft), min(raright), max(rainc) / (np.cos(min(declims)))) lmra = len(master_ra) if args.maxwidth != 0: if lmra > args.maxwidth: xboundary = (lmra - args.maxwidth) / 2 master_ra = master_ra[xboundary:-xboundary] if args.verbose: print "Found ra,dec pixel increments (arcsec):" print np.array(rainc) * 206265., np.array(decinc) * 206265. ma = pims[-1].coordinates() ma['direction'].set_referencepixel( [len(master_dec) / 2, len(master_ra) / 2]) ma['direction'].set_increment([ decinc[np.argmin(np.abs(decinc))], rainc[np.argmin(np.abs(rainc))] ]) ma['direction'].set_referencevalue( [master_dec[len(master_dec) / 2], master_ra[len(master_ra) / 2]]) else: print('Using the special NCP mosaic mode.') ra_width = 20. / 180 * np.pi dec_width = 20. / 180 * np.pi rainc = rainc[np.argmin(np.abs(rainc))] decinc = decinc[np.argmin(np.abs(decinc))] ra_imsize = int(ra_width / np.abs(rainc)) dec_imsize = int(dec_width / np.abs(decinc)) master_ra = np.arange(ra_imsize, dtype=float) / ra_imsize * rainc - ra_width / 2 master_dec = np.arange( dec_imsize, dtype=float) / dec_imsize * decinc - dec_width / 2 ma = pims[-1].coordinates() ma['direction'].set_referencevalue([np.pi / 2, 0.]) ma['direction'].set_increment([decinc, rainc]) ma['direction'].set_referencepixel([dec_imsize / 2., ra_imsize / 2.]) # Initialize the arrays for the output image, sensitivity, and weights print 'making output image of size', len(master_dec), 'x', len(master_ra) master_im = np.zeros((len(master_dec), len(master_ra))) master_mask = np.zeros((len(master_dec), len(master_ra))) # Reproject the images onto the master grid, weight and normalize for i in range(len(pims)): print 'doing image', i im = pims[i].regrid([2, 3], ma, outshape=(nc, ns, len(master_dec), len(master_ra))) fa = pfcs[i].regrid([2, 3], ma, outshape=(nc, ns, len(master_dec), len(master_ra))) imdata = np.squeeze(im.getdata()) facmask = np.squeeze(fa.getdata()) newim = imdata * facmask # newpb = pbdata # newwt = (weights[i]*newpb)**2 master_im += newim master_mask += facmask # master_sens += newpb*newwt # master_weight += newwt print 'Blanking' blank = np.ones_like(im) * np.nan master_im = np.where(master_mask, master_im, blank) # Show image if requested if args.plotimg: plt.imshow(master_im, vmin=0., vmax=0.5) plt.show() # Write fits files arrax = np.zeros((1, 1, len(master_im[:, 0]), len(master_im[0, :]))) arrax[0, 0, :, :] = master_im # Open new casa image for mosaic new_pim = pim.image('', shape=(1, 1, len(master_dec), len(master_ra)), coordsys=ma) new_pim.putdata(arrax) # Write fits new_pim.tofits(args.outfits, overwrite=True) # need to add new beam info (not sure if this is possible with pyrap) hdu = pyfits.open(args.outfits, mode='update') header = hdu[0].header header.update('BMAJ', mean_psf_fwhm[0]) header.update('BMIN', mean_psf_fwhm[1]) header.update('BPA', mean_psf_fwhm[2]) header.update('BUNIT', pims[-1].info()['unit']) header.update('RESTFRQ', mean_frequency) header.update('RESTFREQ', mean_frequency) newhdu = pyfits.PrimaryHDU(data=hdu[0].data, header=header) newhdu.writeto(args.outfits, clobber=True) return
print "Usage" print " plot_Ateam_elevation.py <msname>" # Create a measures object me = pm.measures() # Open the measurement set and the antenna and pointing table ms = pt.table(msname) # Get the position of the first antenna and set it as reference frame ant_table = pt.table(msname + '/ANTENNA') ant_no = 0 pos = ant_table.getcol('POSITION') x = qa.quantity( pos[ant_no,0], 'm' ) y = qa.quantity( pos[ant_no,1], 'm' ) z = qa.quantity( pos[ant_no,2], 'm' ) position = me.position( 'wgs84', x, y, z ) me.doframe( position ) print position ant_table.close() # Get the first pointing of the first antenna field_table = pt.table(msname + '/FIELD') field_no = 0 direction = field_table.getcol('PHASE_DIR') ra = direction[ ant_no, field_no, 0 ] dec = direction[ ant_no, field_no, 1 ] targets.insert(0, {'name' : 'Pointing', 'ra' : ra, 'dec' : dec})
def getconversion(text): q = quantity(1., text) if q.conforms(radian): return q.get_value('rad') return 1
def run(self, imager_exec, vds, parset, resultsdir, start_time, end_time): # imager_exec: path to cimager executable # vds: VDS file describing the data to be imaged # parset: imager configuration # resultsdir: place resulting images here # start_time: ) time range to be imaged # end_time: ) in seconds (may be None) # ---------------------------------------------------------------------- with log_time(self.logger): self.logger.info("Processing %s" % (vds, )) # Bail out if destination exists (can thus resume a partial run). # Should be configurable? # ------------------------------------------------------------------ parset_data = Parset(parset) image_names = parset_data.getStringVector("Cimager.Images.Names") for image_name in image_names: outputfile = os.path.join(resultsdir, image_name + ".restored") self.logger.info(outputfile) if os.path.exists(outputfile): self.logger.info("Image already exists: aborting.") return 0 try: working_dir = mkdtemp(suffix=".%s" % (os.path.basename(__file__), )) # If a time range has been specified, copy that section of the # input MS and only image that. # -------------------------------------------------------------- query = [] if start_time: self.logger.debug("Start time is %s" % start_time) start_time = quantity(float(start_time), 's') query.append("TIME > %f" % start_time.get('s').get_value()) if end_time: self.logger.debug("End time is %s" % end_time) end_time = quantity(float(end_time), 's') query.append("TIME < %f" % end_time.get('s').get_value()) query = " AND ".join(query) if query: # Select relevant section of MS. # ---------------------------------------------------------- self.logger.debug("Query is %s" % query) output = os.path.join(working_dir, "timeslice.MS") vds_parset = get_parset(vds) t = table(vds_parset.getString("FileName")) t.query(query, name=output) # Patch updated information into imager configuration. # ---------------------------------------------------------- parset = patch_parset(parset, {'Cimager.dataset': output}) else: self.logger.debug("No time range selected") self.logger.debug("Running cimager") with CatchLog4CXX( working_dir, self.logger.name + "." + os.path.basename(vds)): cimager_process = Popen([imager_exec, "-inputs", parset], stdout=PIPE, stderr=PIPE, cwd=working_dir) sout, serr = cimager_process.communicate() log_process_output("cimager", sout, serr, self.logger) if cimager_process.returncode != 0: raise CalledProcessError(cimager_process.returncode, imager_exec) # Dump the resulting images in the pipeline results area. # I'm not aware of a foolproof way to predict the image names # that will be produced, so we read them from the # parset and add standard cimager prefixes. # -------------------------------------------------------------- parset_data = Parset(parset) image_names = parset_data.getStringVector( "Cimager.Images.Names") prefixes = [ "image", "psf", "residual", "weights", "sensitivity" ] self.logger.debug("Copying images to %s" % resultsdir) for image_name in image_names: for prefix in prefixes: filename = image_name.replace("image", prefix, 1) shutil.move(os.path.join(working_dir, filename), os.path.join(resultsdir, filename)) if parset_data.getBool('Cimager.restore'): shutil.move( os.path.join(working_dir, image_name + ".restored"), os.path.join(resultsdir, image_name + ".restored")) except CalledProcessError, e: self.logger.error(str(e)) return 1 finally:
def __init__(self, path, mode): try: from pyrap.images import image except ImportError: raise UnsupportedError( 'cannot open CASAcore images in Pyrap mode without ' 'the Python module "pyrap.images"') super(PyrapImage, self).__init__(path, mode) # no mode specifiable self._handle = image(path) allinfo = self._handle.info() self.units = maybelower(allinfo.get('unit')) self.shape = np.asarray(self._handle.shape(), dtype=np.int) self.axdescs = [] if 'coordinates' in allinfo: pc = allinfo['coordinates'].get('pointingcenter') # initial=True signifies that the pointing center information # hasn't actually been initialized. if pc is not None and not pc['initial']: # This bit of info doesn't have any metadata about units or # whatever; appears to be fixed as RA/Dec in radians. self.pclat = pc['value'][1] self.pclon = pc['value'][0] ii = self._handle.imageinfo() if 'restoringbeam' in ii: self.bmaj = _pyrap_convert(ii['restoringbeam']['major'], 'rad') self.bmin = _pyrap_convert(ii['restoringbeam']['minor'], 'rad') self.bpa = _pyrap_convert(ii['restoringbeam']['positionangle'], 'rad') # Make sure that angular units are always measured in radians, # because anything else is ridiculous. from pyrap.quanta import quantity self._wcscale = wcscale = np.ones(self.shape.size) c = self._handle.coordinates() radian = quantity(1., 'rad') for item in c.get_axes(): if isinstance(item, six.string_types): self.axdescs.append(item.replace(' ', '_')) else: for subitem in item: self.axdescs.append(subitem.replace(' ', '_')) def getconversion(text): q = quantity(1., text) if q.conforms(radian): return q.get_value('rad') return 1 i = 0 for item in c.get_unit(): if isinstance(item, six.string_types): wcscale[i] = getconversion(item) i += 1 elif len(item) == 0: wcscale[i] = 1 # null unit i += 1 else: for subitem in item: wcscale[i] = getconversion(subitem) i += 1 # Figure out which axes are lat/long/spec. We have some # paranoia code the give up in case there are multiple axes # that appear to be of the same type. This stuff could # be cleaned up. lat = lon = spec = -1 try: logspecidx = c.get_names().index('spectral') except ValueError: specaxname = None else: specaxname = c.get_axes()[logspecidx] for i, name in enumerate(self.axdescs): # These symbolic direction names obtained from # casacore/coordinates/Coordinates/DirectionCoordinate.cc # Would be nice to have a better system for determining # this a la what wcslib provides. if name == specaxname: spec = i elif name in ('Right_Ascension', 'Hour_Angle', 'Longitude'): if lon == -1: lon = i else: lon = -2 elif name in ('Declination', 'Latitude'): if lat == -1: lat = i else: lat = -2 if lat >= 0: self._latax = lat if lon >= 0: self._lonax = lon if spec >= 0: self._specax = spec # Phew, that was gross. if self._specax is not None: sd = c.get_coordinate('spectral').dict() wi = sd.get('wcs') if wi is not None: try: from mirtask._miriad_c import mirwcs_compute_freq except ImportError: pass else: spectype = wi['ctype'].replace('\x00', '')[:4] restfreq = sd.get('restfreq', 0.) specval = self.toworld(0.5 * (self.shape - 1))[self._specax] self.charfreq = mirwcs_compute_freq( spectype, specval, restfreq) * 1e-9 # TODO: any unit weirdness or whatever here? self.mjd = c.get_obsdate()['m0']['value']
def _pyrap_convert(d, unitstr): from pyrap.quanta import quantity return quantity(d['value'], d['unit']).get_value(unitstr)
def __init__(self, observer_names, ECEF_positions, feed_angles=None, epoch='J2000', feed_basis='linear', enable_rotation=True, enable_pa=True, enable_derotation=True, field_centre=(0, -90)): """ Machine to rotate and derotate visibilities around 3rd axis of observer's local coordiante frame Args: @observer_names: list of antenna names @ECEF_positions: (nant, 3) array, as provided in MS::ANTENNA subtable @feed_angles: (nant, 2) array, as provided by MS::FEED subtable. None for nominally oriented receptors @epoch: coordinate system epoch, usually J2000 @feed_basis: linear or circular feeds @enable_rotation: switches on rotation @enable_derotation: switches on derotation @enable_pa: include PA in rotation/derotation (else feed angle only) @field_centre: initial field centre, SCP by default """ if not len(observer_names) == ECEF_positions.shape[0]: raise ValueError("Must provide a coordinate for every antenna") if not ECEF_positions.shape[1] == 3: raise ValueError("ECEF coordinates must be 3 dimensional") self.__observer_names = copy.deepcopy(observer_names) print( "Initializing new parallactic angle machine for {} ECEF positions". format(len(self.__observer_names)), file=log(0)) for s in [ "%s\t\t%.2f\t%.2f\t%.2f" % (aname, X, Y, Z) for aname, (X, Y, Z) in zip(self.__observer_names, ECEF_positions) ]: print(" " + s, file=log(1)) self.__observer_positions = [ pm.position('itrf', *(pq.quantity(x, 'm') for x in pos)) for pos in ECEF_positions ] self.__epoch = epoch log.info("Conversion epoch is %s" % self.__epoch) # initialize field centre to SCP self.__zenith_azel = pm.direction( "AZEL", *(pq.quantity(fi, 'deg') for fi in (0, 90))) self.__observer_zenithal_angle = None self.__field_centre = None self.field_centre = field_centre self.feed_basis = feed_basis self.__enable_rotation = None self.__enable_derotation = None self.__enable_pa = enable_pa self.__feed_angles = feed_angles self.enable_rotation = enable_rotation self.enable_derotation = enable_derotation
def getAzEl(pointing, time, position, ha_limit=-1000): if HAS_PYRAP: if ha_limit == -1000: azel = radec2azel(pointing[0], pointing[1], time=str(time) + 's', pos=position) az = azel['m0']['value'] el = azel['m1']['value'] else: me = measures() p = me.position("ITRF", str(position[0]) + 'm', str(position[1]) + 'm', str(position[2]) + 'm') t = me.epoch("UTC", qu.quantity(str(time) + 's')) phasedir = me.direction('J2000', str(pointing[0]) + 'rad', str(pointing[1]) + 'rad') me.doframe(p) me.doframe(t) hadec = me.measure(phasedir, "HADEC") if abs(hadec['m0']['value']) > ha_limit: print("below horizon", tab.taql('calc ctod($time s)')[0], degrees(hadec['m0']['value']), degrees(hadec['m1']['value'])) return 999, 999 else: azel = me.measure(phasedir, "AZELGEO") az = azel['m0']['value'] el = azel['m1']['value'] elif HAS_EPHEM: if ha_limit != -1000: print( "limiting on HA/DEC not implemented for PyEphem yet, ignoring") location_lat, location_lon, location_height = ITRFToWGS84( position[0], position[1], position[2]) location = ephem.Observer() # convert geodetic latitude to geocentric # flattening, f, defined above for WGS84 stuff geodet_lat = math.radians(location_lat) tan_geocentric_latitude = math.tan(geodet_lat) * (1 - f)**2 geocentric_latitude = GeodeticToGeocentricLat(geodet_lat, location_height) location.lat = geocentric_latitude location.lon = math.radians(location_lon) location.elevation = location_height location.pressure = 0.0 # convert to Dublin Julian Date for PyEphem location.date = time / 86400.0 - 15019.5 lst = location.sidereal_time() equatorial = ephem.Equatorial( str(12.0 * math.degrees(pointing[0]) / 180), str(math.degrees(pointing[1]))) body = ephem.FixedBody() body._ra = equatorial.ra body._dec = equatorial.dec body._epoch = equatorial.epoch body.compute(location) az = math.degrees(body.az) * math.pi / 180.0 el = math.degrees(body.alt) * math.pi / 180.0 else: print('failure to get azimuth and elevation! Exiting!') return -1, -1 return az, el
# There is a bug in mscorpol package script antennaJones.py the line 210. # It has to be changed from "if stnLoc=='CS' or stnLoc=='RS':" to # "if stnLoc=='CS': # or stnLoc=='RS':", i.e. to comment out 'RS' part. # It makes sense as all RS stations have just only one ear of 48 tiles similar # to International stations with 96 tiles, thus antenna must be "HBA" instead of "HBA0" #stations=["CS001", "CS002", "CS003", "CS004", "CS005", "CS006", "CS007", # "CS011", "CS013", "CS017", "CS021", "CS024", "CS026", "CS028", # "CS030", "CS031", "CS032", "CS101", "CS103", "CS201", "CS301", # "CS302", "CS401", "CS501", "DE601", "DE602", "DE603", "DE604", # "DE605", "FR606", "SE607", "UK608", "DE609", "PL610", "PL611", "PL612"] # m a i n if __name__=="__main__": subwidth=100./512. obstimes=quantity([55159.77650462962963, 55159.77650462962963], 'd') direction=measures().direction('J2000', str(6.123487681)+'rad', str(1.0265154)+'rad') out = open("casa_beamcorr_pkg.py", "wt") out.write("casa_beamcorr={") for ss in xrange(len(stations)): print "%s, #%d of %d" % (stations[ss], ss+1, len(stations)) out.write("\"%s\" : [" % (stations[ss])) for ii in xrange(51, 1536, 6): # freq between 10 MHz and 300 MHz outline="" for jj in xrange(ii, ii+6 > 1536 and 1536 or ii+6): if jj != ii: outline += ", " freq=jj*subwidth+subwidth/2. # in MHz Jn=aj.getJonesByAntFld("Hamaker", obstimes, stations[ss], direction, freq*1.e6) bc_casa = 1./np.abs(0.5*(Jn[0,0,0]*np.conj(Jn[0,0,0]) + Jn[0,0,1]*np.conj(Jn[0,0,1]) + \ Jn[0,1,0]*np.conj(Jn[0,1,0]) + Jn[0,1,1]*np.conj(Jn[0,1,1])))
def getAteamList(MSname, innerDistance=21., outerDistance=35., refFreq=58., elLimit=20., verbose=False): # Here are the Ateam sources to check, with RA,Dec in rad targets = [ { 'name': 'CasA', 'ra': 6.123487680622104, 'dec': 1.0265153995604648 }, { 'name': 'CygA', 'ra': 5.233686575770755, 'dec': 0.7109409582180791 }, { 'name': 'TauA', 'ra': 1.4596748493730913, 'dec': 0.38422502335921294 }, #{'name' : 'HerA', 'ra' : 4.4119087330382163, 'dec' : 0.087135562905816893}, { 'name': 'VirA', 'ra': 3.276086511413598, 'dec': 0.21626589533567378 } ] #, #{'name' : 'HydA', 'ra' : 2.4351466, 'dec' : -0.21110706}, #{'name' : 'PerA', 'ra' : 0.87180363, 'dec' : 0.72451580}, #{'name' : 'SUN'}, #{'name' : 'JUPITER'}] # Need a measure object me = pm.measures() # Open the ms and get the reference time and frequency ms = pt.table(MSname, ack=False) refTime = ms.getcell('TIME', 0) freq_table = pt.table(ms.getkeyword('SPECTRAL_WINDOW'), ack=False) msFreq = freq_table.getcell('REF_FREQUENCY', 0) # correct the inner and outer distances for frequency freqFactor = (refFreq * 1.e6) / msFreq innerDistance *= freqFactor outerDistance *= freqFactor if verbose: print('At frequency %f MHz:' % (msFreq / 1.e6)) print('Frequency-corrected inner radius: %f' % innerDistance) print('Frequency-corrected outer radius: %f' % outerDistance) print(' (or %f for CasA,CygA)' % (outerDistance * 2.)) print('') # Get location of the first station ant_table = pt.table(ms.getkeyword('ANTENNA'), ack=False) ant_no = 0 pos = ant_table.getcol('POSITION') x = qa.quantity(pos[ant_no, 0], 'm') y = qa.quantity(pos[ant_no, 1], 'm') z = qa.quantity(pos[ant_no, 2], 'm') position = me.position('wgs84', x, y, z) me.doframe(position) #print position ant_table.close() # Get pointing direction of the MS field_table = pt.table(ms.getkeyword('FIELD'), ack=False) field_no = 0 direction = field_table.getcol('PHASE_DIR') ra = direction[ant_no, field_no, 0] dec = direction[ant_no, field_no, 1] targets.insert(0, {'name': 'Pointing', 'ra': ra, 'dec': dec}) field_table.close() # set up the target pointing direction ra_qa = qa.quantity(targets[0]['ra'], 'rad') dec_qa = qa.quantity(targets[0]['dec'], 'rad') pointing = me.direction('j2000', ra_qa, dec_qa) # this will be the list of sources to demix aTeamList = [] # For each source, we have to calculate # a) distance to target field # b) elevation for target in targets[1:]: t = qa.quantity(refTime, 's') t1 = me.epoch('utc', t) me.doframe(t1) # calculate the sun and jupiter positions specially if 'ra' in list(target.keys()): ra_qa = qa.quantity(target['ra'], 'rad') dec_qa = qa.quantity(target['dec'], 'rad') direction = me.direction('j2000', ra_qa, dec_qa) else: direction = me.direction(target['name']) # Now the separation between the target and the Ateam source aTeamDistance = me.separation(pointing, direction).get_value() # Now the elevation of the Ateam source at the reference time a = me.measure(direction, 'azel') elevation = a['m1'] elDeg = elevation['value'] / pi * 180. # print if verbose if verbose: print('Source: %s' % target['name']) print('Separation: %f' % aTeamDistance) print('Elevation: %f' % elDeg) # Does it need to be demixed? if target['name'] == 'CygA' or target['name'] == 'CasA': odFact = 2. else: odFact = 1. if aTeamDistance > innerDistance and aTeamDistance < outerDistance * odFact and elDeg > elLimit: aTeamList.append(target['name']) if verbose: print('DEMIX\n') elif verbose: print('DO NOT DEMIX\n') return aTeamList
inter=interv[0] else: print("\nMeasurement sets intervals are not the same!") print("Intervals detected: {0}".format(interv)) sys.exit() print("\nInterval = {0}s".format(inter)) if concat(args, oname): # if True: print("Changing Times on Set...") mstochange=pt.table(oname, ack=False, readonly=False) amps_time = mstochange.getcol('TIME') amps_time_cen = mstochange.getcol('TIME_CENTROID') new_time, newtime_cen, start, end=newtimearray(amps_time, amps_time_cen, inter, gap) mstochange.putcol('TIME',new_time) mstochange.putcol('TIME_CENTROID',newtime_cen) mstochange.close() mstochange=pt.table(oname+'/OBSERVATION', ack=False, readonly=False) mstochange.putcell("LOFAR_OBSERVATION_START", 0, start) mstochange.putcell("LOFAR_OBSERVATION_END", 0, start) newrange=np.array([start, end]) mstochange.putcell("TIME_RANGE", 0, newrange) mstochange.close() inttime=end-start print("Start Time: {0}".format(datetime.utcfromtimestamp(quantity('{0}s'.format(start)).to_unix_time()))) print("NEW End Time: {0}".format(datetime.utcfromtimestamp(quantity('{0}s'.format(end)).to_unix_time()))) print("Integration Time = {0:.2f}s ({1:.2f} hours)".format(inttime, (inttime)/3600.)) else: sys.exit()
import numpy import pyrap.measures as pm import pyrap.tables as pt import pyrap.quanta as qa import pylab if len(sys.argv) != 2: print 'Error: I need an MS name' exit(1) me = pm.measures() t = pt.table(sys.argv[1]) timevals = t.getcol('TIME') tb = pt.table(t.getkeyword('ANTENNA')) pos = tb.getcol('POSITION') x = qa.quantity(pos[0, 0], 'm') y = qa.quantity(pos[0, 1], 'm') z = qa.quantity(pos[0, 2], 'm') tb.close() position = me.position('wgs84', x, y, z) tb = pt.table(t.getkeyword('FIELD')) direction = numpy.squeeze(tb.getcol('PHASE_DIR')) tb.close() t.close() RA = qa.quantity(direction[0], 'rad') dec = qa.quantity(direction[1], 'rad') pointing = me.direction('j2000', RA, dec) me.doframe(position) el = numpy.zeros(len(timevals)) az = numpy.zeros(len(timevals)) for i in range(len(timevals)):
def pipeline_logic(self): from to_process import datafiles # datafiles is a list of MS paths. with log_time(self.logger): # Build a map of compute node <-> data location on storage nodes. storage_mapfile = self.run_task( "datamapper", datafiles )['mapfile'] # Produce a GVDS file describing the data on the storage nodes. self.run_task('vdsmaker', storage_mapfile) # Read metadata (start, end times, pointing direction) from GVDS. vdsinfo = self.run_task("vdsreader") # NDPPP reads the data from the storage nodes, according to the # map. It returns a new map, describing the location of data on # the compute nodes. ndppp_results = self.run_task( "ndppp", storage_mapfile, parset=os.path.join( self.config.get("layout", "parset_directory"), "ndppp.1.initial.parset" ), data_start_time=vdsinfo['start_time'], data_end_time=vdsinfo['end_time'] ) # Remove baselines which have been fully-flagged in any individual # subband. compute_mapfile = self.run_task( "flag_baseline", ndppp_results['mapfile'], baselines=ndppp_results['fullyflagged'] )['mapfile'] # Build a sky model ready for BBS & return the name & flux of the # central source. ra = quantity(vdsinfo['pointing']['ra']).get_value('deg') dec = quantity(vdsinfo['pointing']['dec']).get_value('deg') central = self.run_task( "skymodel", ra=ra, dec=dec, search_size=2.5 ) # Patch the name of the central source into the BBS parset for # subtraction. with patched_parset( self.task_definitions.get("bbs", "parset"), { 'Step.correct.Model.Sources': "[ \"%s\" ]" % (central["source_name"]), 'Step.subtract.Model.Sources': "[ \"%s\" ]" % (central["source_name"]) } ) as bbs_parset: # BBS modifies data in place, so the map produced by NDPPP # remains valid. self.run_task("bbs", compute_mapfile, parset=bbs_parset) # Now, run DPPP three times on the output of BBS. We'll run # this twice: once on CORRECTED_DATA, and once on # SUBTRACTED_DATA. Clip anything at more than 5 times the flux of # the central source. with patched_parset( os.path.join( self.config.get("layout", "parset_directory"), "ndppp.1.postbbs.parset" ), { "clip1.amplmax": str(5 * central["source_flux"]) }, output_dir=self.config.get("layout", "parset_directory") ) as corrected_ndppp_parset: for i in repeat(None, 3): self.run_task( "ndppp", compute_mapfile, parset=corrected_ndppp_parset, suffix="" ) with patched_parset( os.path.join( self.config.get("layout", "parset_directory"), "ndppp.1.postbbs.parset" ), { "msin.datacolumn": "SUBTRACTED_DATA", "msout.datacolumn": "SUBTRACTED_DATA", "clip1.amplmax": str(5 * central["source_flux"]) }, output_dir=self.config.get("layout", "parset_directory") ) as subtracted_ndppp_parset: for i in repeat(None, 3): self.run_task( "ndppp", compute_mapfile, parset=subtracted_ndppp_parset, suffix="" ) # Image CORRECTED_DATA. self.logger.info("Imaging CORRECTED_DATA") # Patch the pointing direction recorded in the VDS file into # the parset for the cimager. with patched_parset( self.task_definitions.get("cimager", "parset"), { 'Images.ra': quantity(vdsinfo['pointing']['ra']).formatted("time"), 'Images.dec': quantity(vdsinfo['pointing']['dec']).formatted("angle") }, output_dir=self.config.get("layout", "parset_directory") ) as imager_parset: # And run cimager. self.outputs['images'] = self.run_task( "cimager", compute_mapfile, parset=imager_parset, results_dir=os.path.join( self.config.get("layout", "results_directory"), "corrected" ) )['images'] # Image SUBTRACTED_DATA. self.logger.info("Imaging SUBTRACTED_DATA") # Patch the pointing direction recorded in the VDS file into # the parset for the cimager, and change the column to be # imaged. with patched_parset( self.task_definitions.get("cimager", "parset"), { 'Images.ra': quantity(vdsinfo['pointing']['ra']).formatted("time"), 'Images.dec': quantity(vdsinfo['pointing']['dec']).formatted("angle"), 'datacolumn': "SUBTRACTED_DATA" }, output_dir=self.config.get("layout", "parset_directory") ) as subtracted_imager_parset: # And run cimager. self.outputs['images'] = self.run_task( "cimager", compute_mapfile, parset=subtracted_imager_parset, results_dir=os.path.join( self.config.get("layout", "results_directory"), "subtracted" ) )['images']
def test_uvw_new_casacore(msname): r''' Test if UVW = UVW_FROM_ITRF(XYZ_ANTENNA2 - XYZ_ANTENNA1) ''' dm = measures() tab = table(msname) ant1 = tab.getcol('ANTENNA1') ant2 = tab.getcol('ANTENNA2') uvw = tab.getcol('UVW') time = tab.getcol('TIME') time_epochs = [ dm.epoch('UTC', quantity(mjds, 's')) for mjds in concatenate([time[:3000], time[-3000:]], axis=0) ] field_table = table(tab.getkeyword('FIELD')) phase_dir = field_table.getcol('PHASE_DIR')[0, 0, :] phase_dir_meas_info = field_table.getcolkeyword('PHASE_DIR', 'MEASINFO') phase_dir_units = field_table.getcolkeyword('PHASE_DIR', 'QuantumUnits') phase_dir_quantities = [ '%r%s' % (angle, unit) for angle, unit in zip(phase_dir, phase_dir_units) ] lofar = dm.position('ITRF', '3826577.462m', '461022.624m', '5064892.526m') dm.do_frame(lofar) dm.do_frame( dm.direction(phase_dir_meas_info['Ref'], phase_dir_quantities[0], phase_dir_quantities[1])) ant_table = table(tab.getkeyword('ANTENNA')) xyz = ant_table.getcol('POSITION') xyz_1 = array([xyz[ant, :] for ant in ant1]) xyz_2 = array([xyz[ant, :] for ant in ant2]) delta_xyz = (xyz_2 - xyz_1) uvw_computed = [] for ant1_xyz, ant2_xyz, epoch in zip(xyz_1[:2000], xyz_2[:2000], time_epochs): dm.do_frame(epoch) ant_1_quant = [quantity(p, 'm') for p in ant1_xyz] ant_2_quant = [quantity(p, 'm') for p in ant2_xyz] ant_pos = dm.position( 'ITRF', list(map(list, list(zip(ant_1_quant, ant_2_quant))))) bl_quant = [quantity(value, 'm') for value in dxyz] #print bl_quant bl = dm.baseline('ITRF', bl_quant[0], bl_quant[1], bl_quant[2]) #print bl uvw_computed.append(dm.to_uvw(bl)) for a1, a2, uvw_ms, uvw_comp in zip(ant1, ant2, uvw, uvw_computed): uvw_comp = array(uvw_comp['xyz'].get_value('m')) if norm(uvw_ms) > 0.0: arg = inner(uvw_ms, uvw_comp) / (norm(uvw_ms)**2) if arg > 1.0: arg = 1.0 if arg < -1.0: arg = -1.0 angle_mas = arccos(arg) * 180 * 3600 * 1000. / pi if angle_mas > 50.0: fmt = 'Angle UVW computed / MS %03d--%03d = %.3f mas (%.3f deg)' raise ValueError( fmt % (a1, a2, angle_mas, angle_mas / 1000. / 3600.0)) diff = uvw_ms - uvw_comp if norm(diff) > 1e-3: raise ValueError('UVW computed - UVW MS %03d--%03d = %.3f mm' % (a1, a2, norm(diff) * 1e3)) return True
def synthesize_uvw(station_ECEF, time, a1, a2, phase_ref, stopctr_units=["rad", "rad"], stopctr_epoch="j2000", time_TZ="UTC", time_unit="s", posframe="ITRF", posunits=["m", "m", "m"]): """ Synthesizes new UVW coordinates based on time according to NRAO CASA convention (same as in fixvis) station_ECEF: ITRF station coordinates read from MS::ANTENNA time: time column, preferably time centroid a1: ANTENNA_1 index a2: ANTENNA_2 index phase_ref: phase reference centre in radians returns dictionary of dense uvw coordinates and indices: { "UVW": shape (nbl * ntime, 3), "TIME_CENTROID": shape (nbl * ntime,), "ANTENNA_1": shape (nbl * ntime,), "ANTENNA_2": shape (nbl * ntime,) } Note: input and output antenna indexes may not have the same order or be flipped in 1 to 2 index Note: This operation CANNOT be applied blockwise due to a casacore.measures threadsafety issue """ assert time.size == a1.size assert a1.size == a2.size ants = np.concatenate((a1, a2)) unique_ants = np.unique(ants) unique_time = np.unique(time) na = unique_ants.size nbl = na * (na - 1) // 2 + na ntime = unique_time.size # keep a full uvw array for all antennae - including those # dropped by previous calibration and CASA splitting padded_uvw = np.zeros((ntime * nbl, 3), dtype=np.float64) antindices = np.stack(np.triu_indices(na, 0), axis=1) padded_time = unique_time.repeat(nbl) padded_a1 = np.tile(antindices[:, 0], (1, ntime)).ravel() padded_a2 = np.tile(antindices[:, 1], (1, ntime)).ravel() dm = measures() epoch = dm.epoch(time_TZ, quantity(time[0], time_unit)) refdir = dm.direction(stopctr_epoch, quantity(phase_ref[0, 0], stopctr_units[0]), quantity(phase_ref[0, 1], stopctr_units[1])) obs = dm.position(posframe, quantity(station_ECEF[0, 0], posunits[0]), quantity(station_ECEF[0, 1], posunits[1]), quantity(station_ECEF[0, 2], posunits[2])) #setup local horizon coordinate frame with antenna 0 as reference position dm.do_frame(obs) dm.do_frame(refdir) dm.do_frame(epoch) p = progress(unique_time.size) for ti, t in enumerate(unique_time): p.increment() epoch = dm.epoch("UT1", quantity(t, "s")) dm.do_frame(epoch) station_uv = np.zeros_like(station_ECEF) for iapos, apos in enumerate(station_ECEF): compuvw = dm.to_uvw( dm.baseline( posframe, quantity([apos[0], station_ECEF[0, 0]], posunits[0]), quantity([apos[1], station_ECEF[0, 1]], posunits[1]), quantity([apos[2], station_ECEF[0, 2]], posunits[2]))) station_uv[iapos] = compuvw["xyz"].get_value()[0:3] for bl in range(nbl): blants = antindices[bl] bla1 = blants[0] bla2 = blants[1] # same as in CASA convention (Convention for UVW calculations in CASA, Rau 2013) padded_uvw[ti * nbl + bl, :] = station_uv[bla1] - station_uv[bla2] return dict( zip(["UVW", "TIME_CENTROID", "ANTENNA1", "ANTENNA2"], [padded_uvw, padded_time, padded_a1, padded_a2]))
print "\nInterval = {0}s".format(inter) if concat(args, oname): # if True: print "Changing Times on Set..." mstochange = pt.table(oname, ack=False, readonly=False) amps_time = mstochange.getcol('TIME') amps_time_cen = mstochange.getcol('TIME_CENTROID') new_time, newtime_cen, start, end = newtimearray(amps_time, amps_time_cen, inter, gap) mstochange.putcol('TIME', new_time) mstochange.putcol('TIME_CENTROID', newtime_cen) mstochange.close() mstochange = pt.table(oname + '/OBSERVATION', ack=False, readonly=False) mstochange.putcell("LOFAR_OBSERVATION_START", 0, start) mstochange.putcell("LOFAR_OBSERVATION_END", 0, start) newrange = np.array([start, end]) mstochange.putcell("TIME_RANGE", 0, newrange) mstochange.close() inttime = end - start print "Start Time: {0}".format( datetime.utcfromtimestamp( quantity('{0}s'.format(start)).to_unix_time())) print "NEW End Time: {0}".format( datetime.utcfromtimestamp(quantity('{0}s'.format(end)).to_unix_time())) print "Integration Time = {0:.2f}s ({1:.2f} hours)".format( inttime, (inttime) / 3600.) else: sys.exit()
def __mjd2dt(self, utc_timestamp): """ Converts array of UTC timestamps to list of datetime objects for human readable printing """ return [dt.datetime.utcfromtimestamp(pq.quantity(t, "s").to_unix_time()) for t in utc_timestamp]
def go(self): self.logger.info("Starting cimager run") super(cimager, self).go() self.outputs['images'] = [] # Build a GVDS file describing all the data to be processed # ---------------------------------------------------------------------- self.logger.debug("Building VDS file describing all data for cimager") gvds_file = os.path.join(self.config.get("layout", "job_directory"), "vds", "cimager.gvds") inputs = LOFARinput(self.inputs) inputs['args'] = self.inputs['args'] inputs['gvds'] = gvds_file inputs['unlink'] = False inputs['makevds'] = self.inputs['makevds'] inputs['combinevds'] = self.inputs['combinevds'] inputs['nproc'] = self.inputs['nproc'] inputs['directory'] = os.path.dirname(gvds_file) outputs = LOFARoutput(self.inputs) if self.cook_recipe('vdsmaker', inputs, outputs): self.logger.warn("vdsmaker reports failure") return 1 self.logger.debug("cimager GVDS is %s" % (gvds_file, )) # Read data for processing from the GVDS file # ---------------------------------------------------------------------- parset = Parset(gvds_file) data = [] for part in range(parset.getInt('NParts')): host = parset.getString("Part%d.FileSys" % part).split(":")[0] vds = parset.getString("Part%d.Name" % part) data.append((host, vds)) # Divide data into timesteps for imaging # timesteps is a list of (start, end, results directory) tuples # ---------------------------------------------------------------------- timesteps = [] results_dir = self.inputs['results_dir'] if self.inputs['timestep'] == 0: self.logger.info("No timestep specified; imaging all data") timesteps = [(None, None, results_dir)] else: self.logger.info("Using timestep of %s s" % self.inputs['timestep']) gvds = get_parset(gvds_file) start_time = quantity(gvds['StartTime'].get()).get('s').get_value() end_time = quantity(gvds['EndTime'].get()).get('s').get_value() step = float(self.inputs['timestep']) while start_time < end_time: timesteps.append((start_time, start_time + step, os.path.join(results_dir, str(start_time)))) start_time += step # Run each cimager process in a separate thread # ---------------------------------------------------------------------- command = "python %s" % (self.__file__.replace('master', 'nodes')) for label, timestep in enumerate(timesteps): self.logger.info("Processing timestep %d" % label) jobs = [] parsets = [] start_time, end_time, resultsdir = timestep for host, vds in data: vds_data = Parset(vds) frequency_range = [ vds_data.getDoubleVector("StartFreqs")[0], vds_data.getDoubleVector("EndFreqs")[-1] ] parsets.append( self.__get_parset( os.path.basename( vds_data.getString('FileName')).split('.')[0], vds_data.getString("FileName"), str(frequency_range), vds_data.getStringVector("Extra.FieldDirectionType") [0], vds_data.getStringVector("Extra.FieldDirectionRa")[0], vds_data.getStringVector("Extra.FieldDirectionDec")[0], 'True', # cimager bug: non-restored image unusable )) jobs.append( ComputeJob(host, command, arguments=[ self.inputs['imager_exec'], vds, parsets[-1], resultsdir, start_time, end_time ])) self._schedule_jobs(jobs, max_per_node=self.inputs['nproc']) for parset in parsets: parset = Parset(parset) image_names = parset.getStringVector("Cimager.Images.Names") self.outputs['images'].extend(image_names) [os.unlink(parset) for parset in parsets] # Check if we recorded a failing process before returning # ---------------------------------------------------------------------- if self.error.isSet(): self.logger.warn("Failed imager process detected") return 1 else: return 0
return mjd2lst(jd - 2400000.5, position) # NB: datetime is not sensitive to leap seconds. # However, leap seconds were first introduced in 1972. # So there are no leap seconds between the start of the # Modified Julian epoch and the start of the Unix epoch, # so this calculation is safe. #julian_epoch = datetime.datetime(1858, 11, 17) #unix_epoch = datetime.datetime(1970, 1, 1, 0, 0) #delta = unix_epoch - julian_epoch #deltaseconds = delta.total_seconds() #unix_epoch = 3506716800 # The above is equivalent to this: unix_epoch = quantity("1970-01-01T00:00:00").get_value('s') def julian2unix(timestamp): """ Convert a modifed julian timestamp (number of seconds since 17 November 1858) to Unix timestamp (number of seconds since 1 January 1970). Args: timestamp (numbers.Number): Number of seconds since the Unix epoch. Returns: numbers.Number: Number of seconds since the modified Julian epoch. """ return timestamp - unix_epoch