00001 import re
00002 from asap._asap import selector as _selector, srctype
00003 from asap.utils import unique, _to_list
00004
00005 class selector(_selector):
00006 """
00007 A selection object to be applied to scantables to restrict the
00008 scantables to specific rows.
00009 """
00010 fields = ["pols", "ifs", "beams", "scans", "cycles", "name", "query", "types", "rows"]
00011
00012 def __init__(self, *args, **kw):
00013 if len(args) == 1:
00014 if isinstance(args[0], self.__class__) \
00015 or isinstance(args[0], _selector):
00016 _selector.__init__(self, args[0])
00017 else:
00018 raise TypeError("Argument can only be a selector object")
00019 else:
00020 _selector.__init__(self)
00021 for k,v in kw.items():
00022 if k in self.fields:
00023 func = getattr(self, "set_%s" % k)
00024 func(v)
00025
00026 def reset(self):
00027 """
00028 Unset all selections.
00029 """
00030 self._reset()
00031
00032 def is_empty(self):
00033 """
00034 Has anything been set?
00035 """
00036 return self._empty()
00037
00038 def set_polarisations(self, pols=[]):
00039 """
00040 Set the polarisations to be selected in the scantable.
00041 Parameters:
00042 pols: a list of integers of 0-3, or strings, e.g ["I","Q"].
00043 Default [] is no selection
00044 Example:
00045 sel = selector()
00046 # These are equivalent if data is 'linear'
00047 sel.set_polarisations(["XX","Re(XY)"])
00048 sel.set_polarisations([0,2])
00049 # reset the polarisation selection
00050 sel.set_polarisations()
00051
00052 """
00053 vec = _to_list(pols, str) or _to_list(pols, int)
00054 if isinstance(vec, list):
00055 if len(vec) and isinstance(vec[-1],str):
00056 self._setpolstrings(vec)
00057 return
00058 self._setpols(vec)
00059 else:
00060 raise TypeError('Unknown pol type. Please use [0,1...] or ["XX","YY"...]')
00061
00062
00063 set_polarizations = set_polarisations
00064
00065 set_pols = set_polarisations
00066
00067 def set_ifs(self, ifs=[]):
00068 """
00069 Set a sequence of IF numbers (0-based).
00070 Parameters:
00071 ifs: a list of integers. Default [] is to unset the selection.
00072 """
00073 vec = _to_list(ifs, int)
00074 if isinstance(vec,list):
00075 self._setifs(vec)
00076 else:
00077 raise TypeError('Unknown IFno type. Use lists of integers.')
00078
00079 def set_scans(self, scans=[]):
00080 """
00081 Set a sequence of Scan numbers (0-based).
00082 Parameters:
00083 scans: a list of integers. Default [] is to unset the selection.
00084 """
00085 vec = _to_list(scans, int)
00086 if isinstance(vec,list):
00087 self._setscans(vec)
00088 else:
00089 raise TypeError('Unknown Scan number type. Use lists of integers.')
00090
00091 def set_beams(self, beams=[]):
00092 """
00093 Set a sequence of Beam numbers (0-based).
00094 Parameters:
00095 beams: a list of integers. Default [] is to unset the selection.
00096 """
00097 vec = _to_list(beams, int)
00098 if isinstance(vec,list):
00099 self._setbeams(vec)
00100 else:
00101 raise TypeError('Unknown Beam number type. Use lists of integers.')
00102
00103 def set_cycles(self, cycles=[]):
00104 """
00105 Set a sequence of IF numbers (0-based).
00106 Parameters:
00107 cycless: a list of integers. Default [] is to unset the selection.
00108 """
00109 vec = _to_list(cycles, int)
00110 if isinstance(vec,list):
00111 self._setcycles(vec)
00112 else:
00113 raise TypeError('Unknown Cycle number type. Use lists of integers.')
00114
00115
00116 def set_name(self, name):
00117 """
00118 Set a selection based on a name. This can be a unix pattern , e.g. "*_R"
00119 Parameters:
00120 name: a string containing a source name or pattern
00121 Examples:
00122 # select all reference scans which start with "Orion"
00123 selection.set_name("Orion*_R")
00124 """
00125 if isinstance(name, str):
00126 self._setname(name)
00127 else:
00128 raise TypeError('name must be a string')
00129
00130 def set_tsys(self, tsysmin=0.0, tsysmax=None):
00131 """
00132 Select by Tsys range.
00133 Parameters:
00134 tsysmin: the lower threshold. Default 0.0
00135 tsysmax: the upper threshold. Default None.
00136 Examples:
00137 # select all spectra with Tsys <= 500.0
00138 selection.set_tsys(tsysmax=500.0)
00139
00140 """
00141 taql = "SELECT FROM $1 WHERE TSYS[0] >= %f" % (tsysmin)
00142 if isinstance(tsysmax, float):
00143 taql = taql + " AND TSYS[0] <= %f" % ( tsysmax)
00144 self._settaql(taql)
00145
00146 def set_query(self, query):
00147 """
00148 Select by Column query. Power users only!
00149 Example:
00150 # select all off scans with integration times over 60 seconds.
00151 selection.set_query("SRCTYPE == PSOFF AND INTERVAL > 60.0")
00152 """
00153 rx = re.compile("((SRCTYPE *[!=][=] *)([a-zA-Z.]+))", re.I)
00154 for r in rx.findall(query):
00155 sval = None
00156 stype = r[-1].lower()
00157 if stype.find('srctype.') == -1:
00158 stype = ".".join(["srctype", stype])
00159 try:
00160 sval = eval(stype)
00161 sval = "%s%d" % (r[1], sval)
00162 except:
00163 continue
00164 query = query.replace(r[0], sval)
00165 taql = "SELECT FROM $1 WHERE " + query
00166 self._settaql(taql)
00167
00168 def set_order(self, order):
00169 """
00170 Set the order the scantable should be sorted by.
00171 Parameters:
00172 order: The list of column names to sort by in order
00173 """
00174 self._setorder(order)
00175
00176 def set_rows(self, rows=[]):
00177 """
00178 Set a sequence of row numbers (0-based). Power users Only!
00179 NOTICE row numbers can be changed easily by sorting,
00180 prior selection, etc.
00181 Parameters:
00182 rows: a list of integers. Default [] is to unset the selection.
00183 """
00184 vec = _to_list(rows, int)
00185 if isinstance(vec,list):
00186 self._setrows(vec)
00187 else:
00188 raise TypeError('Unknown row number type. Use lists of integers.')
00189
00190 def set_types(self, types=[]):
00191 """
00192 Set a sequence of source types.
00193 Parameters:
00194 types: a list of integers. Default [] is to unset the selection.
00195 """
00196 vec = _to_list(types, int)
00197 if isinstance(vec,list):
00198 self._settypes(vec)
00199 else:
00200 raise TypeError('Unknown row number type. Use lists of integers.')
00201
00202 def get_scans(self):
00203 return list(self._getscans())
00204 def get_cycles(self):
00205 return list(self._getcycles())
00206 def get_beams(self):
00207 return list(self._getbeams())
00208 def get_ifs(self):
00209 return list(self._getifs())
00210 def get_pols(self):
00211 return list(self._getpols())
00212 def get_poltypes(self):
00213 return list(self._getpoltypes())
00214 def get_order(self):
00215 return list(self._getorder())
00216 def get_types(self):
00217 return list(self._gettypes())
00218 def get_rows(self):
00219 return list(self._getrows())
00220 def get_query(self):
00221 prefix = "SELECT FROM $1 WHERE "
00222 return self._gettaql().replace(prefix, "")
00223
00224 def get_name(self):
00225 print "NYI"
00226 s = self._gettaql()
00227 return
00228 def __str__(self):
00229 out = ""
00230 d = {"SCANNO": self.get_scans(),
00231 "CYCLENO": self.get_cycles(),
00232 "BEAMNO": self.get_beams(),
00233 "IFNO": self.get_ifs(),
00234 "Pol Type": self.get_poltypes(),
00235 "POLNO": self.get_pols(),
00236 "QUERY": self.get_query(),
00237 "SRCTYPE": self.get_types(),
00238 "ROWS": self.get_rows(),
00239 "Sort Order": self.get_order()
00240 }
00241 for k,v in d.iteritems():
00242 if v:
00243 out += "%s: %s\n" % (k, v)
00244 if len(out):
00245 return out[:-1]
00246 else:
00247 return out
00248
00249 def __add__(self, other):
00250 """
00251 Merge two selections.
00252 """
00253 if self.is_empty():
00254 return selector(other)
00255 elif other.is_empty():
00256 return selector(self)
00257 union = selector()
00258 gets = [[self._getscans(), other._getscans(), union._setscans],
00259 [self._getcycles(), other._getcycles(),union._setcycles],
00260 [self._getbeams(), other._getbeams(), union._setbeams],
00261 [self._getifs(), other._getifs(), union._setifs],
00262 [self._getpols(), other._getpols(), union._setpols]]
00263 for v in gets:
00264 vec = list(v[0]+v[1])
00265 vec.sort()
00266 v[2](unique(vec))
00267 q = other.get_query()
00268 qs = self.get_query()
00269 if len(q) and len(qs):
00270 union.set_query(qs +" AND " + q)
00271 else:
00272 if len(q):
00273 union.set_query(q)
00274 elif len(qs):
00275 union.set_query(qs)
00276 return union