casa
$Rev:20696$
|
00001 import os 00002 import sys 00003 from taskinit import * 00004 from get_user import get_user 00005 00006 import asap as sd 00007 from asap import _to_list 00008 from asap.scantable import is_scantable 00009 import pylab as pl 00010 import sdutil 00011 00012 def sdstat(infile, antenna, fluxunit, telescopeparm, specunit, restfreq, frame, doppler, scanlist, field, iflist, pollist, masklist, invertmask, interactive, outfile, format, overwrite): 00013 00014 casalog.origin('sdstat') 00015 00016 ### 00017 ### Now the actual task code 00018 ### 00019 try: 00020 worker = sdstat_worker(**locals()) 00021 worker.initialize() 00022 worker.execute() 00023 worker.finalize() 00024 00025 return worker.statistics 00026 00027 except Exception, instance: 00028 sdutil.process_exception(instance) 00029 raise Exception, instance 00030 00031 class sdstat_worker(sdutil.sdtask_template): 00032 def __init__(self, **kwargs): 00033 super(sdstat_worker,self).__init__(**kwargs) 00034 00035 def __del__(self): 00036 # restore scantable when the instance is deleted 00037 self.cleanup() 00038 00039 def parameter_check(self): 00040 # If outfile is set, sd.rcParams['verbose'] must be True 00041 self.verbose_saved = sd.rcParams['verbose'] 00042 if ( len(self.outfile) > 0 ): 00043 if ( not os.path.exists(sdutil.get_abspath(self.outfile)) \ 00044 or self.overwrite ): 00045 sd.rcParams['verbose']=True 00046 00047 00048 def initialize_scan(self): 00049 #load the data without averaging 00050 sorg = sd.scantable(self.infile,average=False,antenna=self.antenna) 00051 00052 # collect data to restore 00053 self.restorer = sdutil.scantable_restore_factory(sorg, 00054 self.infile, 00055 self.fluxunit, 00056 self.specunit, 00057 self.frame, 00058 self.doppler, 00059 self.restfreq) 00060 00061 # scantable selection 00062 sorg.set_selection(self.get_selector()) 00063 00064 00065 # this is bit tricky 00066 # set fluxunit here instead of self.set_to_scan 00067 # and remove fluxunit attribute to disable additional 00068 # call of set_fluxunit in self.set_to_scan 00069 self.scan = sdutil.set_fluxunit(sorg, self.fluxunit, self.telescopeparm, False) 00070 self.fluxunit_saved = self.fluxunit 00071 del self.fluxunit 00072 00073 if self.scan: 00074 # Restore flux unit in original table before deleting 00075 self.restorer.restore() 00076 del self.restorer 00077 self.restorer = None 00078 else: 00079 self.scan = sorg 00080 00081 def execute(self): 00082 self.set_to_scan() 00083 00084 # restore self.fluxunit 00085 self.fluxunit = self.fluxunit_saved 00086 del self.fluxunit_saved 00087 00088 self.calc_statistics() 00089 00090 def calc_statistics(self): 00091 # Warning for multi-IF data 00092 if len(self.scan.getifnos()) > 1: 00093 casalog.post( 'The scantable contains multiple IF data.', priority='WARN' ) 00094 casalog.post( 'Note the same mask(s) are applied to all IFs based on CHANNELS.', priority='WARN' ) 00095 casalog.post( 'Baseline ranges may be incorrect for all but IF=%d.\n' % (self.scan.getif(0)), priority='WARN' ) 00096 00097 # set mask 00098 self.__set_mask() 00099 00100 # set formatter 00101 self.__set_formatter() 00102 00103 # set unit labels 00104 self.__set_unit_labels() 00105 00106 # calculate statistics 00107 #statsdict = get_stats(s, msk, formstr) 00108 self.__calc_stats() 00109 00110 # reshape statsdict for return 00111 for k in ['min','max']: 00112 self.statistics['%s_abscissa'%(k)] = qa.quantity(self.statistics.pop('%s_abc'%(k)),self.xunit) 00113 for (k,u) in [('eqw',self.xunit),('totint',self.intunit)]: 00114 self.statistics[k] = qa.quantity(self.statistics[k],u) 00115 00116 def save(self): 00117 if ( len(self.outfile) > 0 ): 00118 if ( not os.path.exists(sdutil.get_abspath(self.outfile)) \ 00119 or self.overwrite ): 00120 f=open(self.outfile,'w') 00121 f.write(self.resultstats) 00122 f.close() 00123 else: 00124 casalog.post( 'File '+self.outfile+' already exists.\nStatistics results are not written into the file.', priority = 'WARN' ) 00125 00126 def cleanup(self): 00127 # restore sd.rcParams 00128 sd.rcParams['verbose'] = self.verbose_saved 00129 00130 # restore original scantable 00131 if self.restorer is not None: 00132 self.restorer.restore() 00133 00134 def __calc_stats(self): 00135 usr = get_user() 00136 tmpfile = '/tmp/tmp_'+usr+'_casapy_asap_scantable_stats' 00137 self.resultstats = '' 00138 self.statistics = {} 00139 00140 # calculate regular statistics 00141 statsname = ['max', 'min', 'max_abc', 'min_abc', 00142 'sum', 'mean', 'median', 'rms', 00143 'stddev'] 00144 for name in statsname: 00145 v = self.scan.stats(name,self.msk,self.format_string) 00146 self.statistics[name] = list(v) if len(v) > 1 else v[0] 00147 if sd.rcParams['verbose']: 00148 self.resultstats += get_text_from_file(tmpfile) 00149 00150 # calculate additional statistics (eqw and integrated intensity) 00151 self.__calc_eqw_and_integf() 00152 00153 if sd.rcParams['verbose']: 00154 # Print equivalent width 00155 out = self.__get_statstext('eqw', self.abclbl, 'eqw') 00156 self.resultstats += out 00157 00158 # Print integrated flux 00159 outp = self.__get_statstext('Integrated intensity', self.intlbl, 'totint') 00160 self.resultstats += outp 00161 00162 # to logger 00163 casalog.post(out[:-2]+outp) 00164 00165 def __calc_eqw_and_integf(self): 00166 eqw = None 00167 integratef = None 00168 if isinstance(self.statistics['max'],list): 00169 # User selected multiple scans,ifs 00170 ns = len(self.statistics['max']) 00171 eqw=[] 00172 integratef=[] 00173 for i in range(ns): 00174 #Get bin width 00175 abcissa, lbl = self.scan.get_abcissa(rowno=i) 00176 dabc=abs(abcissa[-1] - abcissa[0])/float(len(abcissa)-1) 00177 # Construct equivalent width (=sum/max) 00178 eqw = eqw + [get_eqw(self.statistics['max'][i], 00179 self.statistics['min'][i], 00180 self.statistics['sum'][i], 00181 dabc)] 00182 # Construct integrated flux 00183 integratef = integratef + [get_integf(self.statistics['sum'][i], dabc)] 00184 else: 00185 # Single scantable only 00186 abcissa, lbl = self.scan.get_abcissa(rowno=0) 00187 dabc=abs(abcissa[-1] - abcissa[0])/float(len(abcissa)-1) 00188 00189 # Construct equivalent width (=sum/max) 00190 eqw = get_eqw(self.statistics['max'], 00191 self.statistics['min'], 00192 self.statistics['sum'], 00193 dabc) 00194 00195 # Construct integrated flux 00196 integratef = get_integf(self.statistics['sum'], dabc) 00197 self.statistics['eqw'] = eqw 00198 self.statistics['totint'] = integratef 00199 00200 def __set_mask(self): 00201 self.msk = None 00202 if self.interactive: 00203 # Interactive masking 00204 self.msk = sdutil.interactive_mask(self.scan, 00205 self.masklist, 00206 False, 00207 purpose='to calculate statistics') 00208 msks = self.scan.get_masklist(self.msk) 00209 if len(msks) < 1: 00210 raise Exception, 'No channel is selected. Exit without calculation.' 00211 lbl=self.scan.get_unit() 00212 casalog.post( 'final mask list ('+lbl+') = '+str(msks) ) 00213 00214 del msks 00215 00216 # set the mask region 00217 elif ( len(self.masklist) > 0): 00218 self.msk=self.scan.create_mask(self.masklist,invert=self.invertmask) 00219 msks=self.scan.get_masklist(self.msk) 00220 if len(msks) < 1: 00221 del self.msk, msks 00222 raise Exception, 'Selected mask lists are out of range. Exit without calculation.' 00223 del msks 00224 else: 00225 # Full region 00226 casalog.post( 'Using full region' ) 00227 00228 def __set_formatter(self): 00229 self.format_string=self.format.replace(' ','') 00230 if len(self.format_string)==0: 00231 casalog.post("Invalid format string. Using the default 3.3f.") 00232 self.format_string='3.3f' 00233 00234 def __set_unit_labels(self): 00235 if self.specunit != '': self.abclbl = self.specunit 00236 else: self.abclbl = self.scan.get_unit() 00237 if self.fluxunit != '': ordlbl = self.fluxunit 00238 else: ordlbl = self.scan.get_fluxunit() 00239 self.intlbl = ordlbl+' * '+self.abclbl 00240 00241 # Check units 00242 if self.abclbl == 'channel' and not qa.check(self.abclbl): 00243 qa.define('channel','1 _') 00244 00245 self.xunit = check_unit(self.abclbl,self.abclbl,'_') 00246 self.intunit = check_unit(ordlbl,ordlbl+'.'+self.abclbl,'_.'+self.abclbl) 00247 00248 def __get_statstext(self, title, label, key): 00249 sep = "--------------------------------------------------" 00250 head = string.join([sep,string.join([" ","%s ["%(title),label,"]"]," "),sep],'\n') 00251 tail = '' 00252 out = head + '\n' 00253 val = self.statistics[key] 00254 if isinstance(val,list): 00255 ns = len(val) 00256 for i in xrange(ns): 00257 out += self.__get_statstr(i, val[i], sep) 00258 else: 00259 out += self.__get_statstr(0, val, sep) 00260 out += '\n%s'%(tail) 00261 return out 00262 00263 def __get_statstr(self, irow, val, separator): 00264 out = '' 00265 out += 'Scan[%d] (%s) ' % (self.scan.getscan(irow), self.scan._getsourcename(irow)) 00266 out += 'Time[%s]:\n' % (self.scan._gettime(irow)) 00267 if self.scan.nbeam(-1) > 1: out += ' Beam[%d] ' % (self.scan.getbeam(irow)) 00268 if self.scan.nif(-1) > 1: out += ' IF[%d] ' % (self.scan.getif(irow)) 00269 if self.scan.npol(-1) > 1: out += ' Pol[%d] ' % (self.scan.getpol(irow)) 00270 out += ('= %'+self.format_string) % (val) + '\n' 00271 out += "%s\n "%(separator) 00272 return out 00273 00274 def check_unit(unit_in,valid_unit=None,default_unit=None): 00275 if qa.check(unit_in): 00276 return valid_unit 00277 else: 00278 casalog.post('Undefined unit: \'%s\'...ignored'%(unit_in), priority='WARN') 00279 return default_unit 00280 00281 def get_eqw(maxl, minl, suml, dabc): 00282 eqw = 0.0 00283 if ( maxl != 0.0 or minl != 0.0 ): 00284 if ( abs(maxl) >= abs(minl) ): 00285 eqw = suml/maxl*dabc 00286 else: 00287 eqw = suml/minl*dabc 00288 return eqw 00289 00290 def get_integf(suml, dabc): 00291 return suml * dabc 00292 00293 def get_text_from_file(filename): 00294 f = open(filename,'r') 00295 rlines = f.readlines() 00296 f.close() 00297 return string.join(rlines,'') 00298