def randomCoords(imagenames, ncoords=10): import random from taskinit import ia, qa xmin, xmax = [], [] ymin, ymax = [], [] for image in imagenames: ia.open(image) print image, ia.boundingbox() trc = ia.boundingbox()['trcf'].split(', ') blc = ia.boundingbox()['blcf'].split(', ') xmin.append(qa.convert(qa.quantity(trc[0]), 'rad')['value']) xmax.append(qa.convert(qa.quantity(blc[0]), 'rad')['value']) ymin.append(qa.convert(qa.quantity(blc[1]), 'rad')['value']) ymax.append(qa.convert(qa.quantity(trc[1]), 'rad')['value']) ia.done() randomcoords = CoordList(imagenames) for i in range(ncoords): imageid = random.randint(0, len(imagenames) - 1) x = random.uniform(xmin[imageid], xmax[imageid]) y = random.uniform(ymin[imageid], ymax[imageid]) c = Coord(x, y, 1.0) randomcoords.append(c) return randomcoords
def __axis(self, idx, unit): refpix = self.coordsys.referencepixel()['numeric'][idx] refval = self.coordsys.referencevalue()['numeric'][idx] increment = self.coordsys.increment()['numeric'][idx] _unit = self.units[idx] if _unit != unit: refval = qa.convert(qa.quantity(refval,_unit),unit)['value'] increment = qa.convert(qa.quantity(increment,_unit),unit)['value'] #return numpy.array([refval+increment*(i-refpix) for i in xrange(self.nchan)]) return (refpix, refval, increment)
def to_velocity(self, frequency, freq_unit='GHz', restfreq=None): rest_frequency = self.coordsys.restfrequency() # user-defined rest frequency takes priority if restfreq is not None: vrf = qa.convert(qa.quantity(restfreq), freq_unit)['value'] elif rest_frequency['unit'] != freq_unit: vrf = qa.convert(rest_frequency, freq_unit)['value'] else: vrf = rest_frequency['value'] return (1.0 - (frequency / vrf)) * LightSpeed
def _calculate_sigma_weights(coords, maxmaskradius=None): import numpy as np from taskinit import ia global stampsize if coords.physical and coords.imagenames[0]: ia.open(coords.imagenames[0]) # beam = qa.convert(ia.restoringbeam()['major'], 'rad')['value'] if ia.restoringbeam() == {}: masksize = 10 else: masksize = 2*np.abs(qa.convert(ia.restoringbeam()['major'],'rad')['value']/ ia.coordsys().increment()['numeric'][0]) ia.done() X = np.arange(0, stampsize)-stampsize/2 Y = np.arange(0, stampsize)-stampsize/2 X,Y = np.meshgrid(X,Y) for i,coord in enumerate(coords): tmpdata = data[i,:,:,:,:] for j in range(tmpdata.shape[2]): for k in range(tmpdata.shape[3]): tmpdata[:,:,j,k] = (tmpdata[:,:,j,k]*np.double( np.sqrt(X**2+Y**2)>masksize)) sigma = np.std(tmpdata) if sigma == 0: coord.weight = 0. else: coord.weight = 1/sigma if maxmaskradius and maxmaskradius < masksize: masksize = maxmaskradius return coords
def to_velocity(self, frequency, freq_unit='GHz'): rest_frequency = self.coordsys.restfrequency() if rest_frequency['unit'] != freq_unit: vrf = qa.convert(rest_frequency, freq_unit)['value'] else: vrf = rest_frequency['value'] return (1.0 - (frequency / vrf)) * LightSpeed
def noise(coords, vis, weighting='sigma2', imagenames=[], beam=None, nrand=50, stampsize=32, maskradius=None): """ Calculate noise using a Monte Carlo method, can be time consuming. """ import stacker import stacker.image from math import pi if beam is None: try: from taskinit import ia, qa ia.open(imagenames[0]) beam = qa.convert(ia.restoringbeam()['major'], 'rad')['value'] ia.done() except ImportError: beam = 1 / 3600. / 180. * pi dist = [] for i in range(nrand): random_coords = stacker.randomizeCoords(coords, beam=beam) if weighting == 'sigma2': random_coords = stacker.image.calculate_sigma2_weights( random_coords, imagenames, stampsize, maskradius) dist.append(stack(random_coords, vis)) return np.std(np.real(np.array(dist)))
def mean_radius_with_known_theta(retdict): """ Return the average apparent mean radius of an ellipsoid with semiaxes a >= b >= c (= retdict['radii']['value']). "average" means average over a rotation period, and "apparent mean radius" means the radius of a circle with the same area as the apparent disk. """ a = retdict['radii']['value'][0] b2 = retdict['radii']['value'][1]**2 c2 = retdict['radii']['value'][2]**2 onemboa2 = 1.0 - b2 / a**2 units = {} values = {} for c in ['RA', 'DEC', 'NP_RA', 'NP_DEC']: units[c] = retdict['data'][c]['data']['unit'] values[c] = retdict['data'][c]['data']['value'] av = 0.0 nrows = len(retdict['data']['RA']['data']['value']) for i in xrange(nrows): radec = me.direction('app', {'unit': units['RA'], 'value': values['RA'][i]}, {'unit': units['DEC'], 'value': values['DEC'][i]}) np = me.direction('j2000', {'unit': units['NP_RA'], 'value': values['NP_RA'][i]}, {'unit': units['NP_DEC'], 'value': values['NP_DEC'][i]}) szeta2 = scipy.sin(qa.convert(me.separation(radec, np), 'rad')['value'])**2 csinz2 = c2 * szeta2 bcosz2 = b2 * (1.0 - szeta2) bcz2pcsz2 = bcosz2 + csinz2 m = csinz2 * onemboa2 / bcz2pcsz2 av += (scipy.sqrt(bcz2pcsz2) * scipy.special.ellipe(m) - av) / (i + 1.0) return scipy.sqrt(2.0 * a * av / scipy.pi)
def to_frequency(self, velocity, freq_unit='km/s'): rest_frequency = self.coordsys.restfrequency() if rest_frequency['unit'] != freq_unit: vrf = qa.convert(rest_frequency, freq_unit)['value'] else: vrf = rest_frequency['value'] return (1.0 - velocity / LightSpeed) * vrf
def noise(coords, vis, weighting='sigma2', imagenames=[], beam=None, nrand=50, stampsize=32, maskradius=None): """ Calculate noise using a Monte Carlo method, can be time consuming. """ import stacker import stacker.image from math import pi if beam is None: try: from taskinit import ia, qa ia.open(imagenames[0]) beam = qa.convert(ia.restoringbeam()['major'], 'rad')['value'] ia.done() except ImportError: beam = 1/3600./180.*pi dist = [] for i in range(nrand): random_coords = stacker.randomizeCoords(coords, beam=beam) if weighting == 'sigma2': random_coords = stacker.image.calculate_sigma2_weights( random_coords, imagenames, stampsize, maskradius) dist.append(stack(random_coords, vis)) return np.std(np.real(np.array(dist)))
def mean_radius_with_known_theta(retdict): """ Return the average apparent mean radius of an ellipsoid with semiaxes a >= b >= c (= retdict['radii']['value']). "average" means average over a rotation period, and "apparent mean radius" means the radius of a circle with the same area as the apparent disk. """ a = retdict["radii"]["value"][0] b2 = retdict["radii"]["value"][1] ** 2 c2 = retdict["radii"]["value"][2] ** 2 onemboa2 = 1.0 - b2 / a ** 2 units = {} values = {} for c in ["RA", "DEC", "NP_RA", "NP_DEC"]: units[c] = retdict["data"][c]["data"]["unit"] values[c] = retdict["data"][c]["data"]["value"] av = 0.0 nrows = len(retdict["data"]["RA"]["data"]["value"]) for i in xrange(nrows): radec = me.direction( "app", {"unit": units["RA"], "value": values["RA"][i]}, {"unit": units["DEC"], "value": values["DEC"][i]} ) np = me.direction( "j2000", {"unit": units["NP_RA"], "value": values["NP_RA"][i]}, {"unit": units["NP_DEC"], "value": values["NP_DEC"][i]}, ) szeta2 = scipy.sin(qa.convert(me.separation(radec, np), "rad")["value"]) ** 2 csinz2 = c2 * szeta2 bcosz2 = b2 * (1.0 - szeta2) bcz2pcsz2 = bcosz2 + csinz2 m = csinz2 * onemboa2 / bcz2pcsz2 av += (scipy.sqrt(bcz2pcsz2) * scipy.special.ellipe(m) - av) / (i + 1.0) return scipy.sqrt(2.0 * a * av / scipy.pi)
def noise(coords, nrandom = 50, imagenames=[], stampsize=32, method = 'mean', weighting = 'simga2', maskradius=None, psfmode = 'point'): import stacker import numpy as np from taskinit import ia, qa ia.open(imagenames[0]) beam = qa.convert(ia.restoringbeam()['major'], 'rad')['value'] ia.done() # if coords.coord_type == 'physical': # coords = stacker.getPixelCoords(coords, imagenames) _allocate_buffers(imagenames, stampsize, len(coords)*len(imagenames)) dist = [] for i in range(nrandom): random_coords = stacker.randomizeCoords(coords, beam=beam) random_coords = stacker.getPixelCoords(random_coords, imagenames) _load_stack(random_coords, psfmode) if method == 'mean' and weighting == 'sigma2': random_coords = _calculate_sigma2_weights(random_coords, maskradius) elif method == 'mean' and weighting == 'sigma': random_coords = _calculate_sigma_weights(random_coords, maskradius) stacked_im = _stack_stack(method, random_coords) dist.append(stacked_im[int(stampsize/2+0.5), int(stampsize/2+0.5),0,0]) return np.std(dist)
def parse_figsize(figsize): """ return figsize in inches """ casalog.post('parse_figsize input: {input}'.format(input=figsize), priority='DEBUG') parsed = None if figsize is not None and isinstance(figsize, str) and len(figsize) > 0: size_list = figsize.split(',') size_inch_list = [x / 25.4 for s in size_list for x in qa.getvalue(qa.convert(qa.quantity(s),outunit='mm'))] if len(size_inch_list) == 1: s = size_inch_list[0] parsed = (s, s) else: parsed = tuple(size_inch_list[:2]) casalog.post('parse_figsize output: {output}'.format(output=parsed), priority='DEBUG') return parsed
def __call__(self, dx, dy, nu=None): """ Returns primary beam correction for translation (dx, dy) from center. Keyword arguments: dx -- Projected separation in x direction in radians dy -- Projected separation in y direction in radians nu -- Frequency, either self.nu0 or nu must be set. """ from scipy.constants import c from taskinit import qa if nu is None: if self.nu0 is None: return 0. nu = self.nu0 dishdia = qa.convert(self.dishdia, 'm')['value'] vp_fwhm = 1.22 * c / nu / dishdia return np.exp(-4. * np.log(2) * (dx**2 + dy**2) / vp_fwhm**2)
def imreg(vis=None, ephem=None, msinfo=None, imagefile=None, timerange=None, reftime=None, fitsfile=None, beamfile=None, offsetfile=None, toTb=None, sclfactor=1.0, verbose=False, p_ang=False, overwrite=True, usephacenter=True, deletehistory=False, subregion=[], docompress=False): ''' main routine to register CASA images Required Inputs: vis: STRING. CASA measurement set from which the image is derived imagefile: STRING or LIST. name of the input CASA image timerange: STRING or LIST. timerange used to generate the CASA image, must have the same length as the input images. Each element should be in CASA standard time format, e.g., '2012/03/03/12:00:00~2012/03/03/13:00:00' Optional Inputs: msinfo: DICTIONARY. CASA MS information, output from read_msinfo. If not provided, generate one from the supplied vis ephem: DICTIONARY. solar ephem, output from read_horizons. If not provided, query JPL Horizons based on time info of the vis (internet connection required) fitsfile: STRING or LIST. name of the output registered fits files reftime: STRING or LIST. Each element should be in CASA standard time format, e.g., '2012/03/03/12:00:00' offsetfile: optionally provide an offset with a series of solar x and y offsets with timestamps toTb: Bool. Convert the default Jy/beam to brightness temperature? sclfactor: scale the image values up by its value (to compensate VLA 20 dB attenuator) verbose: Bool. Show more diagnostic info if True. usephacenter: Bool -- if True, correct for the RA and DEC in the ms file based on solar empheris. Otherwise assume the phasecenter is correctly pointed to the solar disk center (EOVSA case) subregion: Region selection. See 'help par.region' for details. Usage: >>> from suncasa.utils import helioimage2fits as hf >>> hf.imreg(vis='mydata.ms', imagefile='myimage.image', fitsfile='myimage.fits', timerange='2017/08/21/20:21:10~2017/08/21/20:21:18') The output fits file is 'myimage.fits' History: BC (sometime in 2014): function was first wrote, followed by a number of edits by BC and SY BC (2019-07-16): Added checks for stokes parameter. Verified that for converting from Jy/beam to brightness temperature, the convention of 2*k_b*T should always be used. I.e., for unpolarized source, stokes I, RR, LL, XX, YY, etc. in the output CASA images from (t)clean should all have same values of radio intensity (in Jy/beam) and brightness temperature (in K). ''' if deletehistory: ms_clearhistory(vis) if not imagefile: raise ValueError('Please specify input image') if not timerange: raise ValueError('Please specify timerange of the input image') if type(imagefile) == str: imagefile = [imagefile] if type(timerange) == str: timerange = [timerange] if not fitsfile: fitsfile = [img + '.fits' for img in imagefile] if type(fitsfile) == str: fitsfile = [fitsfile] nimg = len(imagefile) if len(timerange) != nimg: raise ValueError( 'Number of input images does not equal to number of timeranges!') if len(fitsfile) != nimg: raise ValueError( 'Number of input images does not equal to number of output fits files!' ) nimg = len(imagefile) if verbose: print(str(nimg) + ' images to process...') if reftime: # use as reference time to find solar disk RA and DEC to register the image, but not the actual timerange associated with the image if type(reftime) == str: reftime = [reftime] * nimg if len(reftime) != nimg: raise ValueError( 'Number of reference times does not match that of input images!' ) helio = ephem_to_helio(vis, ephem=ephem, msinfo=msinfo, reftime=reftime, usephacenter=usephacenter) else: # use the supplied timerange to register the image helio = ephem_to_helio(vis, ephem=ephem, msinfo=msinfo, reftime=timerange, usephacenter=usephacenter) if toTb: (bmajs, bmins, bpas, beamunits, bpaunits) = getbeam(imagefile=imagefile, beamfile=beamfile) for n, img in enumerate(imagefile): if verbose: print('processing image #' + str(n) + ' ' + img) fitsf = fitsfile[n] timeran = timerange[n] # obtain duration of the image as FITS header exptime try: [tbg0, tend0] = timeran.split('~') tbg_d = qa.getvalue(qa.convert(qa.totime(tbg0), 'd'))[0] tend_d = qa.getvalue(qa.convert(qa.totime(tend0), 'd'))[0] tdur_s = (tend_d - tbg_d) * 3600. * 24. dateobs = qa.time(qa.quantity(tbg_d, 'd'), form='fits', prec=10)[0] except: print('Error in converting the input timerange: ' + str(timeran) + '. Proceeding to the next image...') continue hel = helio[n] if not os.path.exists(img): warnings.warn('{} does not existed!'.format(img)) else: if os.path.exists(fitsf) and not overwrite: raise ValueError( 'Specified fits file already exists and overwrite is set to False. Aborting...' ) else: p0 = hel['p0'] tb.open(img + '/logtable', nomodify=False) nobs = tb.nrows() tb.removerows([i + 1 for i in range(nobs - 1)]) tb.close() ia.open(img) imr = ia.rotate(pa=str(-p0) + 'deg') if subregion is not []: imr = imr.subimage(region=subregion) imr.tofits(fitsf, history=False, overwrite=overwrite) imr.close() imsum = ia.summary() ia.close() ia.done() # construct the standard fits header # RA and DEC of the reference pixel crpix1 and crpix2 (imra, imdec) = (imsum['refval'][0], imsum['refval'][1]) # find out the difference of the image center to the CASA phase center # RA and DEC difference in arcseconds ddec = degrees((imdec - hel['dec_fld'])) * 3600. dra = degrees((imra - hel['ra_fld']) * cos(hel['dec_fld'])) * 3600. # Convert into image heliocentric offsets prad = -radians(hel['p0']) dx = (-dra) * cos(prad) - ddec * sin(prad) dy = (-dra) * sin(prad) + ddec * cos(prad) if offsetfile: try: offset = np.load(offsetfile) except: raise ValueError( 'The specified offsetfile does not exist!') reftimes_d = offset['reftimes_d'] xoffs = offset['xoffs'] yoffs = offset['yoffs'] timg_d = hel['reftime'] ind = bisect.bisect_left(reftimes_d, timg_d) xoff = xoffs[ind - 1] yoff = yoffs[ind - 1] else: xoff = hel['refx'] yoff = hel['refy'] if verbose: print( 'offset of image phase center to visibility phase center (arcsec): dx={0:.2f}, dy={1:.2f}' .format(dx, dy)) print( 'offset of visibility phase center to solar disk center (arcsec): dx={0:.2f}, dy={1:.2f}' .format(xoff, yoff)) (crval1, crval2) = (xoff + dx, yoff + dy) # update the fits header to heliocentric coordinates hdu = pyfits.open(fitsf, mode='update') hdu[0].verify('fix') header = hdu[0].header dshape = hdu[0].data.shape ndim = hdu[0].data.ndim (cdelt1, cdelt2) = (-header['cdelt1'] * 3600., header['cdelt2'] * 3600. ) # Original CDELT1, 2 are for RA and DEC in degrees header['cdelt1'] = cdelt1 header['cdelt2'] = cdelt2 header['cunit1'] = 'arcsec' header['cunit2'] = 'arcsec' header['crval1'] = crval1 header['crval2'] = crval2 header['ctype1'] = 'HPLN-TAN' header['ctype2'] = 'HPLT-TAN' header['date-obs'] = dateobs # begin time of the image if not p_ang: hel['p0'] = 0 try: # this works for pyfits version of CASA 4.7.0 but not CASA 4.6.0 if tdur_s: header.set('exptime', tdur_s) else: header.set('exptime', 1.) header.set('p_angle', hel['p0']) header.set('hgln_obs', 0.) header.set('rsun_ref', sun.constants.radius.value) if sunpyver <= 1: header.set( 'dsun_obs', sun.sunearth_distance(Time(dateobs)).to(u.meter).value) header.set( 'rsun_obs', sun.solar_semidiameter_angular_size( Time(dateobs)).value) header.set( 'hglt_obs', sun.heliographic_solar_center(Time(dateobs))[1].value) else: header.set( 'dsun_obs', sun.earth_distance(Time(dateobs)).to(u.meter).value) header.set('rsun_obs', sun.angular_radius(Time(dateobs)).value) header.set('hglt_obs', sun.L0(Time(dateobs)).value) except: # this works for astropy.io.fits if tdur_s: header.append(('exptime', tdur_s)) else: header.append(('exptime', 1.)) header.append(('p_angle', hel['p0'])) header.append(('hgln_obs', 0.)) header.append(('rsun_ref', sun.constants.radius.value)) if sunpyver <= 1: header.append( ('dsun_obs', sun.sunearth_distance(Time(dateobs)).to( u.meter).value)) header.append(('rsun_obs', sun.solar_semidiameter_angular_size( Time(dateobs)).value)) header.append(('hglt_obs', sun.heliographic_solar_center( Time(dateobs))[1].value)) else: header.append( ('dsun_obs', sun.earth_distance(Time(dateobs)).to(u.meter).value)) header.append( ('rsun_obs', sun.angular_radius(Time(dateobs)).value)) header.append(('hglt_obs', sun.L0(Time(dateobs)).value)) # check if stokes parameter exist exist_stokes = False stokes_mapper = { 'I': 1, 'Q': 2, 'U': 3, 'V': 4, 'RR': -1, 'LL': -2, 'RL': -3, 'LR': -4, 'XX': -5, 'YY': -6, 'XY': -7, 'YX': -8 } if 'CRVAL3' in header.keys(): if header['CTYPE3'] == 'STOKES': stokenum = header['CRVAL3'] exist_stokes = True if 'CRVAL4' in header.keys(): if header['CTYPE4'] == 'STOKES': stokenum = header['CRVAL4'] exist_stokes = True if exist_stokes: if stokenum in stokes_mapper.values(): stokesstr = list(stokes_mapper.keys())[list( stokes_mapper.values()).index(stokenum)] else: print('Stokes parameter {0:d} not recognized'.format( stokenum)) if verbose: print('This image is in Stokes ' + stokesstr) else: print( 'STOKES Information does not seem to exist! Assuming Stokes I' ) stokenum = 1 # intensity units to brightness temperature if toTb: # get restoring beam info bmaj = bmajs[n] bmin = bmins[n] beamunit = beamunits[n] data = hdu[ 0].data # remember the data order is reversed due to the FITS convension keys = list(header.keys()) values = list(header.values()) # which axis is frequency? faxis = keys[values.index('FREQ')][-1] faxis_ind = ndim - int(faxis) # find out the polarization of this image k_b = qa.constants('k')['value'] c_l = qa.constants('c')['value'] # Always use 2*kb for all polarizations const = 2. * k_b / c_l**2 if header['BUNIT'].lower() == 'jy/beam': header['BUNIT'] = 'K' header['BTYPE'] = 'Brightness Temperature' for i in range(dshape[faxis_ind]): nu = header['CRVAL' + faxis] + header['CDELT' + faxis] * ( i + 1 - header['CRPIX' + faxis]) if header['CUNIT' + faxis] == 'KHz': nu *= 1e3 if header['CUNIT' + faxis] == 'MHz': nu *= 1e6 if header['CUNIT' + faxis] == 'GHz': nu *= 1e9 if len(bmaj) > 1: # multiple (per-plane) beams bmajtmp = bmaj[i] bmintmp = bmin[i] else: # one single beam bmajtmp = bmaj[0] bmintmp = bmin[0] if beamunit == 'arcsec': bmaj0 = np.radians(bmajtmp / 3600.) bmin0 = np.radians(bmintmp / 3600.) if beamunit == 'arcmin': bmaj0 = np.radians(bmajtmp / 60.) bmin0 = np.radians(bmintmp / 60.) if beamunit == 'deg': bmaj0 = np.radians(bmajtmp) bmin0 = np.radians(bmintmp) if beamunit == 'rad': bmaj0 = bmajtmp bmin0 = bmintmp beam_area = bmaj0 * bmin0 * np.pi / (4. * log(2.)) factor = const * nu**2 # SI unit jy_to_si = 1e-26 # print(nu/1e9, beam_area, factor) factor2 = sclfactor # if sclfactor: # factor2 = 100. if faxis == '3': data[:, i, :, :] *= jy_to_si / beam_area / factor * factor2 if faxis == '4': data[ i, :, :, :] *= jy_to_si / beam_area / factor * factor2 header = fu.headerfix(header) hdu.flush() hdu.close() if ndim - np.count_nonzero(np.array(dshape) == 1) > 3: docompress = False ''' Caveat: only 1D, 2D, or 3D images are currently supported by the astropy fits compression. If a n-dimensional image data array does not have at least n-3 single-dimensional entries, force docompress to be False ''' print( 'warning: The fits data contains more than 3 non squeezable dimensions. Skipping fits compression..' ) if docompress: fitsftmp = fitsf + ".tmp.fits" os.system("mv {} {}".format(fitsf, fitsftmp)) hdu = pyfits.open(fitsftmp) hdu[0].verify('fix') header = hdu[0].header data = hdu[0].data fu.write_compressed_image_fits(fitsf, data, header, compression_type='RICE_1', quantize_level=4.0) os.system("rm -rf {}".format(fitsftmp)) if deletehistory: ms_restorehistory(vis) return fitsfile
def plt_dspec(specdata, pol='I', dmin=None, dmax=None, timerange=None, freqrange=None, timestr=True, movie=False, framedur=60., dtframe=10., goessav=None, goes_trange=None, savepng=True, savepdf=False): """ timerange: format: ['2012/03/10/18:00:00','2012/03/10/19:00:00'] freqrange: format: [1000.,1500.] in MHz movie: do a movie of dynamic spectrum? framedur: time range of each frame dtframe: time difference of consecutive frames goessav: provide an IDL save file from the sswidl GOES widget output goes_trange: plot only the specified time range for goes timestr: display time as strings on X-axis -- currently the times do not update themselves when zooming in """ # Set up variables import matplotlib.pyplot as plt import numpy from numpy import log10 from astropy.time import Time if pol != 'RR' and pol != 'LL' and pol != 'RRLL' and pol != 'I' and pol != 'V' and pol != 'IV': print "Please enter 'RR', 'LL', 'RRLL', 'I', 'V', 'IV' for pol" return 0 if type(specdata) is str: specdata = np.load(specdata) bl = specdata['bl'].item() try: (npol, nbl, nfreq, ntim) = specdata['spec'].shape spec = specdata['spec'] tim = specdata['tim'] tim_ = Time(tim / 3600. / 24., format='mjd') tim_plt = tim_.plot_date freq = specdata['freq'] if not 'bl' in vars(): bl = specdata['bl'] except: print('format of specdata not recognized. Check your input') return -1 if timerange: if type(timerange[0]) is str: timerange = [ qa.convert(qa.quantity(t), 's')['value'] for t in timerange ] tidx = np.where((tim >= timerange[0]) & (tim <= timerange[1]))[0] else: tidx = range(ntim) if freqrange: fidx = np.where((freq >= freqrange[0] * 1e6) & (freq <= freqrange[1] * 1e6))[0] else: fidx = range(nfreq) # setup plot parameters print 'ploting dynamic spectrum...' spec_med = np.median(np.absolute(spec)) # if not dmin: # dmin = spec_med / 20. # if not dmax: # dmax = spec_med * 5. # do the plot for b in range(nbl): if pol != 'RRLL' and pol != 'IV': if pol == 'RR': spec_plt = spec[0, b, :, :] elif pol == 'LL': spec_plt = spec[1, b, :, :] elif pol == 'I': spec_plt = (spec[0, b, :, :] + spec[1, b, :, :]) / 2. elif pol == 'V': spec_plt = (spec[0, b, :, :] - spec[1, b, :, :]) / 2. if movie: f = plt.figure(figsize=(16, 8), dpi=100) if goessav: gs = gridspec.GridSpec(2, 1, height_ratios=[2, 1]) gs.update(left=0.06, right=0.97, top=0.95, bottom=0.06) ax1 = f.add_subplot(gs[0]) ax2 = f.add_subplot(gs[1]) if os.path.exists(goessav): goes = readsav(goessav) # IDL anytim 0 sec correspond to 1979 Jan 01, convert to mjd time anytimbase = qa.convert( qa.quantity('1979/01/01/00:00:00'), 's')['value'] mjdbase = goes['utbase'] + anytimbase ts = goes['tarray'] + mjdbase lc0 = goes['yclean'][0, :] lc1 = goes['yclean'][1, :] else: ax1 = f.add_subplot(211) tstart = tim[tidx[0]] tend = tim[tidx[-1]] tstartstr = qa.time(qa.quantity(tstart, 's'))[0] tendstr = qa.time(qa.quantity(tend, 's'))[0] nfrm = int((tend - tstart) / dtframe) + 1 print 'Movie mode set. ' + str( nfrm ) + ' frames to plot from ' + tstartstr + ' to ' + tendstr for i in range(nfrm): if (i != 0) and (i % 10 == 0): print str(i) + ' frames done' timeran = [ tstart + i * dtframe, tstart + i * dtframe + framedur ] tidx1 = np.where((tim >= timeran[0]) & (tim <= timeran[1]))[0] tim1 = tim_[tidx1] freq1 = freq[fidx] / 1e9 spec_plt1 = spec_plt[fidx, :][:, tidx1] ax1.pcolormesh(tim1.plot_date, freq1, spec_plt1, cmap='jet', vmin=dmin, vmax=dmax) ax1.set_xlim(tim1[0].plot_date, tim1[-1].plot_date) ax1.set_ylim(freq1[0], freq1[-1]) ax1.set_ylabel('Frequency (GHz)') ax1.set_title('Dynamic spectrum @ bl ' + bl.split(';')[b] + ', pol ' + pol) if timestr: # date_format = mdates.DateFormatter('%H:%M:%S.%f') # ax1.xaxis_date() # ax1.xaxis.set_major_formatter(date_format) locator = AutoDateLocator() ax1.xaxis.set_major_locator(locator) ax1.xaxis.set_major_formatter( AutoDateFormatter(locator)) ax1.set_autoscale_on(False) if goessav: if goes_trange: if type(goes_trange[0]) is str: goes_trange = [ qa.convert(qa.quantity(t), 's')['value'] for t in goes_trange ] idx = np.where((ts >= goes_trange[0]) & (ts <= goes_trange[1]))[0] else: idx = range(len(ts)) ts_plt = ts[idx] lc0_plt = lc0[idx] utbase = qa.convert(qa.quantity('0001/01/01/00:00:00'), 'd')['value'] + 1 ts_plt_d = ts_plt / 3600. / 24. - utbase ax2.plot_date(ts_plt_d, lc0_plt, 'b-') ax2.axvspan(tim1[0].mjd - utbase, tim1[-1].mjd - utbase, color='red', alpha=0.5) ax2.set_yscale('log') ax2.set_title('GOES 1-8 A') tstartstr_ = tim1[0].datetime.strftime( '%Y-%m-%dT%H%M%S.%f')[:-3] tendstr_ = tim1[1].datetime.strftime('%H%M%S.%f')[:-3] timstr = tstartstr_ + '-' + tendstr_ figfile = 'dspec_t' + timstr + '.png' if not os.path.isdir('dspec'): os.makedirs('dspec') f.savefig('dspec/' + figfile) plt.cla() else: f = plt.figure(figsize=(8, 4), dpi=100) ax = f.add_subplot(111) freqghz = freq / 1e9 ax.pcolormesh(tim_plt, freqghz, spec_plt, cmap='jet', vmin=dmin, vmax=dmax) ax.set_xlim(tim_plt[tidx[0]], tim_plt[tidx[-1]]) ax.set_ylim(freqghz[fidx[0]], freqghz[fidx[-1]]) try: from sunpy import lightcurve from sunpy.time import TimeRange, parse_time t1 = tim_[tidx[0]] t2 = tim_[tidx[-1]] tr = TimeRange(t1.iso, t2.iso) goes = lightcurve.GOESLightCurve.create(tr) goes.data['xrsb'] = 2 * (np.log10(goes.data['xrsb'])) + 26 xx = [str(ll) for ll in np.array(goes.data.index)] yy = np.array(goes.data['xrsb']) ax.plot(Time(xx).mjd * 24 * 3600, yy, c='yellow') rightaxis_label_time = Time(xx[-1]).mjd * 24 * 3600 ax.text(rightaxis_label_time, 9.6, 'A', fontsize='15') ax.text(rightaxis_label_time, 11.6, 'B', fontsize='15') ax.text(rightaxis_label_time, 13.6, 'C', fontsize='15') ax.text(rightaxis_label_time, 15.6, 'M', fontsize='15') ax.text(rightaxis_label_time, 17.6, 'X', fontsize='15') except: pass def format_coord(x, y): col = np.argmin(np.absolute(tim_plt - x)) row = np.argmin(np.absolute(freqghz - y)) if col >= 0 and col < ntim and row >= 0 and row < nfreq: timstr = tim_[col].isot flux = spec_plt[row, col] return 'time {0} = {1}, freq = {2:.3f} GHz, flux = {3:.2f} Jy'.format( col, timstr, y, flux) else: return 'x = {0}, y = {1:.3f}'.format(x, y) ax.format_coord = format_coord ax.set_ylabel('Frequency (GHz)') if bl: ax.set_title('Dynamic spectrum @ bl ' + bl.split(';')[b] + ', pol ' + pol) else: ax.set_title('Medium dynamic spectrum') if timestr: # date_format = mdates.DateFormatter('%H:%M:%S.%f') # ax.xaxis_date() # ax.xaxis.set_major_formatter(date_format) locator = AutoDateLocator() ax.xaxis.set_major_locator(locator) ax.xaxis.set_major_formatter(AutoDateFormatter(locator)) ax.set_autoscale_on(False) else: f = plt.figure(figsize=(8, 6), dpi=100) R_plot = np.absolute(spec[0, b, :, :]) L_plot = np.absolute(spec[1, b, :, :]) I_plot = (R_plot + L_plot) / 2. V_plot = (R_plot - L_plot) / 2. if pol == 'RRLL': spec_plt_1 = R_plot spec_plt_2 = L_plot polstr = ['RR', 'LL'] if pol == 'IV': spec_plt_1 = I_plot spec_plt_2 = V_plot polstr = ['I', 'V'] ax1 = f.add_subplot(211) freqghz = freq / 1e9 ax1.pcolormesh(tim_plt, freqghz, spec_plt_1, cmap='jet', vmin=dmin, vmax=dmax) ax1.set_xlim(tim_plt[tidx[0]], tim_plt[tidx[-1]]) ax1.set_ylim(freqghz[fidx[0]], freqghz[fidx[-1]]) def format_coord(x, y): col = np.argmin(np.absolute(tim_plt - x)) row = np.argmin(np.absolute(freqghz - y)) if col >= 0 and col < ntim and row >= 0 and row < nfreq: timstr = tim_[col].isot flux = spec_plt[row, col] return 'time {0} = {1}, freq = {2:.3f} GHz, flux = {3:.2f} Jy'.format( col, timstr, y, flux) else: return 'x = {0}, y = {1:.3f}'.format(x, y) ax1.format_coord = format_coord ax1.set_ylabel('Frequency (GHz)') if timestr: # date_format = mdates.DateFormatter('%H:%M:%S.%f') # ax1.xaxis_date() # ax1.xaxis.set_major_formatter(date_format) locator = AutoDateLocator() ax1.xaxis.set_major_locator(locator) ax1.xaxis.set_major_formatter(AutoDateFormatter(locator)) ax1.set_title('Dynamic spectrum @ bl ' + bl.split(';')[b] + ', pol ' + polstr[0]) ax1.set_autoscale_on(False) ax2 = f.add_subplot(212) ax2.pcolormesh(tim_plt, freqghz, spec_plt_2, cmap='jet', vmin=dmin, vmax=dmax) ax2.set_xlim(tim_plt[tidx[0]], tim_plt[tidx[-1]]) ax2.set_ylim(freqghz[fidx[0]], freqghz[fidx[-1]]) if timestr: # date_format = mdates.DateFormatter('%H:%M:%S.%f') # ax2.xaxis_date() # ax2.xaxis.set_major_formatter(date_format) locator = AutoDateLocator() ax2.xaxis.set_major_locator(locator) ax2.xaxis.set_major_formatter(AutoDateFormatter(locator)) def format_coord(x, y): col = np.argmin(np.absolute(tim_plt - x)) row = np.argmin(np.absolute(freqghz - y)) if col >= 0 and col < ntim and row >= 0 and row < nfreq: timstr = tim_[col].isot flux = spec_plt[row, col] return 'time {0} = {1}, freq = {2:.3f} GHz, flux = {3:.2f} Jy'.format( col, timstr, y, flux) else: return 'x = {0}, y = {1:.3f}'.format(x, y) ax2.format_coord = format_coord ax2.set_ylabel('Frequency (GHz)') ax2.set_title('Dynamic spectrum @ bl ' + bl.split(';')[b] + ', pol ' + polstr[1]) ax2.set_autoscale_on(False)
if nspw > 1: casalog.post('Separate MS into %s spws'%nspw) config['nspw'] = nspw config['interpolation'] = interpolation if restfreq != '': config['restfreq'] = restfreq if outframe != '': config['outframe'] = outframe if phasecenter != '': config['phasecenter'] = phasecenter config['veltype'] = veltype config['preaverage'] = preaverage # Only parse timeaverage parameters when timebin > 0s if timeaverage: tb = qa.convert(qa.quantity(timebin), 's')['value'] if not tb > 0: raise Exception, "Parameter timebin must be > '0s' to do time averaging" if timeaverage: casalog.post('Parse time averaging parameters') config['timeaverage'] = True config['timebin'] = timebin config['timespan'] = timespan config['maxuvwdistance'] = maxuvwdistance if docallib: casalog.post('Parse docallib parameters') mycallib = callibrary() mycallib.read(callib) config['calibration'] = True
retdict[hk] = { 'unit': headers[hk]['unit'], 'value': float(retdict[hk]) } except Exception, e: print "Error converting header", hk, "to a Quantity." print "retdict[hk] =", retdict[hk] raise e elif hk == 'GeoLong': long_lat_alt = retdict[hk].split(',') retdict['GeoLong'] = float(long_lat_alt[0]) retdict['GeoLat'] = float(long_lat_alt[1]) retdict['GeoDist'] = float(long_lat_alt[2]) elif hk == 'dMJD': retdict[hk] = qa.convert( qa.totime(retdict[hk].replace('minutes', 'min')), 'd')['value'] elif hk == 'orb_per': unit = 'h' retrograde = False if 'd' in retdict[hk].lower(): unit = 'd' # Actually this is most common. if 'r' in retdict[hk].lower(): retrograde = True value = get_num_from_str(retdict[hk], 'orbital period') if value != False: if retrograde and value > 0.0: value = -value retdict[hk] = {'unit': unit, 'value': value} else: del retdict[hk]
def flagdata( vis, mode, autocorr, # mode manual parameter inpfile, # mode list parameters reason, tbuff, spw, # data selection parameters field, antenna, uvrange, timerange, correlation, scan, intent, array, observation, feed, clipminmax, # mode clip parameters datacolumn, clipoutside, channelavg, chanbin, timeavg, timebin, clipzeros, quackinterval, # mode quack parameters quackmode, quackincrement, tolerance, # mode shadow parameter addantenna, lowerlimit, # mode elevation parameters upperlimit, ntime, # mode tfcrop combinescans, timecutoff, freqcutoff, timefit, freqfit, maxnpieces, flagdimension, usewindowstats, halfwin, extendflags, winsize, # rflag parameters timedev, freqdev, timedevscale, freqdevscale, spectralmax, spectralmin, antint_ref_antenna, # mode antint minchanfrac, verbose, extendpols, # mode extend growtime, growfreq, growaround, flagneartime, flagnearfreq, minrel, # mode summary maxrel, minabs, maxabs, spwchan, spwcorr, basecnt, fieldcnt, name, action, # run or not the tool display, flagbackup, savepars, # save the current parameters to FLAG_CMD or to a file cmdreason, # reason to save to flag cmd outfile, # output file to save flag commands overwrite, # overwrite the outfile file writeflags # HIDDEN parameter ): # # Task flagdata # Flags data from an MS or calibration table based on data selection in various ways casalog.origin('flagdata') if (action == 'none' or action == '' or action == 'calculate'): flagbackup = False # SMC: moved the flagbackup to before initializing the cluster. # Note that with this change, a flag backup will be created even if # an error happens that prevents the flagger tool from running. if (mode != 'summary' and flagbackup): casalog.post('Backup original flags before applying new flags') fh.backupFlags(aflocal=None, msfile=vis, prename='flagdata') # Set flagbackup to False because only the controller # should create a backup flagbackup = False # Initialize the helper class orig_locals = copy.deepcopy(locals()) FHelper = FlagHelper() # Check if vis is a MS, MMS or cal table: # typevis = 1 --> cal table # typevis = 0 --> MS # typevis = 2 --> MMS iscal = False typevis = fh.isCalTable(vis) if typevis == 1: iscal = True # ***************** Input is MMS -- Parallel Processing *********************** if FHelper.isMPIEnabled( ) and typevis == 2 and action != '' and action != 'none': # Create a temporary input file with .tmp extension. # Use this file for all the processing from now on. if (isinstance(inpfile,str) and inpfile != '') or \ (isinstance(inpfile, list) and os.path.isfile(inpfile[0])): inpfile = FHelper.setupInputFile(inpfile) if inpfile != None: orig_locals['inpfile'] = inpfile if outfile != '': outfile = os.path.abspath(outfile) orig_locals['outfile'] = outfile if isinstance(addantenna, str) and addantenna != '': addantenna = os.path.abspath(addantenna) orig_locals['addantenna'] = addantenna if isinstance(timedev, str) and timedev != '': timedev = os.path.abspath(timedev) orig_locals['timedev'] = timedev if isinstance(freqdev, str) and freqdev != '': freqdev = os.path.abspath(freqdev) orig_locals['freqdev'] = freqdev FHelper.__init__(orig_locals) # For tests only # FHelper.bypassParallelProcessing(1) FHelper.setupCluster('flagdata') # (CAS-4119): Override summary minabs,maxabs,minrel,maxrel # so that it is done after consolidating the summaries # By-pass options to filter summary filterSummary = False if ((mode == 'summary') and ((minrel != 0.0) or (maxrel != 1.0) or (minabs != 0) or (maxabs != -1))): filterSummary = True myms = mstool() myms.open(vis) subMS_list = myms.getreferencedtables() myms.close() if (minrel != 0.0): minreal_dict = create_arg_dict(subMS_list, 0.0) FHelper.override_arg('minrel', minreal_dict) if (maxrel != 1.0): maxrel_dict = create_arg_dict(subMS_list, 1.0) FHelper.override_arg('maxrel', maxrel_dict) if (minabs != 0): minabs_dict = create_arg_dict(subMS_list, 0) FHelper.override_arg('minabs', minabs_dict) if (maxabs != -1): maxabs_dict = create_arg_dict(subMS_list, -1) FHelper.override_arg('maxabs', maxabs_dict) # By-pass options to filter summary if savepars: myms = mstool() myms.open(vis) subMS_list = myms.getreferencedtables() myms.close() savepars_dict = create_arg_dict(subMS_list, False) FHelper.override_arg('savepars', savepars_dict) # Execute the parallel engines retVar = FHelper.go() # Save overall RFlag values into timedev/freqdev files once the subMS results have # been consolidated, if needed for RFlag (introduced in CAS-11850) opts_dict = { 'writeflags': writeflags, 'timedev': timedev, 'freqdev': freqdev } fh.save_rflag_consolidated_files(mode, action, retVar, opts_dict, inpfile) # In async mode return the job ids if ParallelTaskHelper.getAsyncMode(): return retVar else: # Filter summary at MMS level if (mode == 'summary'): if filterSummary: retVar = filter_summary(retVar, minrel, maxrel, minabs, maxabs) return retVar # Save parameters at MMS level elif savepars: action = 'none' else: return retVar summary_stats = {} # ***************** Input is a normal MS/cal table **************** # Create local tools # aflocal = casac.agentflagger() aflocal = aftool() mslocal = mstool() try: # Verify the ntime value newtime = 0.0 if type(ntime) == float or type(ntime) == int: if ntime <= 0: raise Exception, 'Parameter ntime cannot be < = 0' else: # units are seconds newtime = float(ntime) elif type(ntime) == str: if ntime == 'scan': # iteration time step is a scan newtime = 0.0 else: # read the units from the string qtime = qa.quantity(ntime) if qtime['unit'] == 'min': # convert to seconds qtime = qa.convert(qtime, 's') elif qtime['unit'] == '': qtime['unit'] = 's' # check units if qtime['unit'] == 's': newtime = qtime['value'] else: casalog.post( 'Cannot convert units of ntime. Will use default 0.0s', 'WARN') casalog.post( "New ntime is of type %s and value %s" % (type(newtime), newtime), 'DEBUG') # Open the MS and attach it to the tool if ((type(vis) == str) & (os.path.exists(vis))): aflocal.open(vis, newtime) else: raise Exception, 'Visibility data set not found - please verify the name' # Get the parameters for the mode agent_pars = {} # By default, write flags to the MS writeflags = True # Only the apply action writes to the MS # action=apply --> write to the MS # action=calculate --> do not write to the MS # action='' --> do not run the tool and do not write to the MS if action != 'apply': writeflags = False # Default mode if mode == '' or mode == 'manualflag': mode = 'manual' # Read in the list of commands # Make a dictionary of the input commands. Select by reason if requested flagcmd = {} if mode == 'list': casalog.post('List mode is active') doPadding = True try: # If tbuff is requested, read and Parse if tbuff == 0.0 or tbuff == [] or tbuff == None: doPadding = False if doPadding: casalog.post('Will apply time buffer padding') # inpfile is a file if isinstance(inpfile, str): inpfile = [inpfile] # read in the list and do a simple parsing to apply tbuff flaglist = fh.readAndParse(inpfile, tbuff) else: flaglist = fh.get_flag_cmd_list(inpfile) # Parse and create a dictionary flagcmd = fh.parseDictionary(flaglist, reason) # Validate the dictionary. # IMPORTANT: if any parameter changes its type, the following # function needs to be updated. The same if any new parameter is # added or removed from the task fh.evaluateFlagParameters(flagcmd, orig_locals) # List of flag commands in dictionary vrows = flagcmd.keys() casalog.post('%s' % flagcmd, 'DEBUG1') except Exception, instance: casalog.post('%s' % instance, 'ERROR') raise Exception, 'Error reading the input list. Make sure the syntax used in the list '\ 'follows the rules given in the inline help of the task.' casalog.post('Selected ' + str(vrows.__len__()) + ' commands from combined input list(s) ') elif mode == 'manual': agent_pars['autocorr'] = autocorr casalog.post('Manual mode is active')
def predictcomp(objname=None, standard=None, epoch=None, minfreq=None, maxfreq=None, nfreqs=None, prefix=None, antennalist=None, showplot=None, savefig=None, symb=None, include0amp=None, include0bl=None, blunit=None, bl0flux=None): """ Writes a component list named clist to disk and returns a dict of {'clist': clist, 'objname': objname, 'angdiam': angular diameter in radians (if used in clist), 'standard': standard, 'epoch': epoch, 'freqs': pl.array of frequencies, in GHz, 'uvrange': pl.array of baseline lengths, in m, 'amps': pl.array of predicted visibility amplitudes, in Jy, 'savedfig': False or, if made, the filename of a plot.} or False on error. objname: An object supported by standard. standard: A standard for calculating flux densities, as in setjy. Default: 'Butler-JPL-Horizons 2010' epoch: The epoch to use for the calculations. Irrelevant for extrasolar standards. minfreq: The minimum frequency to use. Example: '342.0GHz' maxfreq: The maximum frequency to use. Default: minfreq Example: '346.0GHz' Example: '', anything <= 0, or None: use minfreq. nfreqs: The number of frequencies to use. Default: 1 if minfreq == maxfreq, 2 otherwise. prefix: The component list will be saved to prefix + 'spw0_<objname>_<minfreq><epoch>.cl' Default: '' antennalist: An array configuration file as used by simdata. If given, a plot of S vs. |u| will be made. Default: '' (None, just make clist.) showplot: Whether or not to show the plot on screen. Subparameter of antennalist. Default: Necessarily False if antennalist is not specified. True otherwise. savefig: Filename for saving a plot of S vs. |u|. Subparameter of antennalist. Default: False (necessarily if antennalist is not specified) Examples: True (save to prefix + '.png') 'myplot.png' (save to myplot.png) symb: One of matplotlib's codes for plot symbols: .:,o^v<>s+xDd234hH|_ default: '.' include0amp: Force the lower limit of the amplitude axis to 0. Default: False include0bl: Force the lower limit of the baseline length axis to 0. blunit: Unit of the baseline length bl0flux: show zero baseline flux """ retval = False try: casalog.origin('predictcomp') # some parameter minimally required if objname=='': raise Exception, "Error, objname is undefined" if minfreq=='': raise Exception, "Error, minfreq is undefined" minfreqq = qa.quantity(minfreq) minfreqHz = qa.convert(minfreqq, 'Hz')['value'] try: maxfreqq = qa.quantity(maxfreq) except Exception, instance: maxfreqq = minfreqq frequnit = maxfreqq['unit'] maxfreqHz = qa.convert(maxfreqq, 'Hz')['value'] if maxfreqHz <= 0.0: maxfreqq = minfreqq maxfreqHz = minfreqHz if minfreqHz != maxfreqHz: if nfreqs < 2: nfreqs = 2 else: nfreqs = 1 freqs = pl.linspace(minfreqHz, maxfreqHz, nfreqs) myme = metool() mepoch = myme.epoch('UTC', epoch) #if not prefix: ## meanfreq = {'value': 0.5 * (minfreqHz + maxfreqHz), ## 'unit': frequnit} ## prefix = "%s%s_%.7g" % (objname, epoch.replace('/', '-'), ## minfreqq['value']) ## if minfreqHz != maxfreqHz: ## prefix += "to" + maxfreq ## else: ## prefix += minfreqq['unit'] ## prefix += "_" # prefix = '' # if not prefix: if not os.access("./",os.W_OK): casalog.post("No write access in the current directory, trying to write cl to /tmp...","WARN") prefix="/tmp/" if not os.access(prefix, os.W_OK): casalog.post("No write access to /tmp to write cl file", "SEVERE") return False else: prefixdir=os.path.dirname(prefix) if not os.path.exists(prefixdir): prefixdirs = prefixdir.split('/') if prefixdirs[0]=="": rootdir = "/" + prefixdirs[1] else: rootdir = "./" if os.access(rootdir,os.W_OK): os.makedirs(prefixdir) else: casalog.post("No write access to "+rootdir+" to write cl file", "SEVERE") return False # Get clist myim = imtool() if hasattr(myim, 'predictcomp'): casalog.post('local im instance created', 'DEBUG1') else: casalog.post('Error creating a local im instance.', 'SEVERE') return False #print "FREQS=",freqs if standard=='Butler-JPL-Horizons 2012': clist = predictSolarObjectCompList(objname, mepoch, freqs.tolist(), prefix) else: clist = myim.predictcomp(objname, standard, mepoch, freqs.tolist(), prefix) #print "created componentlist =",clist if os.path.isdir(clist): # The spw0 is useless here, but it is added by FluxStandard for the sake of setjy. casalog.post('The component list was saved to ' + clist) retval = {'clist': clist, 'objname': objname, 'standard': standard, 'epoch': mepoch, 'freqs (GHz)': 1.0e-9 * freqs, 'antennalist': antennalist} mycl = cltool() mycl.open(clist) comp = mycl.getcomponent(0) zeroblf=comp['flux']['value'] if standard=='Butler-JPL-Horizons 2012': f0=comp['spectrum']['frequency']['m0']['value'] else: f0=retval['freqs (GHz)'][0] casalog.post("Zero baseline flux %s @ %sGHz " % (zeroblf, f0),'INFO') mycl.close(False) # False prevents the stupid warning. for k in ('shape', 'spectrum'): retval[k] = comp[k] if antennalist: retval['spectrum']['bl0flux']={} retval['spectrum']['bl0flux']['value']=zeroblf[0] retval['spectrum']['bl0flux']['unit']='Jy' retval['savedfig'] = savefig if not bl0flux: zeroblf=[0.0] retval.update(plotcomp(retval, showplot, wantdict=True, symb=symb, include0amp=include0amp, include0bl=include0bl, blunit=blunit, bl0flux=zeroblf[0])) else: retval['savedfig'] = None else: casalog.post("There was an error in making the component list.", 'SEVERE')
def predictcomp(objname=None, standard=None, epoch=None, minfreq=None, maxfreq=None, nfreqs=None, prefix=None, antennalist=None, showplot=None, savefig=None, symb=None, include0amp=None, include0bl=None, blunit=None, bl0flux=None): """ Writes a component list named clist to disk and returns a dict of {'clist': clist, 'objname': objname, 'angdiam': angular diameter in radians (if used in clist), 'standard': standard, 'epoch': epoch, 'freqs': pl.array of frequencies, in GHz, 'uvrange': pl.array of baseline lengths, in m, 'amps': pl.array of predicted visibility amplitudes, in Jy, 'savedfig': False or, if made, the filename of a plot.} or False on error. objname: An object supported by standard. standard: A standard for calculating flux densities, as in setjy. Default: 'Butler-JPL-Horizons 2010' epoch: The epoch to use for the calculations. Irrelevant for extrasolar standards. minfreq: The minimum frequency to use. Example: '342.0GHz' maxfreq: The maximum frequency to use. Default: minfreq Example: '346.0GHz' Example: '', anything <= 0, or None: use minfreq. nfreqs: The number of frequencies to use. Default: 1 if minfreq == maxfreq, 2 otherwise. prefix: The component list will be saved to prefix + '<objname>_spw0_<minfreq><epoch>.cl' Default: '' antennalist: An array configuration file as used by simdata. If given, a plot of S vs. |u| will be made. Default: '' (None, just make clist.) showplot: Whether or not to show the plot on screen. Subparameter of antennalist. Default: Necessarily False if antennalist is not specified. True otherwise. savefig: Filename for saving a plot of S vs. |u|. Subparameter of antennalist. Default: False (necessarily if antennalist is not specified) Examples: True (save to prefix + '.png') 'myplot.png' (save to myplot.png) symb: One of matplotlib's codes for plot symbols: .:,o^v<>s+xDd234hH|_ default: '.' include0amp: Force the lower limit of the amplitude axis to 0. Default: False include0bl: Force the lower limit of the baseline length axis to 0. blunit: Unit of the baseline length bl0flux: show zero baseline flux """ retval = False try: casalog.origin('predictcomp') # some parameter minimally required if objname == '': raise Exception, "Error, objname is undefined" if minfreq == '': raise Exception, "Error, minfreq is undefined" minfreqq = qa.quantity(minfreq) minfreqHz = qa.convert(minfreqq, 'Hz')['value'] try: maxfreqq = qa.quantity(maxfreq) except Exception, instance: maxfreqq = minfreqq frequnit = maxfreqq['unit'] maxfreqHz = qa.convert(maxfreqq, 'Hz')['value'] if maxfreqHz <= 0.0: maxfreqq = minfreqq maxfreqHz = minfreqHz if minfreqHz != maxfreqHz: if nfreqs < 2: nfreqs = 2 else: nfreqs = 1 freqs = pl.linspace(minfreqHz, maxfreqHz, nfreqs) myme = metool() mepoch = myme.epoch('UTC', epoch) #if not prefix: ## meanfreq = {'value': 0.5 * (minfreqHz + maxfreqHz), ## 'unit': frequnit} ## prefix = "%s%s_%.7g" % (objname, epoch.replace('/', '-'), ## minfreqq['value']) ## if minfreqHz != maxfreqHz: ## prefix += "to" + maxfreq ## else: ## prefix += minfreqq['unit'] ## prefix += "_" # prefix = '' # if not prefix: if not os.access("./", os.W_OK): casalog.post( "No write access in the current directory, trying to write cl to /tmp...", "WARN") prefix = "/tmp/" if not os.access(prefix, os.W_OK): casalog.post("No write access to /tmp to write cl file", "SEVERE") return False else: prefixdir = os.path.dirname(prefix) if prefixdir == '/' and len(prefix) > 1: prefix = prefix + '/' prefixdir = os.path.dirname(prefix) if not os.path.exists(prefixdir): prefixdirs = prefixdir.split('/') if prefixdirs[0] == "" and len(prefixdirs) > 1: rootdir = "/" + prefixdirs[1] else: rootdir = "./" if os.access(rootdir, os.W_OK): if prefixdir != '': os.makedirs(prefixdir) else: casalog.post( "No write access to " + rootdir + " to write cl file", "SEVERE") return False # Get clist myim = imtool() if hasattr(myim, 'predictcomp'): casalog.post('local im instance created', 'DEBUG1') else: casalog.post('Error creating a local im instance.', 'SEVERE') return False #print "FREQS=",freqs # output CL file name is fixed : prefix+"spw0_"+minfreq+mepoch.cl minfreqGHz = qa.convert(qa.quantity(minfreq), 'GHz')['value'] decimalfreq = minfreqGHz - int(minfreqGHz) decimalepoch = mepoch['m0']['value'] - int(mepoch['m0']['value']) if decimalfreq == 0.0: minfreqGHzStr = str(int(minfreqGHz)) + 'GHz' else: minfreqGHzStr = str(minfreqGHz) + 'GHz' if decimalepoch == 0.0: epochStr = str(int(mepoch['m0']['value'])) + 'd' else: epochStr = str(mepoch['m0']['value']) + 'd' outfilename = "spw0_" + objname + "_" + minfreqGHzStr + epochStr + '.cl' outfilename = prefix + outfilename if (os.path.exists(outfilename) and os.path.isdir(outfilename)): shutil.rmtree(outfilename) casalog.post("Removing the existing componentlist, " + outfilename) if standard == 'Butler-JPL-Horizons 2012': clist = predictSolarObjectCompList(objname, mepoch, freqs.tolist(), prefix) else: clist = myim.predictcomp(objname, standard, mepoch, freqs.tolist(), prefix) #print "created componentlist =",clist if os.path.isdir(clist): # The spw0 is useless here, but it is added by FluxStandard for the sake of setjy. casalog.post('The component list was saved to ' + clist) retval = { 'clist': clist, 'objname': objname, 'standard': standard, 'epoch': mepoch, 'freqs (GHz)': 1.0e-9 * freqs, 'antennalist': antennalist } mycl = cltool() mycl.open(clist) comp = mycl.getcomponent(0) zeroblf = comp['flux']['value'] if standard == 'Butler-JPL-Horizons 2012': f0 = comp['spectrum']['frequency']['m0']['value'] else: f0 = retval['freqs (GHz)'][0] casalog.post("Zero baseline flux %s @ %sGHz " % (zeroblf, f0), 'INFO') mycl.close(False) # False prevents the stupid warning. for k in ('shape', 'spectrum'): retval[k] = comp[k] if antennalist: retval['spectrum']['bl0flux'] = {} retval['spectrum']['bl0flux']['value'] = zeroblf[0] retval['spectrum']['bl0flux']['unit'] = 'Jy' retval['savedfig'] = savefig if not bl0flux: zeroblf = [0.0] retval.update( plotcomp(retval, showplot, wantdict=True, symb=symb, include0amp=include0amp, include0bl=include0bl, blunit=blunit, bl0flux=zeroblf[0])) else: retval['savedfig'] = None else: casalog.post("There was an error in making the component list.", 'SEVERE')
def subvs(vis=None, outputvis=None, timerange=None, spw=None, subtime1=None, subtime2=None, splitsel=True, reverse=False, overwrite=False): """Perform vector subtraction for visibilities Keyword arguments: vis -- Name of input visibility file (MS) default: none; example: vis='ngc5921.ms' outputvis -- Name of output uv-subtracted visibility file (MS) default: none; example: outputvis='ngc5921_src.ms' timerange -- Time range of performing the UV subtraction: default='' means all times. examples: timerange = 'YYYY/MM/DD/hh:mm:ss~YYYY/MM/DD/hh:mm:ss' timerange = 'hh:mm:ss~hh:mm:ss' spw -- Select spectral window/channel. default = '' all the spectral channels. Example: spw='0:1~20' subtime1 -- Time range 1 of the background to be subtracted from the data default='' means all times. format: timerange = 'YYYY/MM/DD/hh:mm:ss~YYYY/MM/DD/hh:mm:ss' timerange = 'hh:mm:ss~hh:mm:ss' subtime2 -- Time range 2 of the backgroud to be subtracted from the data default='' means all times. examples: timerange = 'YYYY/MM/DD/hh:mm:ss~YYYY/MM/DD/hh:mm:ss' timerange = 'hh:mm:ss~hh:mm:ss' splitsel -- True or False. default = False. If splitsel = False, then the entire input measurement set is copied as the output measurement set (outputvis), with background subtracted at selected timerange and spectral channels. If splitsel = True,then only the selected timerange and spectral channels are copied into the output measurement set (outputvis). reverse -- True or False. default = False. If reverse = False, then the times indicated by subtime1 and/or subtime2 are treated as background and subtracted; If reverse = True, then reverse the sign of the background-subtracted data. The option can be used for mapping absorptive structure. overwrite -- True or False. default = False. If overwrite = True and outputvis already exists, the selected subtime and spw in the output measurment set will be replaced with background subtracted visibilities """ #check the visbility ms if not outputvis or outputvis.isspace(): raise ValueError, 'Please specify outputvis' if os.path.exists(outputvis): if overwrite: print "The already existing output measurement set will be updated." else: raise ValueError, "Output MS %s already exists - will not overwrite." % outputvis else: if not splitsel: shutil.copytree(vis, outputvis) else: ms.open(vis, nomodify=True) ms.split(outputvis, spw=spw, time=timerange, whichcol='DATA') ms.close() #define and check the time ranges if subtime1 and (type(subtime1) == str): [bsubtime1, esubtime1] = subtime1.split('~') bsubtime1sec = qa.getvalue(qa.convert(qa.totime(bsubtime1), 's')) esubtime1sec = qa.getvalue(qa.convert(qa.totime(esubtime1), 's')) timebin1sec = esubtime1sec - bsubtime1sec if timebin1sec < 0: raise Exception, 'Negative timebin! Please check the "subtime1" parameter.' casalog.post('Selected timerange 1: ' + subtime1 + ' as background for uv subtraction.') else: raise Exception, 'Please enter at least one timerange as the background' if subtime2 and (type(subtime2) == str): [bsubtime2, esubtime2] = subtime2.split('~') bsubtime2sec = qa.getvalue(qa.convert(qa.totime(bsubtime2), 's')) esubtime2sec = qa.getvalue(qa.convert(qa.totime(esubtime2), 's')) timebin2sec = esubtime2sec - bsubtime2sec if timebin2sec < 0: raise Exception, 'Negative timebin! Please check the "subtime2" parameter.' timebin2 = str(timebin2sec) + 's' casalog.post('Selected timerange 2: ' + subtime2 + ' as background for uv subtraction.') #plus 1s is to ensure averaging over the entire timerange else: casalog.post( 'Timerange 2 not selected, using only timerange 1 as background') if timerange and (type(timerange) == str): [btimeo, etimeo] = timerange.split('~') btimeosec = qa.getvalue(qa.convert(qa.totime(btimeo), 's')) etimeosec = qa.getvalue(qa.convert(qa.totime(etimeo), 's')) timebinosec = etimeosec - btimeosec if timebinosec < 0: raise Exception, 'Negative timebin! Please check the "timerange" parameter.' casalog.post('Selected timerange: ' + timerange + ' as the time for UV subtraction.') else: casalog.post( 'Output timerange not specified, using the entire timerange') if spw and (type(spw) == str): [spwid, chanran] = spw.split(':') [bchan, echan] = chanran.split('~') else: casalog.post('spw not specified, use all frequency channels') #Select the background indicated by subtime1 ms.open(vis, nomodify=True) #Select the spw id ms.msselect({'time': subtime1}) if spw and (type(spw) == str): ms.selectinit(datadescid=int(spwid)) nchan = int(echan) - int(bchan) + 1 ms.selectchannel(nchan, int(bchan), 1, 1) rec1 = ms.getdata(['data', 'time', 'axis_info'], ifraxis=True) #print 'shape of the frequency matrix ',rec1['axis_info']['freq_axis']['chan_freq'].shape sz1 = rec1['data'].shape print 'dimension of selected background 1', rec1['data'].shape #the data shape is (n_pol,n_channel,n_baseline,n_time), no need to reshape #rec1['data']=rec1['data'].reshape(sz1[0],sz1[1],sz1[2],nspw,sz1[3]/nspw,order='F') #print 'reshaped rec1 ', rec1['data'].shape rec1avg = np.average(rec1['data'], axis=3) casalog.post('Averaging the visibilities in subtime1: ' + subtime1) ms.close() if subtime2 and (type(subtime2) == str): ms.open(vis, nomodify=True) #Select the spw id ms.msselect({'time': subtime2}) if spw and (type(spw) == str): ms.selectinit(datadescid=0) nchan = int(echan) - int(bchan) + 1 ms.selectchannel(nchan, int(bchan), 1, 1) rec2 = ms.getdata(['data', 'time', 'axis_info'], ifraxis=True) sz2 = rec2['data'].shape print 'dimension of selected background 2', rec2['data'].shape #rec2['data']=rec2['data'].reshape(sz2[0],sz2[1],sz2[2],nspw,sz2[3]/nspw,order='F') #print 'reshaped rec1 ', rec2['data'].shape rec2avg = np.average(rec2['data'], axis=3) ms.close() casalog.post('Averaged the visibilities in subtime2: ' + subtime2) #do UV subtraction, according to timerange and spw ms.open(outputvis, nomodify=False) if not splitsel: #outputvis is identical to input visibility, do the selection if timerange and (type(timerange == str)): ms.msselect({'time': timerange}) if spw and (type(spw) == str): ms.selectinit(datadescid=int(spwid)) nchan = int(echan) - int(bchan) + 1 ms.selectchannel(nchan, int(bchan), 1, 1) else: #outputvis is splitted, selections have already applied, select all the data ms.selectinit(datadescid=0) orec = ms.getdata(['data', 'time', 'axis_info'], ifraxis=True) b_rows = orec['data'].shape[2] nchan = orec['data'].shape[1] #szo=orec['data'].shape print 'dimension of output data', orec['data'].shape #orec['data']=orec['data'].reshape(szo[0],szo[1],szo[2],nspw,szo[3]/nspw,order='F') #print 'reshaped rec1 ', orec['data'].shape t_rows = orec['data'].shape[3] casalog.post('Number of baselines: ' + str(b_rows)) casalog.post('Number of spectral channels: ' + str(nchan)) casalog.post('Number of time pixels: ' + str(t_rows)) if subtime1 and (not subtime2): casalog.post( 'Only "subtime1" is defined, subtracting background defined in subtime1: ' + subtime1) t1 = (np.amax(rec1['time']) + np.amin(rec1['time'])) / 2. print 't1: ', qa.time(qa.quantity(t1, 's'), form='ymd', prec=10) for i in range(t_rows): orec['data'][:, :, :, i] -= rec1avg if reverse: orec['data'][:, :, :, i] = -orec['data'][:, :, :, i] if subtime1 and subtime2 and (type(subtime2) == str): casalog.post( 'Both subtime1 and subtime2 are specified, doing linear interpolation between "subtime1" and "subtime2"' ) t1 = (np.amax(rec1['time']) + np.amin(rec1['time'])) / 2. t2 = (np.amax(rec2['time']) + np.amin(rec2['time'])) / 2. touts = orec['time'] print 't1: ', qa.time(qa.quantity(t1, 's'), form='ymd', prec=10) print 't2: ', qa.time(qa.quantity(t2, 's'), form='ymd', prec=10) for i in range(t_rows): tout = touts[i] if tout > np.amax([t1, t2]): tout = np.amax([t1, t2]) elif tout < np.amin([t1, t2]): tout = np.amin([t1, t2]) orec['data'][:, :, :, i] -= (rec2avg - rec1avg) * (tout - t1) / (t2 - t1) + rec1avg if reverse: orec['data'][:, :, :, i] = -orec['data'][:, :, :, i] #orec['data']=orec['data'].reshape(szo[0],szo[1],szo[2],szo[3],order='F') #put the modified data back into the output visibility set del orec['time'] del orec['axis_info'] ms.putdata(orec) ms.close()
def plotcomp(compdict, showplot=True, wantdict=False, symb=',', include0amp=False, include0bl=False, blunit='', bl0flux=0.0): """ Given a dict including {'clist': component list, 'objname': objname, 'epoch': epoch, 'shape': component shape dict, including direction. 'freqs (GHz)': pl.array of frequencies, 'antennalist': An array configuration file as used by simdata, 'savedfig': False or, if specified, the filename to save the plot to, 'standard': setjy fluxstandard type}, and symb: One of matplotlib's codes for plot symbols: .:,o^v<>s+xDd234hH|_ default: ',': The smallest points I could find, make a plot of visibility amplitude vs. baseline length for clist at epoch. If antennalist is not found as is, it will look for antennalist in os.getenv('CASAPATH').split(' ')[0] + '/data/alma/simmos/'. showplot: Whether or not to show the plot on screen. If wantdict is True, it returns a dictionary with the amplitudes and baselines on success. Otherwise, it returns True or False as its estimated success value. include0amp: Force the lower limit of the amplitude axis to 0. include0bl: Force the lower limit of the baseline length axis to 0. blunit: unit of the baseline length (='' used the unit in the data or klambda) bl0flux: Zero baseline flux """ def failval(): """ Returns an appropriate failure value. Note that mydict.update(plotcomp(wantdict=True, ...)) would give a confusing error message if plotcomp returned False. """ retval = False if wantdict: retval = {} return retval retval = failval() # Default try: clist = compdict['clist'] objname = compdict['objname'] epoch = compdict['epoch'] epstr = mepoch_to_str(epoch) antennalist = compdict['antennalist'] # Read the configuration info. if not antennalist: print "compdict['antennalist'] must be set!" print "Try something in", os.getenv("CASAPATH").split(' ')[0] + "/data/alma/simmos/" return failval() # Try repodir if raw antennalist doesn't work. if not os.path.exists(antennalist): repodir = os.getenv("CASAPATH").split(' ')[0] + "/data/alma/simmos/" antennalist = repodir + antennalist su = simutil("") stnx, stny, stnz, diam, padnames, telescopename, obsmeas = su.readantenna(antennalist) #print "telescopename:", telescopename # Check that the source is up. myme = metool() posobs = myme.observatory(telescopename) #print "posobs:", posobs myme.doframe(epoch) myme.doframe(posobs) azel = myme.measure(compdict['shape']['direction'], 'azel') azeldegs = tuple([qa.convert(azel[m], 'deg')['value'] for m in ('m0', 'm1')]) casalog.post("(az, el): (%.2f, %.2f) degrees" % azeldegs) # riseset blabs to the logger, so introduce it now. casalog.post('Rise and set times of ' + objname + " from " + telescopename + ':') approx = '' if 'JPL' in compdict.get('standard', 'JPL'): # The object is in the Solar System or not known to be extragalactic. approx = "APPROXIMATE. The times do not account for the apparent motion of "\ + objname + "." casalog.post(" (" + approx + ")") riset = myme.riseset(compdict['shape']['direction']) msg = '' if riset['rise'] == 'above': msg = objname + " is circumpolar" elif riset['rise'] == 'below': msg = objname + ' is not visible from ' + telescopename if msg: if approx: msg += ' around ' + mepoch_to_str(epoch) casalog.post(msg) else: for t in riset: riset[t]['str'] = mepoch_to_str(riset[t]['utc']) casalog.post(objname + " rises at %s and sets at %s." % (riset['rise']['str'], riset['set']['str'])) tmeridian=(riset['rise']['utc']['m0']['value']+riset['set']['utc']['m0']['value'])/2. casalog.post(objname + ': meridian passage at ' + qa.time(str(tmeridian)+'d')[0]) if approx: riset['NOTE'] = approx if not azel['m1']['value'] > 0.0: casalog.post(objname + " is not visible from " + telescopename + " at " + epstr, 'SEVERE') if wantdict: return riset else: return False # Start a temp MS. workingdir = os.path.abspath(os.path.dirname(clist.rstrip('/'))) tempms = tempfile.mkdtemp(prefix=objname, dir=workingdir) mysm = smtool() mysm.open(tempms) su.setcfg(mysm, telescopename, stnx, stny, stnz, diam, padnames, posobs) #print "cfg set" # Only 1 polarization is wanted for now. stokes, feeds = su.polsettings(telescopename, 'RR') casalog.post("stokes, feeds: %s, %s" % (stokes, feeds)) fband = su.bandname(compdict['freqs (GHz)'][0]) chaninc = 1.0 nchan = len(compdict['freqs (GHz)']) if nchan > 1: chaninc = (compdict['freqs (GHz)'][-1] - compdict['freqs (GHz)'][0]) / (nchan - 1) mysm.setspwindow(spwname=fband, freq=str(compdict['freqs (GHz)'][0]) + 'GHz', deltafreq=str(chaninc) + 'GHz', freqresolution='1Hz', nchannels=nchan, refcode="LSRK", stokes=stokes) mysm.setfeed(mode=feeds, pol=['']) mysm.setlimits(shadowlimit=0.01, elevationlimit='10deg') mysm.setauto(0.0) mysm.setfield(sourcename=objname, sourcedirection=compdict['shape']['direction'], calcode="OBJ", distance='0m') mysm.settimes(integrationtime="1s", usehourangle=False, referencetime=epoch) # this only creates blank uv entries mysm.observe(sourcename=objname, spwname=fband, starttime="-0.5s", stoptime="0.5s", project=objname) mysm.setdata(fieldid=[0]) mysm.setvp() casalog.post("done setting up simulation parameters") mysm.predict(complist=clist) # do actual calculation of visibilities: mysm.close() casalog.post("Simulation finished.") mytb = tbtool() mytb.open(tempms) data = mytb.getcol('DATA')[0] # Again, only 1 polarization for now. data = abs(data) baselines = mytb.getcol('UVW')[:2,:] # Drop w. datablunit = mytb.getcolkeywords('UVW')['QuantumUnits'] mytb.close() #print "Got the data and baselines" shutil.rmtree(tempms) if datablunit[1] != datablunit[0]: casalog.post('The baseline units are mismatched!: %s' % datablunit, 'SEVERE') return failval() datablunit = datablunit[0] # uv dist unit in klambda or m if datablunit == 'm' and blunit=='klambda': kl = qa.constants('C')['value']/(compdict['freqs (GHz)'][0]*1e6) blunit = 'k$\lambda$' else: blunit = datablunit kl = 1.0 pl.ioff() #baselines = pl.hypot(baselines[0]/kl, baselines[1]/kl) baselines = pl.hypot(baselines[0], baselines[1]) #if not showplot: # casalog.post('Sorry, not showing the plot is not yet implemented', # 'WARN') if showplot: pl.ion() pl.clf() pl.ioff() nfreqs = len(compdict['freqs (GHz)']) for freqnum in xrange(nfreqs): freq = compdict['freqs (GHz)'][freqnum] casalog.post("Plotting " + str(freq) + " GHz.") pl.plot(baselines/kl, data[freqnum], symb, label="%.3g GHz" % freq) #pl.plot(baselines, data[freqnum], symb, label="%.3g GHz" % freq) pl.xlabel("Baseline length (" + blunit + ")") pl.ylabel("Visibility amplitude (Jy)") if include0amp: pl.ylim(ymin=0.0) if include0bl: pl.xlim(xmin=0.0) pl.suptitle(objname + " (predicted by %s)" % compdict['standard'], fontsize=14) #pl.suptitle(objname + " (predicted)", fontsize=14) # Unlike compdict['antennalist'], antennalist might have had repodir # prefixed to it. pl.title('at ' + epstr + ' for ' + os.path.basename(compdict['antennalist']), fontsize=10) titletxt='($%.0f^\circ$ az, $%.0f^\circ$ el)' % azeldegs # for comparison of old and new models - omit azeldegs as all in az~0 if bl0flux > 0.0: if len(compdict['freqs (GHz)']) == 1: titletxt+='\n bl0 flux:%.3f Jy' % bl0flux else: titletxt+='\n bl0 flux:%.3f Jy @ %s GHz' % (bl0flux, compdict['freqs (GHz)'][0]) pl.legend(loc='best', title=titletxt) #pl.legend(loc='best', title='($%.0f^\circ$ az, $%.0f^\circ$ el)' % azeldegs) y_formatter=matplotlib.ticker.ScalarFormatter(useOffset=False) pl.axes().yaxis.set_major_formatter(y_formatter) if showplot: pl.ion() pl.draw() if compdict.get('savedfig'): pl.savefig(compdict.get('savedfig')) casalog.post("Saved plot to " + str(compdict.get('savedfig'))) if wantdict: retval = {'amps': data, 'antennalist': antennalist, # Absolute path, now. 'azel': azel, 'baselines': baselines, 'blunit': blunit, 'riseset': riset, 'savedfig': compdict.get('savedfig')} else: retval = True except Exception, instance: casalog.post(str(instance), 'SEVERE') if os.path.isdir(tempms): shutil.rmtree(tempms)
def imreg(vis=None, ephem=None, msinfo=None, imagefile=None, timerange=None, reftime=None, fitsfile=None, beamfile=None, offsetfile=None, toTb=None, scl100=None, verbose=False, p_ang=False, overwrite=True, usephacenter=True, deletehistory=False): ''' main routine to register CASA images Required Inputs: vis: STRING. CASA measurement set from which the image is derived imagefile: STRING or LIST. name of the input CASA image timerange: STRING or LIST. timerange used to generate the CASA image, must have the same length as the input images. Each element should be in CASA standard time format, e.g., '2012/03/03/12:00:00~2012/03/03/13:00:00' Optional Inputs: msinfo: DICTIONARY. CASA MS information, output from read_msinfo. If not provided, generate one from the supplied vis ephem: DICTIONARY. solar ephem, output from read_horizons. If not provided, query JPL Horizons based on time info of the vis (internet connection required) fitsfile: STRING or LIST. name of the output registered fits files reftime: STRING or LIST. Each element should be in CASA standard time format, e.g., '2012/03/03/12:00:00' offsetfile: optionally provide an offset with a series of solar x and y offsets with timestamps toTb: Bool. Convert the default Jy/beam to brightness temperature? scl100: Bool. If True, scale the image values up by 100 (to compensate VLA 20 dB attenuator) verbose: Bool. Show more diagnostic info if True. usephacenter: Bool -- if True, correct for the RA and DEC in the ms file based on solar empheris. Otherwise assume the phasecenter is correctly pointed to the solar disk center (EOVSA case) ''' ia = iatool() if deletehistory: msclearhistory(vis) if verbose: import time t0 = time.time() prtidx = 1 print('point {}: {}'.format(prtidx, time.time() - t0)) prtidx += 1 if not imagefile: raise ValueError, 'Please specify input image' if not timerange: raise ValueError, 'Please specify timerange of the input image' if type(imagefile) == str: imagefile = [imagefile] if type(timerange) == str: timerange = [timerange] if not fitsfile: fitsfile = [img + '.fits' for img in imagefile] if type(fitsfile) == str: fitsfile = [fitsfile] nimg = len(imagefile) if len(timerange) != nimg: raise ValueError, 'Number of input images does not equal to number of timeranges!' if len(fitsfile) != nimg: raise ValueError, 'Number of input images does not equal to number of output fits files!' nimg = len(imagefile) if verbose: print str(nimg) + ' images to process...' if verbose: print('point {}: {}'.format(prtidx, time.time() - t0)) prtidx += 1 if reftime: # use as reference time to find solar disk RA and DEC to register the image, but not the actual timerange associated with the image if type(reftime) == str: reftime = [reftime] * nimg if len(reftime) != nimg: raise ValueError, 'Number of reference times does not match that of input images!' helio = ephem_to_helio(vis, ephem=ephem, msinfo=msinfo, reftime=reftime, usephacenter=usephacenter) else: # use the supplied timerange to register the image helio = ephem_to_helio(vis, ephem=ephem, msinfo=msinfo, reftime=timerange, usephacenter=usephacenter) if verbose: print('point {}: {}'.format(prtidx, time.time() - t0)) prtidx += 1 for n, img in enumerate(imagefile): if verbose: print 'processing image #' + str(n) fitsf = fitsfile[n] timeran = timerange[n] # obtain duration of the image as FITS header exptime try: [tbg0, tend0] = timeran.split('~') tbg_d = qa.getvalue(qa.convert(qa.totime(tbg0), 'd'))[0] tend_d = qa.getvalue(qa.convert(qa.totime(tend0), 'd'))[0] tdur_s = (tend_d - tbg_d) * 3600. * 24. dateobs = qa.time(qa.quantity(tbg_d, 'd'), form='fits', prec=10)[0] except: print 'Error in converting the input timerange: ' + str( timeran) + '. Proceeding to the next image...' continue if verbose: print('point {}: {}'.format(prtidx, time.time() - t0)) prtidx += 1 hel = helio[n] if not os.path.exists(img): raise ValueError, 'Please specify input image' if os.path.exists(fitsf) and not overwrite: raise ValueError, 'Specified fits file already exists and overwrite is set to False. Aborting...' else: p0 = hel['p0'] ia.open(img) imr = ia.rotate(pa=str(-p0) + 'deg') imr.tofits(fitsf, history=False, overwrite=overwrite) imr.close() imsum = ia.summary() ia.close() if verbose: print('point {}: {}'.format(prtidx, time.time() - t0)) prtidx += 1 # construct the standard fits header # RA and DEC of the reference pixel crpix1 and crpix2 (imra, imdec) = (imsum['refval'][0], imsum['refval'][1]) # find out the difference of the image center to the CASA phase center # RA and DEC difference in arcseconds ddec = degrees((imdec - hel['dec_fld'])) * 3600. dra = degrees((imra - hel['ra_fld']) * cos(hel['dec_fld'])) * 3600. # Convert into image heliocentric offsets prad = -radians(hel['p0']) dx = (-dra) * cos(prad) - ddec * sin(prad) dy = (-dra) * sin(prad) + ddec * cos(prad) if offsetfile: try: offset = np.load(offsetfile) except: raise ValueError, 'The specified offsetfile does not exist!' reftimes_d = offset['reftimes_d'] xoffs = offset['xoffs'] yoffs = offset['yoffs'] timg_d = hel['reftime'] ind = bisect.bisect_left(reftimes_d, timg_d) xoff = xoffs[ind - 1] yoff = yoffs[ind - 1] else: xoff = hel['refx'] yoff = hel['refy'] if verbose: print 'offset of image phase center to visibility phase center (arcsec): ', dx, dy print 'offset of visibility phase center to solar disk center (arcsec): ', xoff, yoff (crval1, crval2) = (xoff + dx, yoff + dy) # update the fits header to heliocentric coordinates if verbose: print('point {}: {}'.format(prtidx, time.time() - t0)) prtidx += 1 hdu = pyfits.open(fitsf, mode='update') if verbose: print('point {}: {}'.format(prtidx, time.time() - t0)) prtidx += 1 header = hdu[0].header (cdelt1, cdelt2) = (-header['cdelt1'] * 3600., header['cdelt2'] * 3600. ) # Original CDELT1, 2 are for RA and DEC in degrees header['cdelt1'] = cdelt1 header['cdelt2'] = cdelt2 header['cunit1'] = 'arcsec' header['cunit2'] = 'arcsec' header['crval1'] = crval1 header['crval2'] = crval2 header['ctype1'] = 'HPLN-TAN' header['ctype2'] = 'HPLT-TAN' header['date-obs'] = dateobs # begin time of the image if not p_ang: hel['p0'] = 0 try: # this works for pyfits version of CASA 4.7.0 but not CASA 4.6.0 if tdur_s: header.set('exptime', tdur_s) else: header.set('exptime', 1.) header.set('p_angle', hel['p0']) header.set('dsun_obs', sun.sunearth_distance(Time(dateobs)).to(u.meter).value) header.set( 'rsun_obs', sun.solar_semidiameter_angular_size(Time(dateobs)).value) header.set('rsun_ref', sun.constants.radius.value) header.set('hgln_obs', 0.) header.set('hglt_obs', sun.heliographic_solar_center(Time(dateobs))[1].value) except: # this works for astropy.io.fits if tdur_s: header.append(('exptime', tdur_s)) else: header.append(('exptime', 1.)) header.append(('p_angle', hel['p0'])) header.append( ('dsun_obs', sun.sunearth_distance(Time(dateobs)).to(u.meter).value)) header.append( ('rsun_obs', sun.solar_semidiameter_angular_size(Time(dateobs)).value)) header.append(('rsun_ref', sun.constants.radius.value)) header.append(('hgln_obs', 0.)) header.append( ('hglt_obs', sun.heliographic_solar_center(Time(dateobs))[1].value)) if verbose: print('point {}: {}'.format(prtidx, time.time() - t0)) prtidx += 1 # update intensity units, i.e. to brightness temperature? if toTb: # get restoring beam info (bmajs, bmins, bpas, beamunits, bpaunits) = getbeam(imagefile=imagefile, beamfile=beamfile) bmaj = bmajs[n] bmin = bmins[n] beamunit = beamunits[n] data = hdu[ 0].data # remember the data order is reversed due to the FITS convension dim = data.ndim sz = data.shape keys = header.keys() values = header.values() # which axis is frequency? faxis = keys[values.index('FREQ')][-1] faxis_ind = dim - int(faxis) if header['BUNIT'].lower() == 'jy/beam': header['BUNIT'] = 'K' header['BTYPE'] = 'Brightness Temperature' for i in range(sz[faxis_ind]): nu = header['CRVAL' + faxis] + header['CDELT' + faxis] * ( i + 1 - header['CRPIX' + faxis]) if header['CUNIT' + faxis] == 'KHz': nu *= 1e3 if header['CUNIT' + faxis] == 'MHz': nu *= 1e6 if header['CUNIT' + faxis] == 'GHz': nu *= 1e9 if len(bmaj) > 1: # multiple (per-plane) beams bmajtmp = bmaj[i] bmintmp = bmin[i] else: # one single beam bmajtmp = bmaj[0] bmintmp = bmin[0] if beamunit == 'arcsec': bmaj0 = np.radians(bmajtmp / 3600.) bmin0 = np.radians(bmajtmp / 3600.) if beamunit == 'arcmin': bmaj0 = np.radians(bmajtmp / 60.) bmin0 = np.radians(bmintmp / 60.) if beamunit == 'deg': bmaj0 = np.radians(bmajtmp) bmin0 = np.radians(bmintmp) if beamunit == 'rad': bmaj0 = bmajtmp bmin0 = bmintmp beam_area = bmaj0 * bmin0 * np.pi / (4. * log(2.)) k_b = qa.constants('k')['value'] c_l = qa.constants('c')['value'] factor = 2. * k_b * nu**2 / c_l**2 # SI unit jy_to_si = 1e-26 # print nu/1e9, beam_area, factor factor2 = 1. if scl100: factor2 = 100. if faxis == '3': data[:, i, :, :] *= jy_to_si / beam_area / factor * factor2 if faxis == '4': data[ i, :, :, :] *= jy_to_si / beam_area / factor * factor2 if verbose: print('point {}: {}'.format(prtidx, time.time() - t0)) prtidx += 1 hdu.flush() hdu.close() if verbose: print('point {}: {}'.format(prtidx, time.time() - t0)) prtidx += 1
def mk_diskmodel(outname='disk', bdwidth='325MHz', direction='J2000 10h00m00.0s 20d00m00.0s', reffreq='2.8GHz', flux=660000.0, eqradius='16.166arcmin', polradius='16.166arcmin', pangle='21.1deg', index=None, cell='2.0arcsec', overwrite=True): ''' Create a blank solar disk model image (or optionally a data cube) outname String to use for part of the image and fits file names (default 'disk') direction String specifying the position of the Sun in RA and Dec. Default means use the standard string "J2000 10h00m00.0s 20d00m00.0s" reffreq The reference frequency to use for the disk model (the frequency at which the flux level applies). Default is '2.8GHz'. flux The flux density, in Jy, for the entire disk. Default is 66 sfu. eqradius The equatorial radius of the disk. Default is 16 arcmin + 10" (for typical extension of the radio limb) polradius The polar radius of the disk. Default is 16 arcmin + 10" (for typical extension of the radio limb) pangle The solar P-angle (geographic position of the N-pole of the Sun) in degrees E of N. This only matters if eqradius != polradius index The spectral index to use at other frequencies. Default None means use a constant flux density for all frequencies. cell The cell size (assumed square) to use for the image. The image size is determined from a standard radius of 960" for the Sun, divided by cell size, increased to nearest power of 512 pixels. The default is '2.0arcsec', which results in an image size of 1024 x 1024. Note that the frequency increment used is '325MHz', which is the width of EOVSA bands (not the width of individual science channels) ''' diskim = outname + reffreq + '.im' if os.path.exists(diskim): if overwrite: os.system('rm -rf {}'.format(diskim)) else: return diskim ia = iatool() cl = cltool() cl.done() ia.done() try: aspect = 1.01 # Enlarge the equatorial disk by 1% eqradius = qa.quantity(eqradius) diamajor = qa.quantity(2 * aspect * eqradius['value'], eqradius['unit']) polradius = qa.quantity(polradius) diaminor = qa.quantity(2 * polradius['value'], polradius['unit']) solrad = qa.convert(polradius, 'arcsec') except: print('Radius', eqradius, polradius, 'does not have the expected format, number + unit where unit is arcmin or arcsec') return try: cell = qa.convert(qa.quantity(cell), 'arcsec') cellsize = float(cell['value']) diskpix = solrad['value'] * 2 / cellsize cell_rad = qa.convert(cell, 'rad') except: print('Cell size', cell, 'does not have the expected format, number + unit where unit is arcmin or arcsec') return # Add 90 degrees to pangle, due to angle definition in addcomponent() -- it puts the majoraxis vertical pangle = qa.add(qa.quantity(pangle), qa.quantity('90deg')) mapsize = ((int(diskpix) / 512) + 1) * 512 # Flux density is doubled because it is split between XX and YY cl.addcomponent(dir=direction, flux=flux * 2, fluxunit='Jy', freq=reffreq, shape='disk', majoraxis=diamajor, minoraxis=diaminor, positionangle=pangle) cl.setrefdirframe(0, 'J2000') ia.fromshape(diskim, [mapsize, mapsize, 1, 1], overwrite=True) cs = ia.coordsys() cs.setunits(['rad', 'rad', '', 'Hz']) cell_rad_val = cell_rad['value'] cs.setincrement([-cell_rad_val, cell_rad_val], 'direction') epoch, ra, dec = direction.split() cs.setreferencevalue([qa.convert(ra, 'rad')['value'], qa.convert(dec, 'rad')['value']], type="direction") cs.setreferencevalue(reffreq, 'spectral') cs.setincrement(bdwidth, 'spectral') ia.setcoordsys(cs.torecord()) ia.setbrightnessunit("Jy/pixel") ia.modify(cl.torecord(), subtract=False) ia.close() ia.done() # cl.close() cl.done() return diskim
def ksc_sim_gauss(projname='sim_7m_array_1GHz_gaus', antennalist='ksc-7m.cfg', dishdiam=7, imagename=None, indirection='J2000 14h26m46.0s -14d31m22.0s', incell='1arcsec', frequency='1.0GHz', inwidth='1MHz', radec_offset=[100., 100.], flux=50., majoraxis='40arcsec', minoraxis='27arcsec', positionangle='45.0deg', imsize=[512, 512]): """ Simulate observation of an input Gaussian model :param projname: project name for simobserve :param antennalist: cfg file of the array configuration :param dishdiam: diameter of each dish, in meters :param imagename: name (and path) for output clean image, psf, etc. :param indirection: phase center of the observation :param incell: pixel scale of the model/simulated image :param frequency: central frequency :param inwidth: frequency bandwidth :param radec_offset: offset of the Gaussian source from the phasecenter, in arcsec :param flux: total flux of the Gaussian source, in solar flux unit (sfu) :param majoraxis: FWHM size of the Gaussian source along the major axis :param minoraxis: FWHM size of the Gaussian source along the minor axis :param positionangle: position angle of the Gaussian source :param imsize: size of the model/simulated image, in pixels (x and y) :return: """ # set voltage patterns and primary beams for KSC 7 m. This is a placeholder for now (but required for PB correction) vp = vptool() if len(vp.getvp(telescope='KSC').keys()) == 0: vprec = vp.setpbairy(telescope='KSC', dishdiam='{0:.1f}m'.format(dishdiam), blockagediam='0.75m', maxrad='1.784deg', reffreq='1.0GHz', dopb=True) # make a Gaussian source cl = cltool() ia = iatool() cl.addcomponent(dir=indirection, flux=flux * 1e4, fluxunit='Jy', freq=frequency, shape="Gaussian", majoraxis=majoraxis, minoraxis=minoraxis, positionangle=positionangle) ia.fromshape("Gaussian.im", imsize + [1, 1], overwrite=True) cs = ia.coordsys() cs.setunits(['rad', 'rad', '', 'Hz']) cell_rad = qa.convert(qa.quantity(incell), "rad")['value'] cs.setincrement([-cell_rad, cell_rad], 'direction') ra_ref = qa.toangle(indirection.split(' ')[1]) dec_ref = qa.toangle(indirection.split(' ')[2]) ra = ra_ref['value'] - radec_offset[0] / 3600. dec = dec_ref['value'] - radec_offset[1] / 3600. cs.setreferencevalue([ qa.convert('{0:.4f}deg'.format(ra), 'rad')['value'], qa.convert('{0:.4f}deg'.format(dec), 'rad')['value'] ], type="direction") cs.setreferencevalue("1.0GHz", 'spectral') cs.setincrement('10MHz', 'spectral') ia.setcoordsys(cs.torecord()) ia.setbrightnessunit("Jy/pixel") ia.modify(cl.torecord(), subtract=False) ia.close() simobserve(project=projname, skymodel='Gaussian.im', indirection=indirection, incell=incell, incenter=frequency, inwidth=inwidth, hourangle='transit', refdate='2014/11/01', totaltime='120s', antennalist=antennalist, obsmode='int', overwrite=True) if not imagename: imagename = projname + '/tst' tclean(vis=projname + '/' + projname + '.' + antennalist.split('.')[0] + '.ms', imagename=imagename, imsize=imsize, cell=incell, phasecenter=indirection, niter=200, interactive=False) viewer(projname + '/' + projname + '.' + antennalist.split('.')[0] + '.skymodel') viewer(imagename + '.psf') viewer(imagename + '.image')
plot_profile_map(image, figfile, pol, spectralaxis, restfreq, title, linecolor, linestyle, linewidth, separatepanel, plotmasked, maskedcolor, showaxislabel, showtick, showticklabel, parsed_size, nx, ny, transparent, plotrange) except Exception, e: casalog.post('Error: %s'%(str(e)), priority='SEVERE') import traceback casalog.post(traceback.format_exc(), priority='DEBUG') raise e finally: pass NoData = -32767.0 NoDataThreshold = NoData + 10000.0 LightSpeedQuantity = qa.constants('c') LightSpeed = qa.convert(LightSpeedQuantity, 'km/s')['value'] # speed of light in km/s DPIDetail = 130 dsyb = '$^\circ$' hsyb = ':' msyb = ':' def Deg2HMS(x, arrowance): # Transform degree to HHMMSS.sss format xx = x % 360 + arrowance h = int(xx / 15) m = int((xx % 15) * 4) s = ((xx % 15) * 4 - m) * 60.0 return (h, m, s) def HHMMSSss(x, pos):
else: try: # meanrad might already have been converted. if type(retdict[hk]) != dict: retdict[hk] = {"unit": headers[hk]["unit"], "value": float(retdict[hk])} except Exception, e: print "Error converting header", hk, "to a Quantity." print "retdict[hk] =", retdict[hk] raise e elif hk == "GeoLong": long_lat_alt = retdict[hk].split(",") retdict["GeoLong"] = float(long_lat_alt[0]) retdict["GeoLat"] = float(long_lat_alt[1]) retdict["GeoDist"] = float(long_lat_alt[2]) elif hk == "dMJD": retdict[hk] = qa.convert(qa.totime(retdict[hk].replace("minutes", "min")), "d")["value"] elif hk == "orb_per": unit = "h" retrograde = False if "d" in retdict[hk].lower(): unit = "d" # Actually this is most common. if "r" in retdict[hk].lower(): retrograde = True value = get_num_from_str(retdict[hk], "orbital period") if value != False: if retrograde and value > 0.0: value = -value retdict[hk] = {"unit": unit, "value": value} else: del retdict[hk]
def subvs2(vis=None, outputvis=None, timerange='', spw='', mode=None, subtime1=None, subtime2=None, smoothaxis=None, smoothtype=None, smoothwidth=None, splitsel=None, reverse=None, overwrite=None): """Perform vector subtraction for visibilities Keyword arguments: vis -- Name of input visibility file (MS) default: none; example: vis='ngc5921.ms' outputvis -- Name of output uv-subtracted visibility file (MS) default: none; example: outputvis='ngc5921_src.ms' timerange -- Time range of performing the UV subtraction: default='' means all times. examples: timerange = 'YYYY/MM/DD/hh:mm:ss~YYYY/MM/DD/hh:mm:ss' timerange = 'hh:mm:ss~hh:mm:ss' spw -- Select spectral window/channel. default = '' all the spectral channels. Example: spw='0:1~20' mode -- operation mode default 'linear' mode = 'linear': use a linear fit for the background to be subtracted mode = 'lowpass': act as a lowpass filter---smooth the data using different smooth types and window sizes. Can be performed along either time or frequency axis mode = 'highpass': act as a highpass filter---smooth the data first, and subtract the smoothed data from the original. Can be performed along either time or frequency axis mode = 'linear' expandable parameters: subtime1 -- Time range 1 of the background to be subtracted from the data default='' means all times. format: timerange = 'YYYY/MM/DD/hh:mm:ss~YYYY/MM/DD/hh:mm:ss' timerange = 'hh:mm:ss~hh:mm:ss' subtime2 -- Time range 2 of the backgroud to be subtracted from the data default='' means all times. examples: timerange = 'YYYY/MM/DD/hh:mm:ss~YYYY/MM/DD/hh:mm:ss' timerange = 'hh:mm:ss~hh:mm:ss' mode = 'lowpass' or 'highpass' expandable parameters: smoothaxis -- axis of smooth Default: 'time' smoothaxis = 'time': smooth is along the time axis smoothaxis = 'freq': smooth is along the frequency axis smoothtype -- type of the smooth depending on the convolving kernel Default: 'flat' smoothtype = 'flat': convolving kernel is a flat rectangle, equivalent to a boxcar moving smooth smoothtype = 'hanning': Hanning smooth kernel. See numpy.hanning smoothtype = 'hamming': Hamming smooth kernel. See numpy.hamming smoothtype = 'bartlett': Bartlett smooth kernel. See numpy.bartlett smoothtype = 'blackman': Blackman smooth kernel. See numpy.blackman smoothwidth -- width of the smooth kernel Default: 5 Examples: smoothwidth=5, meaning the width is 5 pixels splitsel -- True or False. default = False. If splitsel = False, then the entire input measurement set is copied as the output measurement set (outputvis), with background subtracted at selected timerange and spectral channels. If splitsel = True,then only the selected timerange and spectral channels are copied into the output measurement set (outputvis). reverse -- True or False. default = False. If reverse = False, then the times indicated by subtime1 and/or subtime2 are treated as background and subtracted; If reverse = True, then reverse the sign of the background-subtracted data. The option can be used for mapping absorptive structure. overwrite -- True or False. default = False. If overwrite = True and outputvis already exists, the selected subtime and spw in the output measurment set will be replaced with background subtracted visibilities """ # check the visbility ms casalog.post('input parameters:') casalog.post('vis: ' + vis) casalog.post('outputvis: ' + outputvis) casalog.post('smoothaxis: ' + smoothaxis) casalog.post('smoothtype: ' + smoothtype) casalog.post('smoothwidth: ' + str(smoothwidth)) if not outputvis or outputvis.isspace(): raise (ValueError, 'Please specify outputvis') if os.path.exists(outputvis): if overwrite: print( "The already existing output measurement set will be updated.") else: raise (ValueError, "Output MS %s already exists - will not overwrite." % outputvis) else: if not splitsel: shutil.copytree(vis, outputvis) else: ms.open(vis, nomodify=True) ms.split(outputvis, spw=spw, time=timerange, whichcol='DATA') ms.close() if timerange and (type(timerange) == str): [btimeo, etimeo] = timerange.split('~') btimeosec = qa.getvalue(qa.convert(qa.totime(btimeo), 's')) etimeosec = qa.getvalue(qa.convert(qa.totime(etimeo), 's')) timebinosec = etimeosec - btimeosec if timebinosec < 0: raise Exception( 'Negative timebin! Please check the "timerange" parameter.') casalog.post('Selected timerange: ' + timerange + ' as the time for UV subtraction.') else: casalog.post( 'Output timerange not specified, using the entire timerange') if spw and (type(spw) == str): spwlist = spw.split(';') else: casalog.post('spw not specified, use all frequency channels') # read the output data datams = mstool() datams.open(outputvis, nomodify=False) datamsmd = msmdtool() datamsmd.open(outputvis) spwinfod = datams.getspectralwindowinfo() spwinfok = spwinfod.keys() spwinfok.sort(key=int) spwinfol = [spwinfod[k] for k in spwinfok] for s, spi in enumerate(spwinfol): print('processing spectral window {}'.format(spi['SpectralWindowId'])) datams.selectinit(reset=True) staql = {'time': '', 'spw': ''} if not splitsel: # outputvis is identical to input visibility, do the selection if timerange and (type(timerange == str)): staql['time'] = timerange if spw and (type(spw) == str): staql['spw'] = spwlist[s] if not spw and not timerange: # data selection is not made print('selecting all spws and times') staql['spw'] = str(spi['SpectralWindowId']) else: # outputvis is splitted, selections have already applied, select all the data print('split the selected spws and times') staql['spw'] = str(spi['SpectralWindowId']) datams.msselect(staql) orec = datams.getdata(['data', 'time', 'axis_info'], ifraxis=True) npol, nchan, nbl, ntim = orec['data'].shape print('dimension of output data', orec['data'].shape) casalog.post('Number of baselines: ' + str(nbl)) casalog.post('Number of spectral channels: ' + str(nchan)) casalog.post('Number of time pixels: ' + str(ntim)) try: if mode == 'linear': # define and check the background time ranges if subtime1 and (type(subtime1) == str): [bsubtime1, esubtime1] = subtime1.split('~') bsubtime1sec = qa.getvalue( qa.convert(qa.totime(bsubtime1), 's')) esubtime1sec = qa.getvalue( qa.convert(qa.totime(esubtime1), 's')) timebin1sec = esubtime1sec - bsubtime1sec if timebin1sec < 0: raise Exception( 'Negative timebin! Please check the "subtime1" parameter.' ) casalog.post('Selected timerange 1: ' + subtime1 + ' as background for uv subtraction.') else: raise Exception( 'Please enter at least one timerange as the background' ) if subtime2 and (type(subtime2) == str): [bsubtime2, esubtime2] = subtime2.split('~') bsubtime2sec = qa.getvalue( qa.convert(qa.totime(bsubtime2), 's')) esubtime2sec = qa.getvalue( qa.convert(qa.totime(esubtime2), 's')) timebin2sec = esubtime2sec - bsubtime2sec if timebin2sec < 0: raise Exception( 'Negative timebin! Please check the "subtime2" parameter.' ) timebin2 = str(timebin2sec) + 's' casalog.post('Selected timerange 2: ' + subtime2 + ' as background for uv subtraction.') # plus 1s is to ensure averaging over the entire timerange else: casalog.post( 'Timerange 2 not selected, using only timerange 1 as background' ) # Select the background indicated by subtime1 ms.open(vis, nomodify=True) # Select the spw id # ms.msselect({'time': subtime1}) staql0 = {'time': subtime1, 'spw': ''} if spw and (type(spw) == str): staql0['spw'] = spwlist[s] else: staql0['spw'] = staql['spw'] ms.msselect(staql0) rec1 = ms.getdata(['data', 'time', 'axis_info'], ifraxis=True) # print('shape of the frequency matrix ',rec1['axis_info']['freq_axis']['chan_freq'].shape) sz1 = rec1['data'].shape print('dimension of selected background 1', rec1['data'].shape) # the data shape is (n_pol,n_channel,n_baseline,n_time), no need to reshape # rec1['data']=rec1['data'].reshape(sz1[0],sz1[1],sz1[2],nspw,sz1[3]/nspw,order='F') # print('reshaped rec1 ', rec1['data'].shape) rec1avg = np.average(rec1['data'], axis=3) casalog.post('Averaging the visibilities in subtime1: ' + subtime1) ms.close() if subtime2 and (type(subtime2) == str): ms.open(vis, nomodify=True) # Select the spw id staql0 = {'time': subtime2, 'spw': ''} if spw and (type(spw) == str): staql0['spw'] = spwlist[s] else: staql0['spw'] = staql['spw'] ms.msselect(staql0) rec2 = ms.getdata(['data', 'time', 'axis_info'], ifraxis=True) sz2 = rec2['data'].shape print('dimension of selected background 2', rec2['data'].shape) # rec2['data']=rec2['data'].reshape(sz2[0],sz2[1],sz2[2],nspw,sz2[3]/nspw,order='F') # print('reshaped rec1 ', rec2['data'].shape) rec2avg = np.average(rec2['data'], axis=3) ms.close() casalog.post('Averaged the visibilities in subtime2: ' + subtime2) if subtime1 and (not subtime2): casalog.post( 'Only "subtime1" is defined, subtracting background defined in subtime1: ' + subtime1) t1 = (np.amax(rec1['time']) + np.amin(rec1['time'])) / 2. print('t1: ', qa.time(qa.quantity(t1, 's'), form='ymd', prec=10)) for i in range(ntim): orec['data'][:, :, :, i] -= rec1avg if reverse: orec['data'][:, :, :, i] = -orec['data'][:, :, :, i] if subtime1 and subtime2 and (type(subtime2) == str): casalog.post( 'Both subtime1 and subtime2 are specified, doing linear interpolation between "subtime1" and "subtime2"' ) t1 = (np.amax(rec1['time']) + np.amin(rec1['time'])) / 2. t2 = (np.amax(rec2['time']) + np.amin(rec2['time'])) / 2. touts = orec['time'] print('t1: ', qa.time(qa.quantity(t1, 's'), form='ymd', prec=10)) print('t2: ', qa.time(qa.quantity(t2, 's'), form='ymd', prec=10)) for i in range(ntim): tout = touts[i] if tout > np.amax([t1, t2]): tout = np.amax([t1, t2]) elif tout < np.amin([t1, t2]): tout = np.amin([t1, t2]) orec['data'][:, :, :, i] -= (rec2avg - rec1avg) * ( tout - t1) / (t2 - t1) + rec1avg if reverse: orec['data'][:, :, :, i] = -orec['data'][:, :, :, i] elif mode == 'highpass': if smoothtype != 'flat' and smoothtype != 'hanning' and smoothtype != 'hamming' and smoothtype != 'bartlett' and smoothtype != 'blackman': raise Exception('Unknown smoothtype ' + str(smoothtype)) if smoothaxis == 'time': if smoothwidth <= 0 or smoothwidth >= ntim: raise Exception( 'Specified smooth width is <=0 or >= the total number of ' + smoothaxis) else: for i in range(orec['data'].shape[0]): for j in range(nchan): for k in range(nbl): orec['data'][i, j, k, :] -= signalsmooth.smooth( orec['data'][i, j, k, :], smoothwidth, smoothtype) if smoothaxis == 'freq': if smoothwidth <= 0 or smoothwidth >= nchan: raise Exception( 'Specified smooth width is <=0 or >= the total number of ' + smoothaxis) else: for i in range(orec['data'].shape[0]): for j in range(nbl): for k in range(ntim): orec['data'][i, :, j, k] -= signalsmooth.smooth( orec['data'][i, :, j, k], smoothwidth, smoothtype) elif mode == 'lowpass': if smoothtype != 'flat' and smoothtype != 'hanning' and smoothtype != 'hamming' and smoothtype != 'bartlett' and smoothtype != 'blackman': raise Exception('Unknown smoothtype ' + str(smoothtype)) if smoothaxis == 'time': if smoothwidth <= 0 or smoothwidth >= ntim: raise Exception( 'Specified smooth width is <=0 or >= the total number of ' + smoothaxis) else: for i in range(orec['data'].shape[0]): for j in range(nchan): for k in range(nbl): orec['data'][i, j, k, :] = signalsmooth.smooth( orec['data'][i, j, k, :], smoothwidth, smoothtype) if smoothaxis == 'freq': if smoothwidth <= 0 or smoothwidth >= nchan: raise Exception( 'Specified smooth width is <=0 or >= the total number of ' + smoothaxis) else: for i in range(orec['data'].shape[0]): for j in range(nbl): for k in range(ntim): orec['data'][i, :, j, k] = signalsmooth.smooth( orec['data'][i, :, j, k], smoothwidth, smoothtype) else: raise Exception('Unknown mode' + str(mode)) except Exception as instance: print('*** Error ***', instance) # orec['data']=orec['data'].reshape(szo[0],szo[1],szo[2],szo[3],order='F') # put the modified data back into the output visibility set del orec['time'] del orec['axis_info'] # ms.open(outputvis,nomodify=False) # if not splitsel: # outputvis is identical to input visibility, do the selection # if timerange and (type(timerange==str)): # datams.msselect({'time':timerange}) # if spw and (type(spw)==str): # datams.selectinit(datadescid=int(spwid)) # nchan=int(echan)-int(bchan)+1 # datams.selectchannel(nchan,int(bchan),1,1) # if not spw and not timerange: # data selection is not made # datams.selectinit(datadescid=0) # else: # outputvis is splitted, selections have already applied, select all the data # datams.selectinit(datadescid=0) datams.putdata(orec) datams.close() datamsmd.done()
try: # meanrad might already have been converted. if type(retdict[hk]) != dict: retdict[hk] = {'unit': headers[hk]['unit'], 'value': float(retdict[hk])} except Exception, e: print "Error converting header", hk, "to a Quantity." print "retdict[hk] =", retdict[hk] raise e elif hk == 'GeoLong': long_lat_alt = retdict[hk].split(',') retdict['GeoLong'] = float(long_lat_alt[0]) retdict['GeoLat'] = float(long_lat_alt[1]) retdict['GeoDist'] = float(long_lat_alt[2]) elif hk == 'dMJD': retdict[hk] = qa.convert(qa.totime(retdict[hk].replace('minutes', 'min')), 'd')['value'] elif hk == 'orb_per': unit = 'h' retrograde = False if 'd' in retdict[hk].lower(): unit = 'd' # Actually this is most common. if 'r' in retdict[hk].lower(): retrograde = True value = get_num_from_str(retdict[hk], 'orbital period') if value != False: if retrograde and value > 0.0: value = -value retdict[hk] = {'unit': unit, 'value': value} else: del retdict[hk]
def plotcomp(compdict, showplot=True, wantdict=False, symb=',', include0amp=False, include0bl=False, blunit='', bl0flux=0.0): """ Given a dict including {'clist': component list, 'objname': objname, 'epoch': epoch, 'shape': component shape dict, including direction. 'freqs (GHz)': pl.array of frequencies, 'antennalist': An array configuration file as used by simdata, 'savedfig': False or, if specified, the filename to save the plot to, 'standard': setjy fluxstandard type}, and symb: One of matplotlib's codes for plot symbols: .:,o^v<>s+xDd234hH|_ default: ',': The smallest points I could find, make a plot of visibility amplitude vs. baseline length for clist at epoch. If antennalist is not found as is, it will look for antennalist in os.getenv('CASAPATH').split(' ')[0] + '/data/alma/simmos/'. showplot: Whether or not to show the plot on screen. If wantdict is True, it returns a dictionary with the amplitudes and baselines on success. Otherwise, it returns True or False as its estimated success value. include0amp: Force the lower limit of the amplitude axis to 0. include0bl: Force the lower limit of the baseline length axis to 0. blunit: unit of the baseline length (='' used the unit in the data or klambda) bl0flux: Zero baseline flux """ def failval(): """ Returns an appropriate failure value. Note that mydict.update(plotcomp(wantdict=True, ...)) would give a confusing error message if plotcomp returned False. """ retval = False if wantdict: retval = {} return retval retval = failval() # Default try: clist = compdict['clist'] objname = compdict['objname'] epoch = compdict['epoch'] epstr = mepoch_to_str(epoch) antennalist = compdict['antennalist'] # Read the configuration info. if not antennalist: print "compdict['antennalist'] must be set!" print "Try something in", os.getenv("CASAPATH").split(' ')[0] + "/data/alma/simmos/" return failval() # Try repodir if raw antennalist doesn't work. if not os.path.exists(antennalist): repodir = os.getenv("CASAPATH").split(' ')[0] + "/data/alma/simmos/" antennalist = repodir + antennalist su = simutil("") stnx, stny, stnz, diam, padnames, nant, telescopename = su.readantenna(antennalist) #print "telescopename:", telescopename # Check that the source is up. myme = metool() posobs = myme.observatory(telescopename) #print "posobs:", posobs myme.doframe(epoch) myme.doframe(posobs) azel = myme.measure(compdict['shape']['direction'], 'azel') azeldegs = tuple([qa.convert(azel[m], 'deg')['value'] for m in ('m0', 'm1')]) casalog.post("(az, el): (%.2f, %.2f) degrees" % azeldegs) # riseset blabs to the logger, so introduce it now. casalog.post('Rise and set times of ' + objname + " from " + telescopename + ':') approx = '' if 'JPL' in compdict.get('standard', 'JPL'): # The object is in the Solar System or not known to be extragalactic. approx = "APPROXIMATE. The times do not account for the apparent motion of "\ + objname + "." casalog.post(" (" + approx + ")") riset = myme.riseset(compdict['shape']['direction']) msg = '' if riset['rise'] == 'above': msg = objname + " is circumpolar" elif riset['rise'] == 'below': msg = objname + ' is not visible from ' + telescopename if msg: if approx: msg += ' around ' + mepoch_to_str(epoch) casalog.post(msg) else: for t in riset: riset[t]['str'] = mepoch_to_str(riset[t]['utc']) casalog.post(objname + " rises at %s and sets at %s." % (riset['rise']['str'], riset['set']['str'])) tmeridian=(riset['rise']['utc']['m0']['value']+riset['set']['utc']['m0']['value'])/2. casalog.post(objname + ': meridian passage at ' + qa.time(str(tmeridian)+'d')[0]) if approx: riset['NOTE'] = approx if not azel['m1']['value'] > 0.0: casalog.post(objname + " is not visible from " + telescopename + " at " + epstr, 'SEVERE') if wantdict: return riset else: return False # Start a temp MS. workingdir = os.path.abspath(os.path.dirname(clist.rstrip('/'))) tempms = tempfile.mkdtemp(prefix=objname, dir=workingdir) mysm = smtool() mysm.open(tempms) su.setcfg(mysm, telescopename, stnx, stny, stnz, diam, padnames, posobs) #print "cfg set" # Only 1 polarization is wanted for now. stokes, feeds = su.polsettings(telescopename, 'RR') casalog.post("stokes, feeds: %s, %s" % (stokes, feeds)) fband = su.bandname(compdict['freqs (GHz)'][0]) chaninc = 1.0 nchan = len(compdict['freqs (GHz)']) if nchan > 1: chaninc = (compdict['freqs (GHz)'][-1] - compdict['freqs (GHz)'][0]) / (nchan - 1) mysm.setspwindow(spwname=fband, freq=str(compdict['freqs (GHz)'][0]) + 'GHz', deltafreq=str(chaninc) + 'GHz', freqresolution='1Hz', nchannels=nchan, refcode="LSRK", stokes=stokes) mysm.setfeed(mode=feeds, pol=['']) mysm.setlimits(shadowlimit=0.01, elevationlimit='10deg') mysm.setauto(0.0) mysm.setfield(sourcename=objname, sourcedirection=compdict['shape']['direction'], calcode="OBJ", distance='0m') mysm.settimes(integrationtime="1s", usehourangle=False, referencetime=epoch) # this only creates blank uv entries mysm.observe(sourcename=objname, spwname=fband, starttime="-0.5s", stoptime="0.5s", project=objname) mysm.setdata(fieldid=[0]) mysm.setvp() casalog.post("done setting up simulation parameters") mysm.predict(complist=clist) # do actual calculation of visibilities: mysm.close() casalog.post("Simulation finished.") mytb = tbtool() mytb.open(tempms) data = mytb.getcol('DATA')[0] # Again, only 1 polarization for now. data = abs(data) baselines = mytb.getcol('UVW')[:2,:] # Drop w. datablunit = mytb.getcolkeywords('UVW')['QuantumUnits'] mytb.close() #print "Got the data and baselines" shutil.rmtree(tempms) if datablunit[1] != datablunit[0]: casalog.post('The baseline units are mismatched!: %s' % datablunit, 'SEVERE') return failval() datablunit = datablunit[0] # uv dist unit in klambda or m if datablunit == 'm' and blunit=='klambda': kl = qa.constants('C')['value']/(compdict['freqs (GHz)'][0]*1e6) blunit = 'k$\lambda$' else: blunit = datablunit kl = 1.0 pl.ioff() #baselines = pl.hypot(baselines[0]/kl, baselines[1]/kl) baselines = pl.hypot(baselines[0], baselines[1]) #if not showplot: # casalog.post('Sorry, not showing the plot is not yet implemented', # 'WARN') if showplot: pl.ion() pl.clf() pl.ioff() nfreqs = len(compdict['freqs (GHz)']) for freqnum in xrange(nfreqs): freq = compdict['freqs (GHz)'][freqnum] casalog.post("Plotting " + str(freq) + " GHz.") pl.plot(baselines/kl, data[freqnum], symb, label="%.3g GHz" % freq) #pl.plot(baselines, data[freqnum], symb, label="%.3g GHz" % freq) pl.xlabel("Baseline length (" + blunit + ")") pl.ylabel("Visibility amplitude (Jy)") if include0amp: pl.ylim(ymin=0.0) if include0bl: pl.xlim(xmin=0.0) pl.suptitle(objname + " (predicted by %s)" % compdict['standard'], fontsize=14) #pl.suptitle(objname + " (predicted)", fontsize=14) # Unlike compdict['antennalist'], antennalist might have had repodir # prefixed to it. pl.title('at ' + epstr + ' for ' + os.path.basename(compdict['antennalist']), fontsize=10) titletxt='($%.0f^\circ$ az, $%.0f^\circ$ el)' % azeldegs # for comparison of old and new models - omit azeldegs as all in az~0 if bl0flux > 0.0: if len(compdict['freqs (GHz)']) == 1: titletxt+='\n bl0 flux:%.3f Jy' % bl0flux else: titletxt+='\n bl0 flux:%.3f Jy @ %s GHz' % (bl0flux, compdict['freqs (GHz)'][0]) pl.legend(loc='best', title=titletxt) #pl.legend(loc='best', title='($%.0f^\circ$ az, $%.0f^\circ$ el)' % azeldegs) y_formatter=matplotlib.ticker.ScalarFormatter(useOffset=False) pl.axes().yaxis.set_major_formatter(y_formatter) if showplot: pl.ion() pl.draw() if compdict.get('savedfig'): pl.savefig(compdict.get('savedfig')) casalog.post("Saved plot to " + str(compdict.get('savedfig'))) if wantdict: retval = {'amps': data, 'antennalist': antennalist, # Absolute path, now. 'azel': azel, 'baselines': baselines, 'blunit': blunit, 'riseset': riset, 'savedfig': compdict.get('savedfig')} else: retval = True except Exception, instance: casalog.post(str(instance), 'SEVERE') if os.path.isdir(tempms): shutil.rmtree(tempms)
def subvs(vis=None, outputvis=None, timerange=None, spw=None, timoffset=4, windowlen=10, windowtype='flat', splitsel=True, reverse=False, overwrite=False): """Vector-subtraction in UV using selected time ranges and spectral channels as background subvs is a function to do UV vector-subtraction. By selecting gliding averaging window, only the low-frequency signals corresponding to the background continuum emission remain. As a result, a uv subtraction of original dynamic spectrum from the background can improve fine stucture such as fibers. Subvs can be used to subtract the background continuum emission to separate the time-dependent emission, e.g. solar coherent radio bursts. Keyword arguments: vis -- Name of input visibility file default: none; example: vis='sun_type3.ms' outputvis -- Name of output visibility file default: none; example: outputvis='sun_type3.sub.ms' timerange -- Select the time range in the data to be subtracted from. timerange = 'YYYY/MM/DD/hh:mm:ss~YYYY/MM/DD/hh:mm:ss' Note: if YYYY/MM/DD is missing date, timerange defaults to the first day in the dataset timerange='09:14:0~09:54:0' picks 40 min on first day timerange='25:00:00~27:30:00' picks 1 hr to 3 hr 30min on next day spw -- Select spectral window/channel. default = '' all the spectral channels. Example: spw='0:1~20' timoffset -- After the convolution, each single channel of smoothed uv vectors in time series are misaligned from original data. Setting the timoffset allow you to shift by the specifed amount of data points. windowlen -- Choose the width the gliding window for smoothing. windowtype -- Choose the type o gliding window. Options available are 'flat', 'hanning', 'hamming', 'bartlett', 'blackman' splitsel -- True of False. default = False. If splitsel = False, then the entire input measurement set is copied as the output measurement set (outputvis), with background subtracted at selected timerange and spectral channels. If splitsel = True,then only the selected timerange and spectral channels are copied into the output measurement set (outputvis). reverse -- True or False. default = False. If reverse = False, then the times indicated by subtime1 and/or subtime2 are treated as background and subtracted; If reverse = True, then reverse the sign of the background-subtracted data. The option can be used for mapping absorptive structure. overwrite -- True or False. default = False. If overwrite = True and outputvis already exists, the selected subtime and spw in the already existing output measurement set will be replaced with subtracted visibilities """ #check the visbility ms if not outputvis or outputvis.isspace(): raise ValueError, 'Please specify outputvis.' if os.path.exists(outputvis): if overwrite: print "The already existing output measurement set will be updated." else: raise ValueError, "Output MS %s already exists - will not overwrite." % outputvis else: if not splitsel: shutil.copytree(vis, outputvis) else: ms.open(vis, nomodify=True) ms.split(outputvis, spw=spw, time=timerange, whichcol='DATA') ms.close() # check and specify time range and channel if timerange and (type(timerange) == str): [btimeo, etimeo] = timerange.split('~') btimeosec = qa.getvalue(qa.convert(qa.totime(btimeo), 's')) etimeosec = qa.getvalue(qa.convert(qa.totime(etimeo), 's')) timebinosec = etimeosec - btimeosec if timebinosec < 0: raise Exception, 'Negative timebin! Please check the "timerange" parameter.' casalog.post('Selected timerange: ' + timerange + ' as the time for UV subtraction.') else: casalog.post( 'Output timerange not specified, using the entire timerange') if spw and (type(spw) == str): [spwid, chanran] = spw.split(':') [bchan, echan] = chanran.split('~') nchan = int(echan) - int(bchan) + 1 else: casalog.post('spw not specified, use all frequency channels') #select data range to be smoothed ms.open(vis, nomodify=True) #Select the spw id ms.msselect({'time': timerange}) ms.selectinit(datadescid=int(spwid)) ms.selectchannel(nchan, int(bchan), 1, 1) rec = ms.getdata(['data', 'time', 'axis_info'], ifraxis=True) #print 'shape of the frequency matrix ',rec1['axis_info']['freq_axis']['chan_freq'].shape sz = rec['data'].shape print 'dimension of selected background for smoothing', rec['data'].shape #the data shape is (n_pol,n_channel,n_baseline,n_time), no need to reshape #rec1['data']=rec1['data'].reshape(sz1[0],sz1[1],sz1[2],nspw,sz1[3]/nspw,order='F') #print 'reshaped rec1 ', rec1['data'].shape if not (timoffset and (type(timoffset) == int)): timoffset = int(4) for i in range(rec['data'].shape[0]): for j in range(rec['data'].shape[1]): for k in range(rec['data'].shape[2]): rec['data'][i, j, k, :] = task_smooth.smooth(rec['data'][i, j, k, :], timoffset, windowlen, windowtype) casalog.post('Smoothing the visibilities in timerange: ' + timerange) ms.close() #do UV subtraction, according to timerange and spw ms.open(outputvis, nomodify=False) if not splitsel: #outputvis is identical to input visibility, do the selection if timerange and (type(timerange == str)): ms.msselect({'time': timerange}) if spw and (type(spw) == str): ms.selectinit(datadescid=int(spwid)) nchan = int(echan) - int(bchan) + 1 ms.selectchannel(nchan, int(bchan), 1, 1) else: #outputvis is splitted, selections have already applied, select all the data ms.selectinit(datadescid=0) orec = ms.getdata(['data', 'time', 'axis_info'], ifraxis=True) b_rows = orec['data'].shape[2] nchan = orec['data'].shape[1] #szo=orec['data'].shape print 'dimension of output data', orec['data'].shape #orec['data']=orec['data'].reshape(szo[0],szo[1],szo[2],nspw,szo[3]/nspw,order='F') #print 'reshaped rec1 ', orec['data'].shape t_rows = orec['data'].shape[3] casalog.post('Number of baselines: ' + str(b_rows)) casalog.post('Number of spectral channels: ' + str(nchan)) casalog.post('Number of time pixels: ' + str(t_rows)) casalog.post('Subtracting background defined in timerange: ' + timerange) for i in range(t_rows): orec['data'][:, :, :, i] -= rec['data'][:, :, :, i] if reverse: orec['data'][:, :, :, i] = -orec['data'][:, :, :, i] del orec['time'] del orec['axis_info'] ms.putdata(orec) ms.close()
plotmasked, maskedcolor, showaxislabel, showtick, showticklabel, parsed_size, nx, ny, transparent, plotrange) except Exception, e: casalog.post('Error: %s' % (str(e)), priority='SEVERE') import traceback casalog.post(traceback.format_exc(), priority='DEBUG') raise e finally: pass NoData = -32767.0 NoDataThreshold = NoData + 10000.0 LightSpeedQuantity = qa.constants('c') LightSpeed = qa.convert(LightSpeedQuantity, 'km/s')['value'] # speed of light in km/s DPIDetail = 130 dsyb = '$^\circ$' hsyb = ':' msyb = ':' def Deg2HMS(x, arrowance): # Transform degree to HHMMSS.sss format xx = x % 360 + arrowance h = int(xx / 15) m = int((xx % 15) * 4) s = ((xx % 15) * 4 - m) * 60.0 return (h, m, s)
def ptclean3(vis, imageprefix, imagesuffix, ncpu, twidth, doreg, usephacenter, reftime, toTb, overwrite, selectdata, field, spw, timerange, uvrange, antenna, scan, observation, intent, datacolumn, imsize, cell, phasecenter, stokes, projection, startmodel, specmode, reffreq, nchan, start, width, outframe, veltype, restfreq, interpolation, gridder, facets, chanchunks, wprojplanes, vptable, usepointing, mosweight, aterm, psterm, wbawp, conjbeams, cfcache, computepastep, rotatepastep, pblimit, normtype, deconvolver, scales, nterms, smallscalebias, restoration, restoringbeam, pbcor, outlierfile, weighting, robust, npixels, uvtaper, niter, gain, threshold, nsigma, cycleniter, cyclefactor, minpsffraction, maxpsffraction, interactive, usemask, mask, pbmask, sidelobethreshold, noisethreshold, lownoisethreshold, negativethreshold, smoothfactor, minbeamfrac, cutthreshold, growiterations, dogrowprune, minpercentchange, verbose, restart, savemodel, calcres, calcpsf, parallel, subregion): if not (type(ncpu) is int): casalog.post('ncpu should be an integer') ncpu = 8 if doreg: # check if ephem and msinfo exist. If not, generate one on the fly try: ephem = hf.read_horizons(vis=vis) except ValueError: print("error in obtaining ephemeris") try: msinfo = hf.read_msinfo(vis) except ValueError: print("error in getting ms info") else: ephem = None msinfo = None if imageprefix: workdir = os.path.dirname(imageprefix) else: workdir = './' tmpdir = workdir + '/tmp/' if not os.path.exists(tmpdir): os.makedirs(tmpdir) # get number of time pixels ms.open(vis) ms.selectinit() timfreq = ms.getdata(['time', 'axis_info'], ifraxis=True) tim = timfreq['time'] ms.close() if twidth < 1: casalog.post('twidth less than 1. Change to 1') twidth = 1 if twidth > len(tim): casalog.post( 'twidth greater than # of time pixels in the dataset. Change to the timerange of the entire dateset' ) twidth = len(tim) # find out the start and end time index according to the parameter timerange # if not defined (empty string), use start and end from the entire time of the ms if not timerange: btidx = 0 etidx = len(tim) - 1 else: try: (tstart, tend) = timerange.split('~') bt_s = qa.convert(qa.quantity(tstart, 's'), 's')['value'] et_s = qa.convert(qa.quantity(tend, 's'), 's')['value'] # only time is given but not date, add the date (at 0 UT) from the first record if bt_s < 86400. or et_s < 86400.: bt_s += np.fix( qa.convert(qa.quantity(tim[0], 's'), 'd')['value']) * 86400. et_s += np.fix( qa.convert(qa.quantity(tim[0], 's'), 'd')['value']) * 86400. btidx = np.argmin(np.abs(tim - bt_s)) etidx = np.argmin(np.abs(tim - et_s)) # make the indice back to those bracket by the timerange if tim[btidx] < bt_s: btidx += 1 if tim[etidx] > et_s: etidx -= 1 if etidx <= btidx: print("ending time must be greater than starting time") print("reinitiating to the entire time range") btidx = 0 etidx = len(tim) - 1 except ValueError: print("keyword 'timerange' has a wrong format") btstr = qa.time(qa.quantity(tim[btidx], 's'), prec=9, form='fits')[0] etstr = qa.time(qa.quantity(tim[etidx], 's'), prec=9, form='fits')[0] iterable = range(btidx, etidx + 1, twidth) print('First time pixel: ' + btstr) print('Last time pixel: ' + etstr) print(str(len(iterable)) + ' images to clean...') res = [] # partition clnpart = partial( clean_iter, tim, vis, imageprefix, imagesuffix, twidth, doreg, usephacenter, reftime, ephem, msinfo, toTb, overwrite, selectdata, field, spw, uvrange, antenna, scan, observation, intent, datacolumn, imsize, cell, phasecenter, stokes, projection, startmodel, specmode, reffreq, nchan, start, width, outframe, veltype, restfreq, interpolation, gridder, facets, chanchunks, wprojplanes, vptable, usepointing, mosweight, aterm, psterm, wbawp, conjbeams, cfcache, computepastep, rotatepastep, pblimit, normtype, deconvolver, scales, nterms, smallscalebias, restoration, restoringbeam, pbcor, outlierfile, weighting, robust, npixels, uvtaper, niter, gain, threshold, nsigma, cycleniter, cyclefactor, minpsffraction, maxpsffraction, interactive, usemask, mask, pbmask, sidelobethreshold, noisethreshold, lownoisethreshold, negativethreshold, smoothfactor, minbeamfrac, cutthreshold, growiterations, dogrowprune, minpercentchange, verbose, restart, savemodel, calcres, calcpsf, parallel, subregion, tmpdir) timelapse = 0 t0 = time() # parallelization if ncpu > 1: import multiprocessing as mprocs casalog.post('Perform clean in parallel ...') print('Perform clean in parallel ...') pool = mprocs.Pool(ncpu) res = pool.map(clnpart, iterable) pool.close() pool.join() else: casalog.post('Perform clean in single process ...') print('Perform clean in single process ...') for i in iterable: res.append(clnpart(i)) t1 = time() timelapse = t1 - t0 print('It took %f secs to complete' % timelapse) # repackage this into a single dictionary results = { 'Succeeded': [], 'BeginTime': [], 'EndTime': [], 'ImageName': [] } for r in res: results['Succeeded'].append(r[0]) results['BeginTime'].append(r[1]) results['EndTime'].append(r[2]) results['ImageName'].append(r[3]) if os.path.exists(tmpdir): os.system('rm -rf ' + tmpdir) return results
def read_msinfo(vis=None, msinfofile=None, use_scan_time=True): import glob # read MS information # msinfo = dict.fromkeys([ 'vis', 'scans', 'fieldids', 'btimes', 'btimestr', 'inttimes', 'ras', 'decs', 'observatory' ]) ms.open(vis) metadata = ms.metadata() observatory = metadata.observatorynames()[0] scans = ms.getscansummary() scanids = sorted(scans.keys(), key=lambda x: int(x)) nscanid = len(scanids) btimes = [] btimestr = [] etimes = [] fieldids = [] inttimes = [] dirs = [] ras = [] decs = [] ephem_file = glob.glob(vis + '/FIELD/EPHEM*SUN.tab') if ephem_file: print('Loading ephemeris info from {}'.format(ephem_file[0])) tb.open(ephem_file[0]) col_ra = tb.getcol('RA') col_dec = tb.getcol('DEC') col_mjd = tb.getcol('MJD') if use_scan_time: from scipy.interpolate import interp1d f_ra = interp1d(col_mjd, col_ra) f_dec = interp1d(col_mjd, col_dec) for idx, scanid in enumerate(scanids): btimes.append(scans[scanid]['0']['BeginTime']) etimes.append(scans[scanid]['0']['EndTime']) fieldid = scans[scanid]['0']['FieldId'] fieldids.append(fieldid) inttimes.append(scans[scanid]['0']['IntegrationTime']) ras = f_ra(np.array(btimes)) decs = f_dec(np.array(btimes)) ras = qa.convert(qa.quantity(ras, 'deg'), 'rad') decs = qa.convert(qa.quantity(decs, 'deg'), 'rad') else: ras = qa.convert(qa.quantity(col_ra, 'deg'), 'rad') decs = qa.convert(qa.quantity(col_dec, 'deg'), 'rad') else: for idx, scanid in enumerate(scanids): btimes.append(scans[scanid]['0']['BeginTime']) etimes.append(scans[scanid]['0']['EndTime']) fieldid = scans[scanid]['0']['FieldId'] fieldids.append(fieldid) inttimes.append(scans[scanid]['0']['IntegrationTime']) dir = ms.getfielddirmeas('PHASE_DIR', fieldid) dirs.append(dir) ras.append(dir['m0']) decs.append(dir['m1']) ms.close() btimestr = [ qa.time(qa.quantity(btimes[idx], 'd'), form='fits', prec=10)[0] for idx in range(nscanid) ] msinfo['vis'] = vis msinfo['scans'] = scans msinfo['fieldids'] = fieldids msinfo['btimes'] = btimes msinfo['btimestr'] = btimestr msinfo['inttimes'] = inttimes msinfo['ras'] = ras msinfo['decs'] = decs msinfo['observatory'] = observatory if msinfofile: np.savez(msinfofile, vis=vis, scans=scans, fieldids=fieldids, btimes=btimes, btimestr=btimestr, inttimes=inttimes, ras=ras, decs=decs, observatory=observatory) return msinfo
def split_core(vis, outputvis, datacolumn, field, spw, width, antenna, timebin, timerange, scan, intent, array, uvrange, correlation, observation, combine, keepflags): retval = True if not outputvis or outputvis.isspace(): raise ValueError, 'Please specify outputvis' myms = mstool() mytb = None if ((type(vis)==str) & (os.path.exists(vis))): myms.open(vis, nomodify=True) else: raise ValueError, 'Visibility data set not found - please verify the name' if os.path.exists(outputvis): myms.close() raise ValueError, "Output MS %s already exists - will not overwrite." % outputvis if (os.path.exists(outputvis+".flagversions")): myms.close() raise ValueError, "The flagversions \"%s.flagversions\" for the output MS already exist. Please delete." % outputvis # No longer needed. When did it get put in? Note that the default # spw='*' in myms.split ends up as '' since the default type for a variant # is BOOLVEC. (Of course!) Therefore both split and myms.split must # work properly when spw=''. #if(spw == ''): # spw = '*' if(type(antenna) == list): antenna = ', '.join([str(ant) for ant in antenna]) ## Accept digits without units ...assume seconds timebin = qa.convert(qa.quantity(timebin), 's')['value'] timebin = str(timebin) + 's' if timebin == '0s': timebin = '-1s' # MSStateGram is picky ('CALIBRATE_WVR.REFERENCE, OBSERVE_TARGET_ON_SOURCE' # doesn't work, but 'CALIBRATE_WVR.REFERENCE,OBSERVE_TARGET_ON_SOURCE' # does), and I don't want to mess with bison now. A .upper() might be a # good idea too, but the MS def'n v.2 does not say whether OBS_MODE should # be case-insensitive. intent = intent.replace(', ', ',') if '^' in spw: casalog.post("The interpretation of ^n in split's spw strings has changed from 'average n' to 'skip n' channels!", 'WARN') casalog.post("Watch for Slicer errors", 'WARN') if type(width) == str: try: if(width.isdigit()): width=[string.atoi(width)] elif(width.count('[') == 1 and width.count(']') == 1): width = width.replace('[', '') width = width.replace(']', '') splitwidth = width.split(',') width = [] for ws in splitwidth: if(ws.isdigit()): width.append(string.atoi(ws)) else: width = [1] except: raise TypeError, 'parameter width is invalid...using 1' if type(correlation) == list: correlation = ', '.join(correlation) correlation = correlation.upper() if hasattr(combine, '__iter__'): combine = ', '.join(combine) if type(spw) == list: spw = ','.join([str(s) for s in spw]) elif type(spw) == int: spw = str(spw) do_chan_mod = spw.find('^') > -1 # '0:2~11^1' would be pointless. if not do_chan_mod: # ...look in width. if type(width) == int and width > 1: do_chan_mod = True elif hasattr(width, '__iter__'): for w in width: if w > 1: do_chan_mod = True break do_both_chan_and_time_mod = (do_chan_mod and string.atof(timebin[:-1]) > 0.0) if do_both_chan_and_time_mod: # Do channel averaging first because it might be included in the spw # string. import tempfile # We want the directory outputvis is in, not /tmp, because /tmp # might not have enough space. # outputvis is itself a directory, so strip off a trailing slash if # it is present. # I don't know if giving tempfile an absolute directory is necessary - # dir='' is effectively '.' in Ubuntu. workingdir = os.path.abspath(os.path.dirname(outputvis.rstrip('/'))) cavms = tempfile.mkdtemp(suffix=outputvis, dir=workingdir) casalog.post('Channel averaging to ' + cavms) if not myms.split(outputms=cavms, field=field, spw=spw, step=width, baseline=antenna, subarray=array, timebin='', time=timerange, whichcol=datacolumn, scan=scan, uvrange=uvrange, combine=combine, correlation=correlation, intent=intent, obs=str(observation)): myms.close() if os.path.isdir(cavms): import shutil shutil.rmtree(cavms) return False # The selection was already made, so blank them before time averaging. field = '' spw = '' width = [1] antenna = '' array = '' timerange = '' datacolumn = 'all' scan = '' intent = '' uvrange = '' observation = '' myms.close() myms.open(cavms) casalog.post('Starting time averaging') if keepflags: taqlstr = '' else: taqlstr = 'NOT (FLAG_ROW OR ALL(FLAG))' if not myms.split(outputms=outputvis, field=field, spw=spw, step=width, baseline=antenna, subarray=array, timebin=timebin, time=timerange, whichcol=datacolumn, scan=scan, uvrange=uvrange, combine=combine, correlation=correlation, taql=taqlstr, intent=intent, obs=str(observation)): myms.close() return False myms.close() if do_both_chan_and_time_mod: import shutil shutil.rmtree(cavms) # Write history to output MS, not the input ms. try: param_names = split_core.func_code.co_varnames[:split_core.func_code.co_argcount] param_vals = [eval(p) for p in param_names] retval &= write_history(myms, outputvis, 'oldsplit', param_names, param_vals, casalog) except Exception, instance: casalog.post("*** Error \'%s\' updating HISTORY" % (instance), 'WARN')
def ephem_to_helio(vis=None, ephem=None, msinfo=None, reftime=None, polyfit=None, usephacenter=False): '''1. Take a solar ms database, read the scan and field information, find out the pointings (in RA and DEC) 2. Compare with the ephemeris of the solar disk center (in RA and DEC) 3. Generate VLA pointings in heliocentric coordinates inputs: msinfo: CASA MS information, output from read_msinfo ephem: solar ephem, output from read_horizons reftime: list of reference times (e.g., used for imaging) CASA standard time format, either a single time (e.g., '2012/03/03/12:00:00' or a time range (e.g., '2012/03/03/12:00:00~2012/03/03/13:00:00'. If the latter, take the midpoint of the timerange for reference. If no date specified, take the date of the first scan polyfit: ONLY works for MS database with only one source with continously tracking; not recommanded unless scan length is too long and want to have very high accuracy usephacenter: Bool -- if True, correct for the RA and DEC in the ms file based on solar empheris. Otherwise assume the phasecenter is correctly pointed to the solar disk center (EOVSA case) return value: helio: a list of VLA pointing information reftimestr: reference time, in FITS format string reftime: reference time, in mjd format ra: actual RA of phasecenter in the ms file at the reference time (interpolated) dec: actual DEC of phasecenter in the ms file at the reference time (interpolated) # CASA uses only RA and DEC of the closest field (e.g. in clean) # ra_fld: right ascention of the CASA reference pointing direction dec_fld: declination of the CASA reference pointing direction raoff: RA offset of the phasecenter in the ms file to solar center decoff: DEC offset of the phasecenter in the ms file to solar center refx: heliocentric X offset of the phasecenter in the ms file to solar center refy: heliocentric Y offset of the phasecenter in the ms file to solar center ######## Example ######### msfile='sun_C_20140910T221952-222952.10s.cal.ms' ephemfile='horizons_sun_20140910.radecp' ephem=vla_prep.read_horizons(ephemfile=ephemfile) msinfo=vla_prep.read_msinfo(msfile=msfile) polyfit=0 reftime = '22:25:20~22:25:40' ''' if not vis or not os.path.exists(vis): raise ValueError('Please provide information of the MS database!') if not ephem: ephem = read_horizons(vis=vis) if not msinfo: msinfo0 = read_msinfo(vis) else: if isinstance(msinfo, str): try: msinfo0 = np.load(msinfo) except: raise ValueError( 'The specified input msinfo file does not exist!') elif isinstance(msinfo, dict): msinfo0 = msinfo else: raise ValueError( 'msinfo should be either a numpy npz or a dictionary') print('msinfo is derived from: {0:s}'.format(msinfo0['vis'])) scans = msinfo0['scans'] fieldids = msinfo0['fieldids'] btimes = msinfo0['btimes'] inttimes = msinfo0['inttimes'] ras = msinfo0['ras'] decs = msinfo0['decs'] if 'observatory' in msinfo0.keys(): if msinfo0['observatory'] == 'EOVSA': usephacenter = False if type(ras) is list: ra_rads = [ra['value'] for ra in ras] elif type(ras) is dict: ra_rads = ras['value'] else: print('Type of msinfo0["ras"] unrecognized.') return 0 if type(decs) is list: dec_rads = [dec['value'] for dec in decs] elif type(decs) is dict: dec_rads = decs['value'] else: print('Type of msinfo0["decs"] unrecognized.') # fit 2nd order polynomial fits to the RAs and DECs # if polyfit: cra = np.polyfit(btimes, ra_rads, 2) cdec = np.polyfit(btimes, dec_rads, 2) # find out phase center infomation in ms according to the input time or timerange # if not reftime: raise ValueError('Please specify a reference time of the image') if type(reftime) == str: reftime = [reftime] if (not isinstance(reftime, list)): print('input "reftime" is not a valid list. Abort...') nreftime = len(reftime) helio = [] for reftime0 in reftime: helio0 = dict.fromkeys([ 'reftimestr', 'reftime', 'ra', 'dec', 'ra_fld', 'dec_fld', 'raoff', 'decoff', 'refx', 'refy', 'p0' ]) helio0['reftimestr'] = reftime0 if '~' in reftime0: # if reftime0 is specified as a timerange try: [tbg0, tend0] = reftime0.split('~') tbg_d = qa.getvalue(qa.convert(qa.totime(tbg0), 'd'))[0] tend_d = qa.getvalue(qa.convert(qa.totime(tend0), 'd'))[0] tdur_s = (tend_d - tbg_d) * 3600. * 24. # if no date is specified, add up the date of the first scan if tend_d < 1.: if tend_d >= tbg_d: tend_d += int(btimes[0]) else: tend_d += int(btimes[0]) + 1 if tbg_d < 1.: tbg_d += int(btimes[0]) tref_d = (tbg_d + tend_d) / 2. except: print('Error in converting the input reftime: ' + str(reftime0) + '. Aborting...') else: # if reftime0 is specified as a single value try: tref_d = qa.getvalue(qa.convert(qa.totime(reftime0), 'd'))[0] # if no date is specified, add up the date of the first scan if tref_d < 1.: tref_d += int(btimes[0]) tbg_d = tref_d # use the intergration time # ind = bisect.bisect_left(btimes, tref_d) # if msinfo0['etimes']: # tdur_s = inttimes[ind - 1] # else: # tdur_s = np.mean(inttimes) tdur_s = 1. except: print('Error in converting the input reftime: ' + str(reftime0) + '. Aborting...') helio0['reftime'] = tref_d # helio0['date-obs'] = qa.time(qa.quantity(tbg_d, 'd'), form='fits', prec=10)[0] # helio0['exptime'] = tdur_s # find out phase center RA and DEC in the measurement set according to the reference time # if polyfit, then use the 2nd order polynomial coeffs inttime = np.nanmean(inttimes) ind = bisect.bisect_left(btimes, tref_d) if ind > 1: dt = tref_d - btimes[ind - 1] if ind < len(btimes): scanlen = btimes[ind] - btimes[ind - 1] (ra_b, ra_e) = (ra_rads[ind - 1], ra_rads[ind]) (dec_b, dec_e) = (dec_rads[ind - 1], dec_rads[ind]) if ind >= len(btimes): scanlen = btimes[ind - 1] - btimes[ind - 2] (ra_b, ra_e) = (ra_rads[ind - 2], ra_rads[ind - 1]) (dec_b, dec_e) = (dec_rads[ind - 2], dec_rads[ind - 1]) if ind == 1: # only one scan exists (e.g., imported from AIPS) ra_b = ra_rads[ind - 1] ra_e = ra_b dec_b = dec_rads[ind - 1] dec_e = dec_b scanlen = 10. # radom value dt = 0. if ind < 1: if np.abs((tref_d - btimes[0]) * 24 * 3600) < inttime / 2.0: ind = 1 ra_b = ra_rads[ind - 1] ra_e = ra_b dec_b = dec_rads[ind - 1] dec_e = dec_b scanlen = 10. # radom value dt = 0. else: raise ValueError( 'Reference time does not fall into the scan list!') if polyfit: ra = cra[0] * tref_d**2. + cra[1] * tref_d + cra[2] dec = cdec[0] * tref_d**2. + cdec[1] * tref_d + cdec[2] # if not, use linearly interpolated RA and DEC at the beginning of this scan and next scan else: ra = ra_b + (ra_e - ra_b) / scanlen * dt dec = dec_b + (dec_e - dec_b) / scanlen * dt if ra < 0: ra += 2. * np.pi if ra_b < 0: ra_b += 2. * np.pi # compare with ephemeris from JPL Horizons time0 = ephem['time'] ra0 = ephem['ra'] dec0 = ephem['dec'] p0 = ephem['p0'] delta0 = ephem['delta'] if len(time0) > 1: ind = bisect.bisect_left(time0, tref_d) dt0 = time0[ind] - time0[ind - 1] dt_ref = tref_d - time0[ind - 1] dra0 = ra0[ind] - ra0[ind - 1] ddec0 = dec0[ind] - dec0[ind - 1] dp0 = p0[ind] - p0[ind - 1] ddelta0 = delta0[ind] - delta0[ind - 1] ra0 = ra0[ind - 1] + dra0 / dt0 * dt_ref dec0 = dec0[ind - 1] + ddec0 / dt0 * dt_ref p0 = p0[ind - 1] + dp0 / dt0 * dt_ref delta0 = delta0[ind - 1] + ddelta0 / dt0 * dt_ref else: try: ra0 = ra0[0] dec0 = dec0[0] p0 = p0[0] delta0 = delta0[0] except: print("Error in retrieving info from ephemeris!") if ra0 < 0: ra0 += 2. * np.pi # RA and DEC offset in arcseconds decoff = degrees((dec - dec0)) * 3600. raoff = degrees((ra - ra0) * cos(dec)) * 3600. # Convert into heliocentric offsets prad = -radians(p0) refx = (-raoff) * cos(prad) - decoff * sin(prad) refy = (-raoff) * sin(prad) + decoff * cos(prad) helio0['ra'] = ra # ra of the actual pointing helio0['dec'] = dec # dec of the actual pointing helio0[ 'ra_fld'] = ra_b # ra of the field, used as the reference in e.g., clean helio0[ 'dec_fld'] = dec_b # dec of the field, used as the refenrence in e.g., clean helio0['raoff'] = raoff helio0['decoff'] = decoff if usephacenter: helio0['refx'] = refx helio0['refy'] = refy else: helio0['refx'] = 0. helio0['refy'] = 0. helio0['p0'] = p0 # helio['r_sun']=np.degrees(R_sun.value/(au.value*delta0))*3600. #in arcsecs helio.append(helio0) return helio
def ptclean(vis, imageprefix, ncpu, twidth, doreg, overwrite, ephemfile, msinfofile, outlierfile, field, spw, selectdata, timerange, uvrange, antenna, scan, observation, intent, mode, resmooth, gridmode, wprojplanes, facets, cfcache, rotpainc, painc, aterm, psterm, mterm, wbawp, conjbeams, epjtable, interpolation, niter, gain, threshold, psfmode, imagermode, ftmachine, mosweight, scaletype, multiscale, negcomponent, smallscalebias, interactive, mask, nchan, start, width, outframe, veltype, imsize, cell, phasecenter, restfreq, stokes, weighting, robust, uvtaper, outertaper, innertaper, modelimage, restoringbeam, pbcor, minpb, usescratch, noise, npixels, npercycle, cyclefactor, cyclespeedup, nterms, reffreq, chaniter, flatnoise, allowchunk): if not (type(ncpu) is int): casalog.post('ncpu should be an integer') ncpu = 8 if doreg: # check if ephemfile and msinfofile exist try: ephem = vla_prep.read_horizons(ephemfile=ephemfile) except ValueError: print("error in reading ephemeris file") if not os.path.isfile(msinfofile): print("msinfofile does not exist!") else: ephem = None # get number of time pixels ms.open(vis) ms.selectinit() timfreq = ms.getdata(['time', 'axis_info'], ifraxis=True) tim = timfreq['time'] # dt = tim[1]-tim[0] #need to change to median of all time intervals dt = np.median(np.diff(tim)) freq = timfreq['axis_info']['freq_axis']['chan_freq'].flatten() ms.close() if twidth < 1 or twidth > len(tim): casalog.post( 'twidth not between 1 and # of time pixels in the dataset. Change to 1' ) twidth = 1 # find out the start and end time index according to the parameter timerange # if not defined (empty string), use start and end from the entire time of the ms if not timerange: btidx = 0 etidx = len(tim) - 1 else: try: (tstart, tend) = timerange.split('~') bt_s = qa.convert(qa.quantity(tstart, 's'), 's')['value'] et_s = qa.convert(qa.quantity(tend, 's'), 's')['value'] # only time is given but not date, add the date (at 0 UT) from the first record if bt_s < 86400. or et_s < 86400.: bt_s += np.fix( qa.convert(qa.quantity(tim[0], 's'), 'd')['value']) * 86400. et_s += np.fix( qa.convert(qa.quantity(tim[0], 's'), 'd')['value']) * 86400. btidx = np.argmin(np.abs(tim - bt_s)) etidx = np.argmin(np.abs(tim - et_s)) # make the indice back to those bracket by the timerange if tim[btidx] < bt_s: btidx += 1 if tim[etidx] > et_s: etidx -= 1 if etidx <= btidx: print "ending time must be greater than starting time" print "reinitiating to the entire time range" btidx = 0 etidx = len(tim) - 1 except ValueError: print "keyword 'timerange' has a wrong format" btstr = qa.time(qa.quantity(tim[btidx], 's'), prec=9, form='fits')[0] etstr = qa.time(qa.quantity(tim[etidx], 's'), prec=9, form='fits')[0] iterable = range(btidx, etidx + 1, twidth) print 'First time pixel: ' + btstr print 'Last time pixel: ' + etstr print str(len(iterable)) + ' images to clean...' res = [] # partition clnpart = partial( clean_iter, tim, freq, vis, imageprefix, ncpu, twidth, doreg, overwrite, ephemfile, ephem, msinfofile, outlierfile, field, spw, selectdata, uvrange, antenna, scan, observation, intent, mode, resmooth, gridmode, wprojplanes, facets, cfcache, rotpainc, painc, aterm, psterm, mterm, wbawp, conjbeams, epjtable, interpolation, niter, gain, threshold, psfmode, imagermode, ftmachine, mosweight, scaletype, multiscale, negcomponent, smallscalebias, interactive, mask, nchan, start, width, outframe, veltype, imsize, cell, phasecenter, restfreq, stokes, weighting, robust, uvtaper, outertaper, innertaper, modelimage, restoringbeam, pbcor, minpb, usescratch, noise, npixels, npercycle, cyclefactor, cyclespeedup, nterms, reffreq, chaniter, flatnoise, allowchunk) timelapse = 0 t0 = time() # parallelization para = 1 if para: casalog.post('Perform clean in parallel ...') pool = mp.Pool(ncpu) # res = pool.map_async(clnpart, iterable) res = pool.map(clnpart, iterable) pool.close() pool.join() else: for i in iterable: res.append(clnpart(i)) t1 = time() timelapse = t1 - t0 print 'It took %f secs to complete' % timelapse # repackage this into a single dictionary results = {'succeeded': [], 'timestamps': [], 'imagenames': []} for r in res: results['succeeded'].append(r[0]) results['timestamps'].append(r[1]) results['imagenames'].append(r[2]) return results
def readJPLephem(fmfile, version=''): """ Reads a JPL Horizons text file (see http://ssd.jpl.nasa.gov/horizons.cgi#top ) for a solar system object and returns various quantities in a dictionary. The dict will be blank ({}) if there is a failure. """ retdict = {} casalog.origin('readJPLephem') # Try opening fmfile now, because otherwise there's no point continuing. try: ephem = open(fmfile, 'rb') print("opened the file=", fmfile) lines = ephem.readlines() # skip this, handle by rstrip later #crCount=0 #newlines='' #newln='' #for ln in lines: # n = ln.count('\r') # if n > 0: # newln=ln.replace('\r','\n') # crCount+=n # newlines += newln #if crCount > 0: # print("The input file appears to contains the carriage return code, \'^M\', will replace it with \'\\n\'...") # raw_input('pause0') # ephem.close() # ephem = open('temp_ephem_data.txt','w+') # ephem.write(newlines) ephem.seek(0) except IOError: casalog.post("Could not open ephemeris file " + fmfile, priority="SEVERE") return {} # reset to default search pattern for MJD cols['MJD']['pat'] = r'(?P<MJD>\d+-\w+-\d+ \d+:\d+)' # Setup the regexps. # Headers (one time only things) # Dictionary of quantity label: regexp pattern pairs that will be searched # for once. The matching quantity will go in retdict[label]. Only a # single quantity (group) will be retrieved per line. headers = { 'NAME': { 'pat': r'^[>\s]*Target body name:\s+\d*\s*(\w+)' }, # object name, w.o. number 'ephtype': { 'pat': r'\?s_type=1#top>\]\s*:\s+\*(\w+)' }, # e.g. OBSERVER 'obsloc': { 'pat': r'^[>\s]*Center-site name:\s+(\w+)' }, # e.g. GEOCENTRIC # Catch either an explicit mean radius or a solitary target radius. 'meanrad': { 'pat': r'(?:Mean radius \(km\)\s*=|^Target radii\s*:)\s*([0-9.]+)(?:\s*km)?\s*$', 'unit': 'km' }, # Triaxial target radii #'radii': {'pat': r'Target radii\s*:\s*([0-9.]+\s*x\s*[0-9.]+\s*x\s*[0-9.]+)\s*km.*Equator, meridian, pole', 'radii': { 'pat': r'Target radii\s*:\s*([0-9.]+\s*x\s*[0-9.]+\s*x\s*[0-9.]+)\s*km.*Equator, meridian, pole|Target radii\s*:\s*([0-9.]+)\s*km\s*', 'unit': 'km' }, 'T_mean': { 'pat': r'Mean Temperature \(K\)\s*=\s*([0-9.]+)', 'unit': 'K' }, # Figure out the units later. 'rot_per': { 'pat': r'(?i)(?<!Inferred )\b(rot(ation(al)?|\.)?\s*per.*=\s*([-0-9.]+\s*[dhr]*|Synchronous))' }, 'orb_per': { 'pat': r'Orbital period((, days)?\s*=\s*[-0-9.]+\s*[dhr](\s*\(?R\)?)?)' }, # MeasComet does not read units for these! E-lon(deg), Lat(deg), Alt(km) 'GeoLong': { 'pat': r'^[>\s]*Center geodetic\s*: ([-+0-9.]+,\s*[-+0-9.]+,\s*[-+0-9.]+)' }, 'dMJD': { 'pat': r'^[>\s]*Step-size\s*:\s*(.+)' }, # request method v wday mth mday hh mm ss yyyy 'VS_CREATE': { 'pat': r'^[>\s]*Ephemeris / \w+ \w+ (\w+\s+\d+\s+\d+:\d+:\d+\s+\d+)' } } for hk in headers: headers[hk]['pat'] = re.compile(headers[hk]['pat']) # Data ("the rows of the table") # need date, r (heliocentric distance), delta (geocentric distance), and phang (phase angle). # (Could use the "dot" time derivatives for Doppler shifting, but it's # likely unnecessary.) #datapat = r'^[>\s]*' datapat = r'^\s*' stoppat = r'[>\s]*\$\$EOE$' # Signifies the end of data. # Read fmfile into retdict. num_cols = 0 in_data = False comp_mismatches = [] print_datapat = False # define interpretation of invalid values ('n.a.') invalid = -999. for origline in ephem: line = origline.rstrip('\r\n') if in_data: if re.match(stoppat, line): break matchobj = re.search(datapat, line) if matchobj: #print("matchobj!") gdict = matchobj.groupdict() #print("gdict=",gdict) for col in gdict: if gdict[col] == 'n.a.': gdict[col] = invalid # print("cols.key=",cols.keys()) if not cols[col].get('unwanted'): retdict['data'][col]['data'].append(gdict[col]) if len(gdict) < num_cols: print("Partially mismatching line:") print(line) print("Found:") print(gdict) print_datapat = True raw_input("pause0") else: print_datapat = True # Chomp trailing whitespace. comp_mismatches.append(re.sub(r'\s*$', '', line)) elif re.match( r'^[>\s]*' + cols['MJD']['header'] + r'\s+' + cols['RA']['header'], line): # need to modify regex to search for the header name for MJD containing second digits if re.match(r'^[>\s]*Date__\(UT\)__HR:MN:SC.fff', line): cols['MJD']['pat'] = r'(?P<MJD>\d+-\w+-\d+ \d+:\d+:\d+.\d+)' # See what columns are present, and finish setting up datapat and # retdict. havecols = [] # extract coordinate ref info m = re.match(r'(^[>\s]*)(\S+)(\s+)(' + cols['RA']['header'] + ')', line) coordref = m.group(4).split('(')[-1] cols['RA']['comment'] += '(' + coordref + ')' cols['DEC']['comment'] += '(' + coordref + ')' #print("cols['RA']['comment']=", cols['RA']['comment']) # Chomp trailing whitespace. myline = re.sub(r'\s*$', '', line) titleline = myline remaining_cols = cols.keys() found_col = True # This loop will terminate one way or another. while myline and remaining_cols and found_col: found_col = False #print("myline = '%s'" % myline) #print("remaining_cols =", ', '.join(remaining_cols)) for col in remaining_cols: if re.match(r'^[>\s]*' + cols[col]['header'], myline): #print("Found", col) havecols.append(col) remaining_cols.remove(col) myline = re.sub(r'^[>\s]*' + cols[col]['header'], '', myline) found_col = True break datapat += r'\s+'.join([cols[col]['pat'] for col in havecols]) sdatapat = datapat casalog.post("Found columns: " + ', '.join(havecols)) datapat = re.compile(datapat) retdict['data'] = {} for col in havecols: if not cols[col].get('unwanted'): retdict['data'][col] = { 'comment': cols[col]['comment'], 'data': [] } num_cols = len(retdict['data']) #elif re.match(r'^\$\$SOE\s*$', line): # Start of ephemeris elif re.match(r'^[>\s]*\$\$SOE\s*$', line): # Start of ephemeris casalog.post("Starting to read data.", priority='INFO2') in_data = True else: #print("line =", line) #print("looking for",) for hk in headers: #print("hk=",hk) if not retdict.has_key(hk): matchobj = re.search(headers[hk]['pat'], line) if matchobj: if hk == 'radii': mobjs = matchobj.groups() for gp in mobjs: if gp != None: retdict[hk] = gp break break else: retdict[hk] = matchobj.group( 1) # 0 is the whole line break ephem.close() # clean up the temp file if exists #if os.path.exists('temp_ephem_data.txt'): # os.remove('temp_ephem_data.txt') # If there were errors, provide debugging info. if comp_mismatches: print("Completely mismatching lines:") #print("\n".join(comp_mismatches)) if print_datapat: print("The apparent title line is:") print(titleline) print("datapat = r'%s'" % sdatapat) # Convert numerical strings into actual numbers. try: retdict['earliest'] = datestr_to_epoch( retdict['data']['MJD']['data'][0]) retdict['latest'] = datestr_to_epoch( retdict['data']['MJD']['data'][-1]) except Exception as e: print("Error!") if retdict.has_key('data'): if retdict['data'].has_key('MJD'): if retdict['data']['MJD'].has_key('data'): #print("retdict['data']['MJD']['data'] =", retdict['data']['MJD']['data']) print("retdict['data'] =", retdict['data']) else: print("retdict['data']['MJD'] has no 'data' key.") print("retdict['data']['MJD'].keys() =", retdict['data']['MJD'].keys()) else: print("retdict['data'] has no 'MJD' key.") print("retdict['data'].keys() =", retdict['data'].keys()) else: print("retdict has no 'data' key.") raise e for hk in headers: if retdict.has_key(hk): if headers[hk].has_key('unit'): if hk == 'radii': radii = retdict[hk].split('x') if len(radii) == 1: a = float(radii[0]) retdict[hk] = { 'unit': headers[hk]['unit'], 'value': (a, a, a) } retdict['meanrad'] = { 'unit': headers[hk]['unit'], 'value': a } else: a, b, c = [float(r) for r in radii] retdict[hk] = { 'unit': headers[hk]['unit'], 'value': (a, b, c) } retdict['meanrad'] = { 'unit': headers[hk]['unit'], 'value': mean_radius(a, b, c) } else: try: # meanrad might already have been converted. if type(retdict[hk]) != dict: retdict[hk] = { 'unit': headers[hk]['unit'], 'value': float(retdict[hk]) } except Exception as e: print("Error converting header", hk, "to a Quantity.") print("retdict[hk] =", retdict[hk]) raise e elif hk == 'GeoLong': long_lat_alt = retdict[hk].split(',') retdict['GeoLong'] = float(long_lat_alt[0]) retdict['GeoLat'] = float(long_lat_alt[1]) retdict['GeoDist'] = float(long_lat_alt[2]) elif hk == 'dMJD': retdict[hk] = qa.convert( qa.totime(retdict[hk].replace('minutes', 'min')), 'd')['value'] elif hk == 'orb_per': unit = 'h' retrograde = False if 'd' in retdict[hk].lower(): unit = 'd' # Actually this is most common. if 'r' in retdict[hk].lower(): retrograde = True value = get_num_from_str(retdict[hk], 'orbital period') if value != False: if retrograde and value > 0.0: value = -value retdict[hk] = {'unit': unit, 'value': value} else: del retdict[hk] # The rotation period might depend on the orbital period ("Synchronous"), # so handle it after all the other headers have been done. if 'rot_per' in retdict: rpstr = retdict['rot_per'] if 'ROTPER' in rpstr: # Asteroid retdict['rot_per'] = { 'unit': 'h', # Always seems to be for asteroids. 'value': get_num_from_str(rpstr, 'rotation period') } elif 'Synchronous' in rpstr: retdict['rot_per'] = retdict['orb_per'] else: # Most likely a planet. match = re.search(r'(\d+)h\s*(\d+)m\s*([0-9.]+)s', rpstr) if match: hms = [float(match.group(i)) for i in range(1, 4)] retdict['rot_per'] = { 'unit': 'h', 'value': hms[0] + (hms[1] + hms[2] / 60.0) / 60.0 } else: # DON'T include the optional r in hr! qa.totime can't handle it. try: match = re.search(r'([-0-9.]+)(?:\s*\+-[0-9.]+)?\s*([dh])', rpstr) if match: retdict['rot_per'] = { 'unit': match.group(2), 'value': float(match.group(1)) } except: print("Error parsing the rotation period from") print(rpstr) if retdict['data'].has_key('ang_sep'): retdict['data']['obs_code'] = {'comment': 'Obscuration code'} for dk in retdict['data']: if dk == 'obs_code': continue if cols[dk].has_key('unit'): retdict['data'][dk]['data'] = { 'unit': cols[dk]['unit'], 'value': scipy.array([float(s) for s in retdict['data'][dk]['data']]) } if dk == 'RadVel': # Convert from km/s to AU/d. Blame MeasComet, not me. retdict['data'][dk]['data']['unit'] = 'AU/d' kmps_to_AUpd = qa.convert('1km/s', 'AU/d')['value'] retdict['data'][dk]['data']['value'] *= kmps_to_AUpd if re.match(r'.*(RA|DEC)$', dk): retdict['data'][dk] = convert_radec(retdict['data'][dk]) elif dk == 'MJD': retdict['data']['MJD'] = datestrs_to_MJDs(retdict['data']['MJD']) elif dk == 'ang_sep': angseps = [] obscodes = [] for asoc in retdict['data'][dk]['data']: angsep, obscode = asoc.split('/') angseps.append(float(angsep)) obscodes.append(obscode) retdict['data'][dk]['data'] = { 'unit': 'arcseconds', 'value': angseps } retdict['data']['obs_code']['data'] = obscodes if len(retdict.get('radii', {'value': []})['value']) == 3 \ and retdict['data'].has_key('NP_RA') and retdict['data'].has_key('NP_DEC'): # Do a better mean radius estimate using the actual theta. retdict['meanrad']['value'] = mean_radius_with_known_theta(retdict) # To be eventually usable as a MeasComet table, a few more keywords are needed. retdict['VS_TYPE'] = 'Table of comet/planetary positions' if version == '': version = '0003.0001' #retdict['VS_VERSION'] = '0003.0001' retdict['VS_VERSION'] = version if retdict.has_key('VS_CREATE'): dt = time.strptime(retdict['VS_CREATE'], "%b %d %H:%M:%S %Y") else: casalog.post( "The ephemeris creation date was not found. Using the current time.", priority="WARN") dt = time.gmtime() retdict['VS_CREATE'] = time.strftime('%Y/%m/%d/%H:%M', dt) # VS_DATE is required by MeasComet, but it doesn't seem to be actually used. retdict['VS_DATE'] = time.strftime('%Y/%m/%d/%H:%M', time.gmtime()) if retdict['data'].has_key('MJD'): #casalog.post("retdict.keys=%s" % retdict.keys()) retdict['MJD0'] = retdict['data']['MJD']['value'][0] - retdict['dMJD'] else: print( "The table will not be usable with me.framecomet because it lacks MJD." ) # adding posrefsys keyword if cols['RA']['comment'].count('J2000'): retdict['posrefsys'] = 'ICRF/J2000.0' if cols['RA']['comment'].count('B1950'): retdict['posrefsys'] = 'FK4/B1950.0' return retdict