1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 """
18
19 This module provides the AIPSImage and AIPSUVData classes. These
20 classes implement most of the data oriented verb-like functionality
21 from classic AIPS.
22
23 Images can be manipulated by creating instances of the AIPSImage class:
24
25 >>> image = AIPSImage('NONAME', 'IMAGE', 1, 1)
26
27 For UV data, the AIPSUVData class should be used:
28
29 >>> uvdata = AIPSUVData('NONAME', 'UVDATA', 1, 1)
30
31 Checking whether the image or UV data actually exists is easy:
32
33 >>> image.exists()
34 False
35 >>> uvdata.exists()
36 False
37
38 >>> print uvdata
39 AIPSUVData('NONAME', 'UVDATA', 1, 1)
40
41 Checking whether two instance refer to the same data is fairly simple:
42
43 >>> image == uvdata
44 False
45
46 >>> image == AIPSImage('NONAME', 'IMAGE', 1, 1)
47 True
48
49 Both classes implement the copy method:
50
51 >>> uvjunk = uvdata.copy()
52 >>> uvjunk == uvdata
53 True
54 >>> uvjunk.name = 'GARBAGE'
55 >>> uvjunk != uvdata
56 True
57
58 """
59
60
61 import AIPS
62
63
64 import sys
65
66
67
68
69
70
71
72
73
74
75
77 """Return the name of the function that called us."""
78 return sys._getframe(1).f_code.co_name
79
80
82
83 """This class implements dispatching function calls to a proxy."""
84
88
90 func = self.inst._method(self.name)
91 return func(self.inst.desc, *args)
92
93
95
96 """This class implements the description of AIPS data that is used
97 when dispatching function calls to a proxy."""
98
99 - def __init__(self, name, klass, disk, seq, userno):
106
107
108
110 return self.__dict__[key]
111
112 pass
113
114
121
122
124
125 """This class describes the header of an AIPS image or UV data set."""
126
127 pass
128
129
131
132 """This class describes generic AIPS data."""
133
170
172 name = property(lambda self: self.desc.name, _set_name,
173 doc='Name of this data set.')
175 klass = property(lambda self: self.desc.klass, _set_klass,
176 doc='Class of this data set.')
183 disk = property(lambda self: self._disk, _set_disk,
184 doc='Disk where this data set is stored.')
186 seq = property(lambda self: self.desc.seq, _set_seq,
187 doc='Sequence number of this data set.')
189 userno = property(lambda self: self.desc.userno, _set_userno,
190 doc='User number used to access this data set.')
191
193 repr = "%s('%s', '%s', %d, %d)" % \
194 (self.__class__.__name__,
195 self.name, self.klass, self.disk, self.seq)
196 return repr
197
199 if self.__class__ != other.__class__:
200 return False
201 if self.desc.name != other.desc.name:
202 return False
203 if self.desc.klass != other.desc.klass:
204 return False
205 if self.desc.disk != other.desc.disk:
206 return False
207 if self.desc.seq != other.desc.seq:
208 return False
209 if self.desc.userno != other.desc.userno:
210 return False
211 return True
212
215
220
223
227
228 - def table(self, type, version):
230
232 return getattr(getattr(self.proxy, self.__class__.__name__), name)
233
235 """Check whether this image or data set exists.
236
237 Returns True if the image or data set exists, False otherwise."""
238 return self._method(_whoami())(self.desc)
239
241 """Verify whether this image or data set can be accessed."""
242 return self._method(_whoami())(self.desc)
243
247 header = property(_generate_header,
248 doc='Header for this data set.')
249
252 keywords = property(_generate_keywords,
253 doc='Keywords for this data set.')
254
256 dict = self._method('tables')(self.desc)
257 return dict
258 tables = property(_generate_tables,
259 doc='Extension tables for this data set.')
260
261 history = property(lambda self: _AIPSHistory(self),
262 doc='History table for this data set.')
263
265 """Get the highest version of an extension table.
266
267 Returns the highest available version number of the extension
268 table TYPE."""
269 return self._method(_whoami())(self.desc, type)
270
271 - def rename(self, name=None, klass=None, seq=None, **kwds):
272 """Rename this image or data set.
273
274 NAME is the new name, KLASS is the new class and SEQ is the
275 new sequence number for the data set. Note that you can't
276 change the disk number, since that would require copying the
277 data."""
278 if name == None: name = self.name
279 if klass == None: klass = self.klass
280 if seq == None: seq = self.seq
281 if 'name' in kwds: name = kwds['name']
282 if 'klass' in kwds: klass = kwds['name']
283 if 'seq' in kwds: seq = kwds['seq']
284 result = self._method(_whoami())(self.desc, name, klass, seq)
285 self.name = result[0]
286 self.klass = result[1]
287 self.seq = result[2]
288 return result
289
290 - def zap(self, force=False):
291 """Destroy this image or data set."""
292 return self._method(_whoami())(self.desc, force)
293
295 """Clear all read and write status flags."""
296 return self._method(_whoami())(self.desc)
297
299 """Get the header of an extension table.
300
301 Returns the header of version VERSION of the extension table
302 TYPE."""
303 return self._method(_whoami())(self.desc, type, version)
304
305
307 """Get a row from an extension table.
308
309 Returns row ROWNO from version VERSION of extension table TYPE
310 as a dictionary."""
311 return self._method(_whoami())(self.desc, type, version, rowno)
312
314 """Destroy an extension table.
315
316 Deletes version VERSION of the extension table TYPE. If
317 VERSION is 0, delete the highest version of table TYPE. If
318 VERSION is -1, delete all versions of table TYPE."""
319 return self._method(_whoami())(self.desc, type, version)
320
322 return self._method('antennas')(self.desc)
323 antennas = property(_generate_antennas,
324 doc = 'Antennas in this data set.')
325
327 return self._method('polarizations')(self.desc)
328 polarizations = property(_generate_polarizations,
329 doc='Polarizations in this data set.')
330
332 return self._method('sources')(self.desc)
333 sources = property(_generate_sources,
334 doc='Sources in this data set.')
335
337 return self._method('stokes')(self.desc)
338 stokes = property(_generate_stokes,
339 doc='Stokes parameters for this data set.')
340
341 pass
342
343
345
346 """This class describes an AIPS image."""
347 pass
348
349
351
352 """This class describes an AIPS UV data set."""
353 pass
354
355
357
358 """ This class implements dispatching table oriented function
359 calls to a proxy."""
360
363
365 func = self.inst._data._method(self.name + '_table')
366 return func(self.inst._data.desc,
367 self.inst._name, self.inst._version, *args)
368
369 pass
370
371
373
374 """This class describes a row of an AIPS extenstion table."""
375
376 pass
377
378
380
381 """This class provides an iterator for AIPS extension tables."""
382
384 self._table = table
385 self._len = len(self._table)
386 self._index = 0
387 return
388
390 if self._index >= self._len:
391 raise StopIteration
392 result = self._table[self._index]
393 self._index += 1
394 return result
395
396 pass
397
398
400
401 """This class describes a generic AIPS extension table."""
402
403 - def __init__(self, data, name, version):
404 self._data = data
405 self._name = name
406 self._version = version
407 return
408
411
415
418
421
424 keywords = property(_generate_keywords,
425 doc='Keywords for this table.')
426
429 version = property(_generate_version, doc='Table version.')
430
431 pass
432
433
434 -class _AIPSHistoryMethod(_AIPSDataMethod):
435
436 """ This class implements dispatching history oriented function
437 calls to a proxy."""
438
439 - def __init__(self, inst, name):
441
442 - def __call__(self, *args):
443 func = self.inst._data._method(self.name + '_history')
444 return func(self.inst._data.desc, *args)
445
446 pass
447
448
449 -class _AIPSHistory(object):
450
451 """This class describes an AIPS hostory table."""
452
453 - def __init__(self, data):
454 self._data = data
455 return
456
457 - def __getitem__(self, key):
458 return _AIPSHistoryMethod(self, '_getitem')(key)
459
460 pass
461
462
463 -class _AIPSCatEntry(_dictify):
464
465 """This class describes an AIPS catalog entry."""
466
467 pass
468
469
471
472 """This class describes an entire AIPS catalogue."""
473
487
489 return self._cat[key]
490
492 return repr(self._cat)
493
495 return self._cat.iterkeys()
496
498 s = ''
499 for disk in self._cat:
500 s += 'Catalog on disk %2d\n' % disk
501 s += ' Cat Mapname Class Seq Pt Last access\n'
502 if len(self._cat[disk]) > 0:
503 s += ''.join([' %3d %-12.12s.%-6.6s. %4d %-2.2s %s %s\n' \
504 % (entry.cno, entry.name, entry.klass,
505 entry.seq, entry.type, entry.date,
506 entry.time) for entry in self._cat[disk]])
507 pass
508 continue
509 return s.strip()
510
511 - def zap(self, force=False, **kwds):
512
513 """Removes a catalogue entry."""
514
515 name = None
516 if 'name' in kwds: name = kwds['name']; del kwds['name']
517 klass = None
518 if 'klass' in kwds: klass = kwds['klass']; del kwds['klass']
519 seq = None
520 if 'seq' in kwds: seq = kwds['seq']; del kwds['seq']
521
522
523 if len(kwds) > 0:
524 keys = ["'%s'" % key for key in kwds.keys()]
525 msg = "zap() got an unexpected keyword argument %s" % keys[0]
526 raise TypeError, msg
527
528 for disk in self._cat:
529 for entry in self._cat[disk]:
530 if name and not entry['name'] == name:
531 continue
532 if klass and not entry['klass'] == klass:
533 continue
534 if seq and not entry['seq'] == seq:
535 continue
536 if entry['type'] == 'MA':
537 AIPSImage(entry['name'], entry['klass'],
538 disk, entry['seq']).zap(force)
539 elif entry['type'] == 'UV':
540 AIPSUVData(entry['name'], entry['klass'],
541 disk, entry['seq']).zap(force)
542 pass
543 continue
544 continue
545 return
546
547 pass
548
549
550
551 if __name__ == '__main__':
552 import doctest, sys
553 results = doctest.testmod(sys.modules[__name__])
554 sys.exit(results[0])
555