Package Wizardry :: Module AIPSData
[hide private]
[frames] | no frames]

Source Code for Module Wizardry.AIPSData

   1  # Copyright (C) 2005, 2006 Joint Institute for VLBI in Europe 
   2  # 
   3  # This program is free software; you can redistribute it and/or modify 
   4  # it under the terms of the GNU General Public License as published by 
   5  # the Free Software Foundation; either version 2 of the License, or 
   6  # (at your option) any later version. 
   7  # 
   8  # This program is distributed in the hope that it will be useful, 
   9  # but WITHOUT ANY WARRANTY; without even the implied warranty of 
  10  # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
  11  # GNU General Public License for more details. 
  12   
  13  # You should have received a copy of the GNU General Public License 
  14  # along with this program; if not, write to the Free Software 
  15  # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
  16   
  17  # Obit stuff. 
  18  import Obit 
  19  import OErr, OSystem 
  20  import AIPSDir, History, Image, UV, InfoList, Table, TableList 
  21   
  22  # Global AIPS defaults. 
  23  import AIPS 
  24   
  25  # Fail gracefully if numarray isn't available. 
  26  try: 
  27      import numarray 
  28  except: 
  29      numarray = None 
  30      pass 
  31   
  32   
33 -def _scalarize(value):
34 """Scalarize a value. 35 36 If VALUE is a list that consists of a single element, return that 37 element. Otherwise return VALUE.""" 38 39 if type(value) == list and len(value) == 1: 40 return value[0] 41 return value
42 43
44 -def _vectorize(value):
45 """Vectorize a value. 46 47 If VALUE is a scalar, return a list consisting of that scalar. 48 Otherwise return VALUE.""" 49 50 if type(value) != list: 51 return [value] 52 return value
53 54
55 -def _rstrip(value):
56 """Strip trailing whitespace.""" 57 58 if type(value) == list: 59 return [str.rstrip() for str in value] 60 return value.rstrip()
61 62
63 -class _AIPSTableRow:
64 """This class is used to access rows in an extension table.""" 65
66 - def __init__(self, table, fields, rownum, err):
67 self._err = err 68 self._table = table 69 self._fields = fields 70 self._rownum = rownum 71 if self._rownum >= 0: 72 assert(not self._err.isErr) 73 self._row = self._table.ReadRow(self._rownum + 1, self._err) 74 if not self._row: 75 raise IndexError, "list index out of range" 76 if self._err.isErr: 77 raise RuntimeError 78 pass 79 return
80
81 - def __str__(self):
82 return str(self._generate_dict())
83
84 - def _generate_dict(self):
85 dict = {} 86 for name in self._fields: 87 if name.startswith('_'): 88 continue 89 dict[name] = getattr(self, name) 90 pass 91 return dict
92
93 - def _findattr(self, name):
94 """Return the field name corresponding to attribute NAME.""" 95 96 if name in self._fields: 97 return self._fields[name] 98 msg = "%s instance has no attribute '%s'" % \ 99 (self.__class__.__name__, name) 100 raise AttributeError, msg
101
102 - def __getattr__(self, name):
103 key = self._findattr(name) 104 return _scalarize(self._row[key])
105
106 - def __setattr__(self, name, value):
107 if name.startswith('_'): 108 self.__dict__[name] = value 109 return 110 key = self._findattr(name) 111 self._row[key] = _vectorize(value) 112 pass
113
114 - def __getitem__(self, name):
115 return self.__getattr__(name)
116
117 - def __setitem__(self, name, value):
118 self.__setattr__(name, value) 119 return
120
121 - def update(self):
122 """Update this row.""" 123 124 assert(not self._err.isErr) 125 self._table.WriteRow(self._rownum + 1, self._row, self._err) 126 if self._err.isErr: 127 raise RuntimeError 128 return
129 130 pass # class _AIPSTableRow
131 132
133 -class AIPSTableRow(_AIPSTableRow):
134 """This class is used as a template row for an extension table.""" 135
136 - def __init__(self, table):
137 _AIPSTableRow.__init__(self, table._table, table._columns, 138 -1, table._err) 139 header = table._table.Desc.Dict 140 self._row = {} 141 self._row['Table name'] = header['Table name'] 142 self._row['NumFields'] = len(header['FieldName']) 143 desc = zip(header['FieldName'], header['type'], header['repeat']) 144 for field, type, repeat in desc: 145 if type == 2 or type == 3: 146 # Integer. 147 self._row[field] = repeat * [0] 148 elif type == 9 or type == 10: 149 # Floating-point number. 150 self._row[field] = repeat * [0.0] 151 elif type == 13: 152 # String. 153 self._row[field] = '' 154 elif type == 14: 155 # Boolean. 156 self._row[field] = repeat * [False] 157 else: 158 msg = "Unimplemented type %d for field %s" % (type, field) 159 raise AssertionError, msg 160 continue 161 return
162
163 - def update(self):
164 # A row instantiated by the AIPSTableRow class cannot be updated. 165 msg = "%s instance has no attribute 'update'" % \ 166 self.__class__.__name__ 167 raise AttributeError, msg
168 169 pass # AIPSTableRow
170 171
172 -class _AIPSTableIter(_AIPSTableRow):
173 """This class is used as an iterator over rows in an extension 174 table.""" 175
176 - def __init__(self, table, fields, err):
177 _AIPSTableRow.__init__(self, table, fields, -1, err)
178
179 - def next(self):
180 """Return the next row.""" 181 182 self._rownum += 1 183 assert(not self._err.isErr) 184 self._row = self._table.ReadRow(self._rownum + 1, self._err) 185 if not self._row: 186 self._err.Clear() 187 raise StopIteration 188 assert(not self._err.isErr) 189 return self
190 191 pass # class _AIPSTableIter
192 193
194 -class _AIPSTableKeywords:
195 - def __init__(self, table, err):
196 self._err = err 197 self._table = table 198 return
199
200 - def __getitem__(self, key):
201 key = key.upper().ljust(8) 202 value = InfoList.PGet(self._table.IODesc.List, key) 203 return _scalarize(value[4])
204
205 - def __setitem__(self, key, value):
206 key = key.upper().ljust(8) 207 try: 208 _type = InfoList.PGet(self._table.IODesc.List, key)[2] 209 except: 210 # New keys are either strings or floats. 211 if type(value) == str: 212 _type = 13 213 else: 214 _type = 9 215 pass 216 pass 217 if _type in (2, 3, 4): 218 value = int(value) 219 InfoList.PAlwaysPutInt(self._table.Desc.List, key, 220 [1, 1, 1, 1, 1], _vectorize(value)) 221 InfoList.PAlwaysPutInt(self._table.IODesc.List, key, 222 [1, 1, 1, 1, 1], _vectorize(value)) 223 elif _type == 9: 224 value = float(value) 225 InfoList.PAlwaysPutFloat(self._table.Desc.List, key, 226 [1, 1, 1, 1, 1], _vectorize(value)) 227 InfoList.PAlwaysPutFloat(self._table.IODesc.List, key, 228 [1, 1, 1, 1, 1], _vectorize(value)) 229 elif _type == 10: 230 value = float(value) 231 InfoList.PAlwaysPutDouble(self._table.Desc.List, key, 232 [1, 1, 1, 1, 1], _vectorize(value)) 233 InfoList.PAlwaysPutDouble(self._table.IODesc.List, key, 234 [1, 1, 1, 1, 1], _vectorize(value)) 235 elif _type == 13: 236 value = str(value).ljust(8) 237 InfoList.PAlwaysPutString(self._table.Desc.List, key, 238 [8, 1, 1, 1, 1], _vectorize(value)) 239 InfoList.PAlwaysPutString(self._table.IODesc.List, key, 240 [8, 1, 1, 1, 1], _vectorize(value)) 241 elif _type == 14: 242 value = bool(value) 243 InfoList.PAlwaysPutBoolean(self._table.Desc.List, key, 244 [1, 1, 1, 1, 1], _vectorize(value)) 245 InfoList.PAlwaysPutBoolean(self._table.IODesc.List, key, 246 [1, 1, 1, 1, 1], _vectorize(value)) 247 else: 248 raise AssertionError, "not implemented" 249 Table.PDirty(self._table) 250 return
251
252 - def _generate_dict(self):
253 dict = {} 254 for key in self._table.IODesc.List.Dict: 255 if self._table.IODesc.List.Dict[key][0] == 13: 256 dict[key] = self._table.IODesc.List.Dict[key][2][0] 257 else: 258 dict[key] = _scalarize(self._table.IODesc.List.Dict[key][2]) 259 pass 260 continue 261 return dict
262
263 - def __str__(self):
264 return str(self._generate_dict())
265 266 pass # class _AIPSTableKeywords
267 268
269 -class _AIPSTable:
270 """This class is used to access extension tables to an AIPS UV 271 data set.""" 272
273 - def __init__(self, data, name, version):
274 if not name.startswith('AIPS '): 275 name = 'AIPS ' + name 276 pass 277 278 self._err = OErr.OErr() 279 280 if version == 0: 281 version = TableList.PGetHigh(data.TableList, name) 282 283 tables = TableList.PGetList(data.TableList, self._err) 284 if not [version, name] in tables: 285 msg = name + ' table' 286 if version: 287 msg += ' version %d' % version 288 pass 289 msg += ' does not exist' 290 raise IOError, msg 291 292 self._table = data.NewTable(3, name, version, self._err) 293 self._table.Open(3, self._err) 294 if self._err.isErr: 295 raise self._err 296 header = self._table.Desc.Dict 297 self._columns = {} 298 self._keys = [] 299 for column in header['FieldName']: 300 # Convert the AIPS ccolumn names into acceptable Python 301 # identifiers. 302 key = column.lower() 303 key = key.replace(' ', '_') 304 key = key.rstrip('.') 305 key = key.replace('.', '_') 306 self._columns[key] = column 307 self._keys.append(key) 308 continue 309 self.name = name 310 self.version = header['version'] 311 return
312
313 - def close(self):
314 """Close this extension table. 315 316 Closing an extension table flushes any changes to the table to 317 disk and updates the information in the header of the data 318 set.""" 319 320 assert(not self._err.isErr) 321 self._table.Close(self._err) 322 if self._err.isErr: 323 raise RuntimeError 324 return
325 326 # The following functions make an extension table behave as a list 327 # of rows. 328
329 - def __getitem__(self, key):
330 if key < 0: 331 key = len(self) - key 332 return _AIPSTableRow(self._table, self._columns, key, self._err)
333
334 - def __iter__(self):
335 return _AIPSTableIter(self._table, self._columns, self._err)
336
337 - def __len__(self):
338 return self._table.Desc.Dict['nrow']
339
340 - def __setitem__(self, key, row):
341 if key < 0: 342 key = len(self) - key 343 assert(not self._err.isErr) 344 self._table.WriteRow(key + 1, row._row, self._err) 345 if self._err.isErr: 346 raise RuntimeError 347 return
348
349 - def append(self, row):
350 """Append a row to this extension table.""" 351 352 assert(not self._err.isErr) 353 self._table.WriteRow(len(self) + 1, row._row, self._err) 354 if self._err.isErr: 355 raise RuntimeError 356 return
357
358 - def _keywords(self):
359 return _AIPSTableKeywords(self._table, self._err)
360 keywords = property(_keywords) 361 362 pass # class _AIPSTable
363 364
365 -class _AIPSHistory:
366 """This class is used to access AIPS history tables.""" 367
368 - def __init__(self, data):
369 self._err = OErr.OErr() 370 self._table = History.History('AIPS HI', data.List, self._err) 371 self._table.Open(3, self._err) 372 if self._err.isErr: 373 raise RuntimeError 374 return
375
376 - def close(self):
377 """Close this history table. 378 379 Closing a history table flushes any changes to the table to 380 disk and updates the information in the header of the data 381 set.""" 382 self._table.Close(self._err) 383 if self._err.isErr: 384 raise RuntimeError 385 return
386 387 # The following functions make an extension table behave as a list 388 # of records. 389
390 - def __getitem__(self, key):
391 assert(not self._err.isErr) 392 record = self._table.ReadRec(key + 1, self._err) 393 if not record: 394 raise IndexError, "list index out of range" 395 if self._err.isErr: 396 raise RuntimeError 397 return record
398
399 - def __setitem__(self, key, record):
400 msg = 'You are not allowed to rewrite history!' 401 raise NotImplementedError, msg
402
403 - def append(self, record):
404 """Append a record to this history table.""" 405 406 assert(not self._err.isErr) 407 self._table.WriteRec(0, record, self._err) 408 if self._err.isErr: 409 raise RuntimeError 410 return
411 412 pass # class _AIPSHistory
413 414
415 -class _AIPSVisibilityIter(object):
416 """This class is used as an iterator over visibilities.""" 417
418 - def __init__(self, data, err):
419 # Give an early warning we're not going to succeed. 420 if not numarray: 421 msg = 'Numerical Python (numarray) not available' 422 raise NotImplementedError, msg 423 424 self._err = err 425 self._data = data 426 self._index = -1 427 self._desc = self._data.Desc.Dict 428 self._len = self._desc['nvis'] 429 self._first = 0 430 self._count = 0 431 self._dirty = False 432 self._flush = False 433 return
434
435 - def __len__(self):
436 return self._len
437
438 - def next(self):
439 self._index += 1 440 if self._index + self._first >= self._len: 441 if self._flush and self._dirty: 442 Obit.UVWrite(self._data.me, self._err.me) 443 if self._err.isErr: 444 raise RuntimeError 445 self._flush = False 446 self._dirty = False 447 raise StopIteration 448 if self._index >= self._count: 449 self._fill() 450 return self
451
452 - def _fill(self):
453 if self._flush and self._dirty: 454 assert(self._first == self._data.Desc.Dict['firstVis'] - 1) 455 Obit.UVRewrite(self._data.me, self._err.me) 456 if self._err.isErr: 457 raise RuntimeError 458 self._flush = False 459 self._dirty = False 460 pass 461 Obit.UVRead(self._data.me, self._err.me) 462 if self._err.isErr: 463 raise RuntimeError 464 shape = len(self._data.VisBuf) / 4 465 self._buffer = numarray.array(sequence=self._data.VisBuf, 466 type=numarray.Float32, shape=shape) 467 self._first = self._data.Desc.Dict['firstVis'] - 1 468 self._count = self._data.Desc.Dict['numVisBuff'] 469 count = InfoList.PGet(self._data.List, "nVisPIO")[4][0] 470 self._buffer.setshape((count, -1)) 471 self._index = 0 472 return
473
474 - def update(self):
475 self._flush = True 476 return
477
478 - def _get_uvw(self):
479 u = self._buffer[self._index][self._desc['ilocu']] 480 v = self._buffer[self._index][self._desc['ilocv']] 481 w = self._buffer[self._index][self._desc['ilocw']] 482 return [u, v, w]
483 - def _set_uvw(self, value):
484 self._buffer[self._index][self._desc['ilocu']] = value[0] 485 self._buffer[self._index][self._desc['ilocv']] = value[1] 486 self._buffer[self._index][self._desc['ilocw']] = value[2] 487 self._dirty = True
488 uvw = property(_get_uvw, _set_uvw) 489
490 - def _get_time(self):
491 return self._buffer[self._index][self._desc['iloct']]
492 - def _set_time(self, value):
493 self._buffer[self._index][self._desc['iloct']] = value 494 self._dirty = True
495 time = property(_get_time, _set_time) 496
497 - def _get_baseline(self):
498 baseline = int(self._buffer[self._index][self._desc['ilocb']]) 499 return [baseline / 256, baseline % 256]
500 - def _set_baseline(self, value):
501 baseline = value[0] * 256 + value[1] 502 self._buffer[self._index][self._desc['ilocb']] = baseline 503 self._dirty = True
504 baseline = property(_get_baseline, _set_baseline) 505
506 - def _get_source(self):
507 return self._buffer[self._index][self._desc['ilocsu']]
508 - def _set_source(self, value):
509 self._buffer[self._index][self._desc['ilocsu']] = value 510 self._dirty = True
511 source = property(_get_source, _set_source) 512
513 - def _get_freqsel(self):
514 return self._buffer[self._index][self._desc['ilocfq']]
515 - def _set_freqsel(self, value):
516 self._buffer[self._index][self._desc['ilocfq']] = value 517 self._dirty = True
518 freqsel = property(_get_freqsel, _set_freqsel) 519
520 - def _get_inttim(self):
521 return self._buffer[self._index][self._desc['ilocit']]
522 - def _set_inttim(self, value):
523 self._buffer[self._index][self._desc['ilocit']] = value 524 self._dirty = True
525 inttim = property(_get_inttim, _set_inttim) 526
527 - def _get_weight(self):
528 return self._buffer[self._index][self._desc['ilocw']]
529 - def _set_weight(self, value):
530 self._buffer[self._index][self._desc['ilocw']] = value 531 self._dirty = True
532 weight = property(_get_weight, _set_weight) 533
534 - def _get_visibility(self):
535 visibility = self._buffer[self._index][self._desc['nrparm']:] 536 inaxes = self._desc['inaxes'] 537 shape = (inaxes[3], inaxes[2], inaxes[1], inaxes[0]) 538 visibility.setshape(shape) 539 return visibility
540 visibility = property(_get_visibility) 541 542 pass # class _AIPSVisibilityIter
543 544
545 -class _AIPSDataKeywords:
546 - def __init__(self, data, obit, err):
547 self._err = err 548 self._data = data 549 self._obit = obit 550 return
551
552 - def __getitem__(self, key):
553 key = key.upper().ljust(8) 554 value = InfoList.PGet(self._data.Desc.List, key) 555 return _scalarize(value[4])
556
557 - def __setitem__(self, key, value):
558 key = key.upper().ljust(8) 559 try: 560 _type = InfoList.PGet(self._data.Desc.List, key)[2] 561 except: 562 # New keys are either strings or floats. 563 if type(value) == str: 564 _type = 13 565 else: 566 _type = 9 567 pass 568 pass 569 if _type in (2, 3, 4): 570 value = int(value) 571 InfoList.PAlwaysPutInt(self._data.Desc.List, key, 572 [1, 1, 1, 1, 1], _vectorize(value)) 573 elif _type == 9: 574 value = float(value) 575 InfoList.PAlwaysPutFloat(self._data.Desc.List, key, 576 [1, 1, 1, 1, 1], _vectorize(value)) 577 elif _type == 10: 578 value = float(value) 579 InfoList.PAlwaysPutDouble(self._data.Desc.List, key, 580 [1, 1, 1, 1, 1], _vectorize(value)) 581 elif _type == 13: 582 value = str(value).ljust(8) 583 InfoList.PAlwaysPutString(self._data.Desc.List, key, 584 [8, 1, 1, 1, 1], _vectorize(value)) 585 elif _type == 14: 586 value = bool(value) 587 InfoList.PAlwaysPutBoolean(self._table.Desc.List, key, 588 [1, 1, 1, 1, 1], _vectorize(value)) 589 else: 590 raise AssertionError, "not implemented" 591 self._obit.PDirty(self._data) 592 return
593
594 - def _generate_dict(self):
595 dict = {} 596 for key in self._data.Desc.List.Dict: 597 if self._data.Desc.List.Dict[key][0] == 13: 598 dict[key] = self._data.Desc.List.Dict[key][2][0] 599 else: 600 dict[key] = _scalarize(self._data.Desc.List.Dict[key][2]) 601 pass 602 continue 603 return dict
604
605 - def __str__(self):
606 return str(self._generate_dict())
607
608 - def update(self):
609 self._obit.PUpdateDesc(self._data, self._err) 610 pass
611 612 pass # class _AIPSDataKeywords
613 614
615 -class _AIPSDataHeader(object):
616 - def __init__(self, data, obit, err):
617 self._err = err 618 self._data = data 619 self._obit = obit 620 self._dict = data.Desc.Dict 621 for key in self._strip: 622 if self._keys[key] in self._dict: 623 value = _rstrip(self._dict[self._keys[key]]) 624 self._dict[self._keys[key]] = value 625 pass 626 continue 627 return
628 629 _keys = {'object': 'object', 630 'telescop': 'teles', 631 'instrume': 'instrume', 632 'observer': 'observer', 633 'date_obs': 'obsdat', 634 'date_map': 'date', 635 'bunit': 'bunit', 636 'ndim': 'naxis', 637 'naxis': 'inaxes', 638 'epoch': 'equinox', 639 'ctype': 'ctype', 640 'crval': 'crval', 641 'cdelt': 'cdelt', 642 'crpix': 'crpix', 643 'crota': 'crota', 644 # Images 645 'niter': 'niter', 646 'datamin': 'minval', 647 'datamax': 'maxval', 648 'bmaj': 'beamMaj', 649 'bmin': 'beamMin', 650 'bpa': 'beamPA', 651 # UV Data sets 652 'sortord': 'isort', 653 'nrparm': 'nrparm', 654 'ptype': 'ptype', 655 'ncorr': 'ncorr'} 656 _strip = ('object', 'telescop', 'instrume', 'observer', 'bunit', 657 'ptype', 'ctype') 658
659 - def __getitem__(self, key):
660 if not key in self._keys: 661 raise KeyError, key 662 return self._dict[self._keys[key]]
663
664 - def __setitem__(self, key, value):
665 if not key in self._keys: 666 raise KeyError, key 667 self._dict[self._keys[key]] = value 668 return
669
670 - def __getattr__(self, name):
671 if name.startswith('_'): 672 return self.__dict__[name] 673 try: 674 value = self.__getitem__(name) 675 except KeyError: 676 msg = "%s instance has no attribute '%s'" \ 677 % (self.__class__.__name__, name) 678 raise AttributeError, msg 679 return value
680
681 - def __setattr__(self, name, value):
682 if name.startswith('_'): 683 self.__dict__[name] = value 684 return 685 try: 686 self.__setitem__(name, value) 687 except KeyError: 688 msg = "%s instance has no attribute '%s'" \ 689 % (self.__class__.__name__, name) 690 raise AttributeError, msg 691 return
692
693 - def _generate_dict(self):
694 dict = {} 695 for key in self._keys: 696 if self._keys[key] in self._dict: 697 dict[key] = self._dict[self._keys[key]] 698 pass 699 continue 700 return dict
701
702 - def __str__(self):
703 return str(self._generate_dict())
704
705 - def update(self):
706 self._data.Desc.Dict = self._dict 707 self._obit.PUpdateDesc(self._data, self._err) 708 pass
709 710 pass # class _AIPSDataHeader
711 712
713 -class _AIPSData(object):
714 """This class is used to access generic AIPS data.""" 715
716 - def __init__(self, *args):
717 # Instances can be created by specifying name, class, disk, 718 # sequency number and (optionally) user number explicitly, or 719 # by passing an object that has the appropriate attributes. 720 # This allows the creation of a Wizardry object from its 721 # non-Wizardry counterpart. 722 723 if len(args) not in [1, 4, 5]: 724 msg = "__init__() takes 2, 5 or 6 arguments (%d given)" \ 725 % (len(args) + 1) 726 raise TypeError, msg 727 728 if len(args) == 1: 729 self._init(args[0].name, args[0].klass, 730 args[0].disk, args[0].seq, args[0].userno) 731 else: 732 userno = -1 733 if len(args) == 5: 734 userno = args[4] 735 pass 736 self._init(args[0], args[1], args[2], args[3], userno) 737 pass 738 return
739 740 _header = None
741 - def _generate_header(self):
742 if not self._header: 743 self._header = _AIPSDataHeader(self._data, self._obit, self._err) 744 pass 745 return self._header
746 header = property(_generate_header, 747 doc = 'Header for this data set.') 748 749 _keywords = None
750 - def _generate_keywords(self):
751 if not self._keywords: 752 self._keywords = _AIPSDataKeywords(self._data, self._obit, 753 self._err) 754 pass 755 return self._keywords
756 keywords = property(_generate_keywords, 757 doc = 'Keywords for this data set.') 758
759 - def _generate_tables(self):
760 # Reopen the file to make sure the list of tables is updated. 761 self._data.Open(3, self._err) 762 return TableList.PGetList(self._data.TableList, self._err)
763 tables = property(_generate_tables, 764 doc = 'Tables attached to this data set.') 765
766 - def _generate_stokes(self):
767 """Generate the 'stokes' attribute.""" 768 769 stokes_dict = {1: 'I', 2: 'Q', 3: 'U', 4: 'V', 770 -1: 'RR', -2: 'LL', -3: 'RL', -4: 'LR', 771 -5: 'XX', -6: 'YY', -7: 'XY', -8: 'YX'} 772 773 stokes = [] 774 header = self._data.Desc.Dict 775 jlocs = header['jlocs'] 776 cval = header['crval'][jlocs] 777 for i in xrange(header['inaxes'][jlocs]): 778 stokes.append(stokes_dict[int(cval)]) 779 cval += header['cdelt'][jlocs] 780 continue 781 return stokes
782 stokes = property(_generate_stokes, 783 doc='Stokes parameters for this data set.') 784
785 - def _generate_name(self):
786 return self._data.Aname
787 name = property(_generate_name) 788
789 - def _generate_klass(self):
790 return self._data.Aclass
791 klass = property(_generate_klass) 792
793 - def _generate_disk(self):
794 return self._data.Disk
795 disk = property(_generate_disk) 796
797 - def _generate_seq(self):
798 return self._data.Aseq
799 seq = property(_generate_seq) 800
801 - def _generate_userno(self):
802 return self._userno
803 userno = property(_generate_userno) 804
805 - def rename(self, name=None, klass=None, seq=None):
806 """Rename this image or data set. 807 808 NAME is the new name, KLASS is the new class and SEQ is the 809 new sequence number for the data set. Note that you can't 810 change the disk number, since that would require copying the 811 data.""" 812 813 if name == None: name = self._data.Aname 814 if klass == None: klass = self._data.Aclass 815 if seq == None: seq = self._data.Aseq 816 817 self._obit.PRename(self._data, self._err, newAIPSName=name.ljust(12), 818 newAIPSClass=klass.ljust(6), newAIPSSeq=seq) 819 820 # If SEQ was zero, we need to check out the assigned sequence 821 # number. We do this based on the catalog number, so there is 822 # a chance it'll fail if somebody does a RECAT. 823 if seq == 0: 824 cno = self._data.Acno 825 entry = AIPSDir.PInfo(self.disk, self.userno, cno, self._err) 826 if name == entry[0:12].strip() and klass == entry[13:19].strip(): 827 seq = int(entry[20:25]) 828 pass 829 pass 830 831 return (name, klass, seq)
832
833 - def table_highver(self, name):
834 """Return the latest version of the extension table NAME.""" 835 836 if not name.startswith('AIPS '): 837 name = 'AIPS ' + name 838 pass 839 840 return TableList.PGetHigh(self._data.TableList, name)
841
842 - def table(self, name, version):
843 """Access an extension table attached to this UV data set. 844 845 Returns version VERSION of the extension table NAME. If 846 VERSION is 0, this returns the highest available version of 847 the requested extension table.""" 848 849 return _AIPSTable(self._data, name, version)
850
851 - def zap_table(self, name, version):
852 """Remove an extension table from this UV data set.""" 853 854 if not name.startswith('AIPS '): 855 name = 'AIPS ' + name 856 857 assert(not self._err.isErr) 858 try: 859 self._data.ZapTable(name, version, self._err) 860 self._data.UpdateTables(self._err) 861 except OErr.OErr, err: 862 print err 863 msg = "Cannot zap %s table version %d", (name, version) 864 raise RuntimeError, msg 865 return
866
867 - def zap(self, force=False):
868 """Removes the data object from the AIPS catalogue.""" 869 if force: 870 self.clrstat() 871 pass 872 self._data.Zap(self._err) 873 return
874
875 - def clrstat(self):
876 """Reset file 'busy' status in the AIPS catalogue.""" 877 cno = Obit.AIPSDirFindCNO(self._data.Disk, self._userno, 878 self._data.Aname, self._data.Aclass, 879 self._type, self._data.Aseq, 880 self._err.me) 881 Obit.AIPSDirStatus(self._data.Disk, self._userno, cno, 4, self._err.me) 882 return
883
884 - def update(self):
885 """Synchronise the data object with the AIPS catalogue entry.""" 886 self._obit.PUpdateDesc(self._data, self._err) 887 return
888 889 pass # class _AIPSData
890 891
892 -class AIPSImage(_AIPSData):
893 """This class is used to access an AIPS image.""" 894
895 - def _init(self, name, klass, disk, seq, userno):
896 self._obit = Image 897 self._type = 'MA' 898 if userno == -1: 899 userno = AIPS.userno 900 pass 901 self._userno = userno 902 self._err = OErr.OErr() 903 self._dirty = False 904 self._squeezed = False 905 OSystem.PSetAIPSuser(userno) 906 self._data = Image.newPAImage(name, name, klass, disk, seq, 907 True, self._err) 908 if self._err.isErr: 909 raise RuntimeError 910 return
911
912 - def _pixels(self):
913 Obit.ImageRead(self._data.me, self._err.me) 914 if self._err.isErr: 915 raise RuntimeError, "Reading image pixels" 916 shape = [] 917 for len in self.header['naxis']: 918 if self._squeezed and len == 1: 919 continue 920 shape.insert(0, len) 921 continue 922 shape = tuple(shape) 923 pixels = numarray.array(sequence=self._data.PixBuf, 924 type=numarray.Float32, shape=shape) 925 self._dirty = True 926 return pixels
927 pixels = property(_pixels) 928
929 - def squeeze(self):
930 """Remove degenerate dimensions from image.""" 931 932 self._squeezed = True 933 return
934 935
936 - def attach_table(self, name, version, **kwds):
937 """Attach an extension table to this image. 938 939 A new extension table is created if the extension table NAME 940 with version VERSION doesn't exist. If VERSION is 0, a new 941 extension table is created with a version that is one higher 942 than the highest available version.""" 943 944 if not name.startswith('AIPS '): 945 name = 'AIPS ' + name 946 947 if version == 0: 948 version = Obit.ImageGetHighVer(self._data.me, name) + 1 949 950 no_parms = 0 951 if 'no_parms' in kwds: 952 no_parms = kwds['no_parms'] 953 data = Obit.ImageCastData(self._data.me) 954 if name == 'AIPS CC': 955 Obit.TableCC(data, [version], 3, name, no_parms, self._err.me) 956 elif name == 'AIPS PS': 957 Obit.TablePS(data, [version], 3, name, self._err.me) 958 elif name == 'AIPS SN': 959 Obit.TableSN(data, [version], 3, name, 960 kwds['no_pol'], kwds['no_if'], self._err.me) 961 else: 962 msg = 'Attaching %s tables is not implemented yet' % name 963 raise NotImplementedError, msg 964 if self._err.isErr: 965 raise RuntimeError 966 return _AIPSTable(self._data, name, version)
967 968 history = property(lambda self: _AIPSHistory(self._data)) 969
970 - def update(self):
971 if self._dirty: 972 Obit.ImageWrite(self._data.me, self._err.me) 973 if self._err.isErr: 974 raise RuntimeError, "Writing image pixels" 975 pass 976 _AIPSData.update(self)
977 978 pass # class AIPSImage
979 980
981 -class AIPSUVData(_AIPSData):
982 """This class is used to access an AIPS UV data set.""" 983
984 - def _init(self, name, klass, disk, seq, userno):
985 self._obit = UV 986 self._type = 'UV' 987 if userno == -1: 988 userno = AIPS.userno 989 self._userno = userno 990 self._err = OErr.OErr() 991 OSystem.PSetAIPSuser(userno) 992 self._data = UV.newPAUV(name, name, klass, disk, seq, True, self._err) 993 if self._err.isErr: 994 raise RuntimeError 995 self._antennas = [] 996 self._polarizations = [] 997 self._sources = [] 998 return
999
1000 - def __len__(self):
1001 return self._data.Desc.Dict['nvis']
1002
1003 - def __getitem__(self, name):
1004 msg = 'Random visibility access is not possible.' 1005 raise NotImplementedError, msg
1006
1007 - def __iter__(self):
1008 self._data.Open(3, self._err) 1009 return _AIPSVisibilityIter(self._data, self._err)
1010
1011 - def _generate_antennas(self):
1012 """Generate the 'antennas' attribute.""" 1013 1014 if not self._antennas: 1015 antable = self.table('AN', 0) 1016 for antenna in antable: 1017 self._antennas.append(antenna.anname.rstrip()) 1018 continue 1019 pass 1020 return self._antennas
1021 1022 antennas = property(_generate_antennas, 1023 doc = 'Antennas in this data set.') 1024
1025 - def _generate_polarizations(self):
1026 """Generate the 'polarizations' attribute. 1027 1028 Returns a list of the polarizations for this data set.""" 1029 1030 if not self._polarizations: 1031 for stokes in self.stokes: 1032 if len(stokes) == 2: 1033 for polarization in stokes: 1034 if not polarization in self._polarizations: 1035 self._polarizations.append(polarization) 1036 pass 1037 continue 1038 pass 1039 continue 1040 pass 1041 return self._polarizations
1042 polarizations = property(_generate_polarizations, 1043 doc='Polarizations in this data set.') 1044
1045 - def _generate_sources(self):
1046 """Generate the 'sources' attribute.""" 1047 1048 if not self._sources: 1049 sutable = self.table('SU', 0) 1050 for source in sutable: 1051 self._sources.append(source.source.rstrip()) 1052 continue 1053 pass 1054 return self._sources
1055 sources = property(_generate_sources, 1056 doc='Sources in this data set.') 1057
1058 - def attach_table(self, name, version, **kwds):
1059 """Attach an extension table to this UV data set. 1060 1061 A new extension table is created if the extension table NAME 1062 with version VERSION doesn't exist. If VERSION is 0, a new 1063 extension table is created with a version that is one higher 1064 than the highest available version.""" 1065 1066 if not name.startswith('AIPS '): 1067 name = 'AIPS ' + name 1068 1069 if version == 0: 1070 version = Obit.UVGetHighVer(self._data.me, name) + 1 1071 1072 header = self._data.Desc.Dict 1073 jlocif = header['jlocif'] 1074 no_if = header['inaxes'][jlocif] 1075 if 'no_if' in kwds: 1076 no_if = kwds['no_if'] 1077 pass 1078 no_pol = len(self.polarizations) 1079 if 'no_pol' in kwds: 1080 no_pol = kwds['no_pol'] 1081 pass 1082 data = Obit.UVCastData(self._data.me) 1083 if name == 'AIPS AI': 1084 Obit.TableAI(data, [version], 3, name, 1085 kwds['no_term'], self._err.me) 1086 elif name == 'AIPS CL': 1087 Obit.TableCL(data, [version], 3, name, 1088 no_pol, no_if, kwds['no_term'], self._err.me) 1089 elif name == 'AIPS FQ': 1090 Obit.TableFQ(data, [version], 3, name, no_if, self._err.me) 1091 elif name == 'AIPS NI': 1092 Obit.TableNI(data, [version], 3, name, 1093 kwds['num_coef'], self._err.me) 1094 elif name == 'AIPS PS': 1095 Obit.TablePS(data, [version], 3, name, self._err.me) 1096 elif name == 'AIPS SN': 1097 Obit.TableSN(data, [version], 3, name, 1098 no_pol, no_if, self._err.me) 1099 elif name == 'AIPS SU': 1100 Obit.TableSU(data, [version], 3, name, no_if, self._err.me) 1101 else: 1102 msg = 'Attaching %s tables is not implemented yet' % name 1103 raise NotImplementedError, msg 1104 if self._err.isErr: 1105 raise RuntimeError 1106 return _AIPSTable(self._data, name, version)
1107 1108 history = property(lambda self: _AIPSHistory(self._data)) 1109 1110 pass # class AIPSUVData
1111 1112 1113 err = OErr.OErr() 1114 OSystem.OSystem("", 1, 0, -1, [], -1, [], True, False, err) 1115