miriad 4.1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README +103 -0
- data/Rakefile +82 -0
- data/ext/bug.c +341 -0
- data/ext/dio.c +317 -0
- data/ext/extconf.rb +49 -0
- data/ext/headio.c +835 -0
- data/ext/hio.c +1515 -0
- data/ext/hio.h +48 -0
- data/ext/interface.c +74 -0
- data/ext/io.h +56 -0
- data/ext/key.c +934 -0
- data/ext/maskio.c +398 -0
- data/ext/maxdimc.h.in +9 -0
- data/ext/miriad.h +371 -0
- data/ext/miriad.i +464 -0
- data/ext/miriad_ruby.c +602 -0
- data/ext/miriad_ruby.i +443 -0
- data/ext/miriad_wrap.c +4210 -0
- data/ext/narray_ruby.swg +59 -0
- data/ext/pack.c +639 -0
- data/ext/scrio.c +132 -0
- data/ext/sysdep.h +185 -0
- data/ext/uvio.c +4934 -0
- data/ext/xyio.c +476 -0
- data/ext/xyzio.c +2020 -0
- data/lib/miriad.rb +564 -0
- metadata +93 -0
data/lib/miriad.rb
ADDED
@@ -0,0 +1,564 @@
|
|
1
|
+
# The MIRIAD-Ruby package...
|
2
|
+
#
|
3
|
+
# 1. makes MIRIAD datasets accessible from Ruby by wrapping the MIRIAD UVIO
|
4
|
+
# routines.
|
5
|
+
#
|
6
|
+
# 2. makes Ruby usable with MIRIAD datasets by adding convenience, utility, and
|
7
|
+
# astronomy related methods to Ruby classes.
|
8
|
+
#
|
9
|
+
#--
|
10
|
+
#$Id: miriad.rb 901 2008-04-17 22:44:07Z davidm $
|
11
|
+
#++
|
12
|
+
|
13
|
+
require 'rbconfig'
|
14
|
+
require 'rubygems'
|
15
|
+
require 'date'
|
16
|
+
require 'narray'
|
17
|
+
miriad_shared_lib = 'miriad.' + Config::CONFIG['DLEXT']
|
18
|
+
require miriad_shared_lib
|
19
|
+
require 'miriad_ruby_shared_library' if false # Fake out RDoc
|
20
|
+
#require 'fftw3'
|
21
|
+
|
22
|
+
# Add CKMS constant to Math module
|
23
|
+
Math::const_set :CKMS, 299792.458 unless Math::const_defined? :CKMS
|
24
|
+
|
25
|
+
# The MIRIAD package adds angle conversion methods to the Math module
|
26
|
+
module Math
|
27
|
+
# Convert possibly non-integer degrees +fr+ to [degrees, minutes, seconds]
|
28
|
+
# where degrees and minutes are integers.
|
29
|
+
def self.d_to_dms(fr)
|
30
|
+
sign = fr <=> 0
|
31
|
+
fr *= sign
|
32
|
+
d = fr.to_i; fr %= 1; fr *= 60
|
33
|
+
m = fr.to_i; fr %= 1; fr *= 60
|
34
|
+
return d*sign, m, fr
|
35
|
+
end
|
36
|
+
|
37
|
+
# Convert possibly non-integer hours +fr+ to [hours, minutes, seconds]
|
38
|
+
# where hours and minutes are integers.
|
39
|
+
def self.h_to_hms(fr); d_to_dms(fr); end
|
40
|
+
|
41
|
+
# Convert degrees, minutes, seconds to possibly non-integer degrees.
|
42
|
+
# Missing arguments are assumed to be 0.
|
43
|
+
def self.dms_to_d(*args)
|
44
|
+
d = 0.to_r
|
45
|
+
d += args.shift unless args.empty?
|
46
|
+
sign = d <=> 0
|
47
|
+
d += args.shift * Rational(sign,60) unless args.empty?
|
48
|
+
d += args.shift * Rational(sign,3600) unless args.empty?
|
49
|
+
return d
|
50
|
+
end
|
51
|
+
|
52
|
+
# Convert hours, minutes, seconds to possibly non-integer hours.
|
53
|
+
# Missing arguments are assumed to be 0.
|
54
|
+
def self.hms_to_h(*args); dms_to_d(*args); end
|
55
|
+
|
56
|
+
# Convert degrees to radians
|
57
|
+
def self.d2r(d) d*PI/180; end
|
58
|
+
# Convert radians to degrees
|
59
|
+
def self.r2d(r) r*180/PI; end
|
60
|
+
# Convert hours to radians
|
61
|
+
def self.h2r(h) h*PI/12; end
|
62
|
+
# Convert radians to hours
|
63
|
+
def self.r2h(r) r*12/PI; end
|
64
|
+
# Convert degrees to hours
|
65
|
+
def self.d2h(d) d/15.0; end
|
66
|
+
# Convert hours to degrees
|
67
|
+
def self.h2d(h) h*15.0; end
|
68
|
+
end
|
69
|
+
|
70
|
+
# Th MIRIAD package adds angle conversion and angle formatting methods to
|
71
|
+
# Numeric class.
|
72
|
+
class Numeric
|
73
|
+
# Convert +self+ to [degrees, minutes, seconds] where degrees and minutes are
|
74
|
+
# integers.
|
75
|
+
def to_dms() Math.d_to_dms(self); end
|
76
|
+
# Convert +self+ to [hours, minutes, seconds] where hours and minutes are
|
77
|
+
# integers.
|
78
|
+
alias :to_hms :to_dms
|
79
|
+
# Convert +self+ to "##d##m##.###s" format with +prec+ fractional places.
|
80
|
+
def to_dmsstr(prec=3)
|
81
|
+
width = prec == 0 ? 2 : prec+3
|
82
|
+
"%02dd%02dm%0#{width}.#{prec}fs" % to_dms
|
83
|
+
end
|
84
|
+
# Convert +self+ to "##:##:##.###" format with +prec+ fractional places.
|
85
|
+
def to_hmsstr(prec=3)
|
86
|
+
width = prec == 0 ? 2 : prec+3
|
87
|
+
"%02d:%02d:%0#{width}.#{prec}f" % to_dms
|
88
|
+
end
|
89
|
+
# Convert +self+ from degrees to radians (i.e. <tt>Math.d2r(self)</tt>).
|
90
|
+
def d2r() Math.d2r(self); end
|
91
|
+
# Convert +self+ from radians to degrees (i.e. <tt>Math.r2d(self)</tt>).
|
92
|
+
def r2d() Math.r2d(self); end
|
93
|
+
# Convert +self+ from hours to radians (i.e. <tt>Math.h2r(self)</tt>).
|
94
|
+
def h2r() Math.h2r(self); end
|
95
|
+
# Convert +self+ from radians to hours (i.e. <tt>Math.r2h(self)</tt>).
|
96
|
+
def r2h() Math.r2h(self); end
|
97
|
+
# Convert +self+ from degrees to hours (i.e. <tt>Math.d2h(self)</tt>).
|
98
|
+
def d2h() Math.d2h(self); end
|
99
|
+
# Convert +self+ from hours to degrees (i.e. <tt>Math.h2d(self)</tt>).
|
100
|
+
def h2d() Math.h2d(self); end
|
101
|
+
end
|
102
|
+
|
103
|
+
# The MIRIAD package adds angle conversion methods to Array class.
|
104
|
+
class Array
|
105
|
+
# Convert +self+ from [degrees, minutes, seconds] to degrees.
|
106
|
+
# Missing arguments are assumed to be 0.
|
107
|
+
def dms_to_d; Math::dms_to_d(*self); end
|
108
|
+
# Convert +self+ from [hours, minutes, seconds] to hours.
|
109
|
+
# Missing arguments are assumed to be 0.
|
110
|
+
alias :hms_to_h :dms_to_d
|
111
|
+
end
|
112
|
+
|
113
|
+
# The MIRIAD package adds angle parsing methods to String class.
|
114
|
+
class String
|
115
|
+
# Parse a "dd:mm:ss.sss" String to Float degrees.
|
116
|
+
# <b>NOT</b> the inverse of Numeric#to_dmsstr (but may become so).
|
117
|
+
def dms_to_d; Math::dms_to_d(*split(':').map{|s| s.to_f}); end
|
118
|
+
# Parse a "hh:mm:ss.sss" String to Float hours.
|
119
|
+
alias :hms_to_h :dms_to_d
|
120
|
+
end
|
121
|
+
|
122
|
+
# The MIRIAD package adds astronomy-related and other utilty methods to
|
123
|
+
# the +DateTime+ class.
|
124
|
+
class DateTime
|
125
|
+
|
126
|
+
# The J2000 epoch
|
127
|
+
J2000 = civil(2000,1,1,12)
|
128
|
+
|
129
|
+
# Create a +DateTime+ object from a numeric Astronomical Julian Date.
|
130
|
+
def self.ajd(d)
|
131
|
+
J2000 + d - J2000.ajd
|
132
|
+
end
|
133
|
+
|
134
|
+
# Besselian year at the time represented by +self+.
|
135
|
+
#
|
136
|
+
# Adapted from http://hpiers.obspm.fr/eop-pc/models/constants.html
|
137
|
+
def by
|
138
|
+
2000+(amjd-51544.5)/365.242189813
|
139
|
+
end
|
140
|
+
|
141
|
+
def ut2_ut1
|
142
|
+
# Taken from
|
143
|
+
# http://www.iers.org/products/6/11136/orig/bulletina-xx-042.txt
|
144
|
+
pi2t=Math::PI*2*(by%1)
|
145
|
+
ENV['UT2_UT1'] || 0.022 * Math::sin(pi2t) \
|
146
|
+
- 0.012 * Math::cos(pi2t) \
|
147
|
+
- 0.006 * Math::sin(2*pi2t) \
|
148
|
+
+ 0.007 * Math::cos(2*pi2t)
|
149
|
+
end
|
150
|
+
|
151
|
+
# UT1-UTC (unit is seconds) at the time represented by +self+
|
152
|
+
#
|
153
|
+
# This is an increasingly out-of-date approximation only. Taken from
|
154
|
+
# http://www.iers.org/products/6/11136/orig/bulletina-xx-042.txt
|
155
|
+
def ut1_utc
|
156
|
+
# TODO Get more accurate measurement of this value from usno
|
157
|
+
ENV.has_key?('UT1_UTC') ?
|
158
|
+
ENV['UT1_UTC'].to_f : -0.2221 - 0.00092 * (amjd - 54399) - ut2_ut1
|
159
|
+
end
|
160
|
+
|
161
|
+
# A +DateTime+ object corresponding to the same time as +self+, but
|
162
|
+
# with an offset of 0. Returns +self+ if <tt>self.offset == 0</tt>.
|
163
|
+
def to_utc
|
164
|
+
(offset == 0) ? self : new_offset(0)
|
165
|
+
end
|
166
|
+
|
167
|
+
# Create a +DateTime+ object from a numeric Astronomical Julian Date.
|
168
|
+
def self.utc
|
169
|
+
now.to_utc
|
170
|
+
end
|
171
|
+
|
172
|
+
# UT1 (expressed in hours) at the time represented by +self+
|
173
|
+
def ut1
|
174
|
+
((amjd % 1) * 24 + ut1_utc/(60*60)) % 24
|
175
|
+
end
|
176
|
+
|
177
|
+
# UT1 (expressed in hours) at the current time.
|
178
|
+
def self.ut1
|
179
|
+
now.ut1
|
180
|
+
end
|
181
|
+
|
182
|
+
# Greenwich Mean Sidereal Time at the time represented by +self+.
|
183
|
+
#
|
184
|
+
# Adapted from http://aa.usno.navy.mil/faq/docs/GAST.php
|
185
|
+
def gmst
|
186
|
+
# The local variables here have been slightly renamed from the reference to
|
187
|
+
# be more ruby-esque. Here is the mapping...
|
188
|
+
#
|
189
|
+
# Local Reference
|
190
|
+
# jdut1 JD
|
191
|
+
# jd0 JD0
|
192
|
+
# h H
|
193
|
+
# d D
|
194
|
+
# d0 D0
|
195
|
+
# t T
|
196
|
+
|
197
|
+
# The UT Julian date of the time of interest
|
198
|
+
jdut1 = ajd + ut1_utc/(24*60*60)
|
199
|
+
# Julian date of the previous midnight (0h) UT
|
200
|
+
jd0 = (jdut1-0.5).floor + 0.5
|
201
|
+
# Hours of UT elapsed since jd0
|
202
|
+
h = (jdut1 - jd0) * 24.0
|
203
|
+
# Days and fraction of day since J2000 epoch
|
204
|
+
d = jdut1 - J2000.ajd
|
205
|
+
# Integer days (and a half) since epoch
|
206
|
+
d0 = jd0 - J2000.ajd
|
207
|
+
# Fractional centuries since epoch
|
208
|
+
t = d/36525.0
|
209
|
+
# gmst
|
210
|
+
(6.697374558 + 0.06570982441908 * d0 + 1.00273790935 * h + 0.000026 * t**2) % 24.0
|
211
|
+
end
|
212
|
+
|
213
|
+
# Equation of the Equinoxes at the time represented by +self+.
|
214
|
+
#
|
215
|
+
# Adapted from http://aa.usno.navy.mil/faq/docs/GAST.php
|
216
|
+
def eqeq
|
217
|
+
# The local variables here have been slightly renamed from the reference to
|
218
|
+
# be more ruby-esque. Here is the mapping...
|
219
|
+
#
|
220
|
+
# Local Reference
|
221
|
+
# jdut1 JD
|
222
|
+
# d D
|
223
|
+
# omega Omega (Greek letter)
|
224
|
+
# dpsi Delta Psi (Greek letters)
|
225
|
+
# eps epsilon (Greek letter)
|
226
|
+
|
227
|
+
# The UT Julian date of the time of interest
|
228
|
+
jdut1 = ajd + ut1_utc/(24*60*60)
|
229
|
+
# Days and fraction of day since J2000 epoch
|
230
|
+
d = jdut1 - J2000.ajd
|
231
|
+
# Longitude of the ascending node of the Moon
|
232
|
+
omega = 125.04 - 0.052954 * d
|
233
|
+
# Mean Longitude of the Sun
|
234
|
+
l = 280.47 + 0.98565 * d
|
235
|
+
# Delta psi
|
236
|
+
dpsi = -0.000319 * Math.sin(omega.d2r) \
|
237
|
+
-0.000024 * Math.sin(2*l.d2r)
|
238
|
+
# Obliquity
|
239
|
+
eps = 23.4393 - 0.0000004 * d
|
240
|
+
# eqeq
|
241
|
+
dpsi * Math.cos(eps.d2r)
|
242
|
+
end
|
243
|
+
|
244
|
+
# Greenwich Apparent Sidereal Time at the time represented by +self+.
|
245
|
+
def gast
|
246
|
+
(gmst + eqeq) % 24.0
|
247
|
+
end
|
248
|
+
|
249
|
+
# Local Mean Sidereal Time in hours at the time represented by
|
250
|
+
# +self+. +longitude+ is in degrees.
|
251
|
+
def lmst(longitude=0.0)
|
252
|
+
(gmst + longitude.d2h) % 24.0
|
253
|
+
end
|
254
|
+
|
255
|
+
# Local Apparent Sidereal Time in hours at the time represented by
|
256
|
+
# +self+. +longitude+ is in degrees.
|
257
|
+
def last(longitude=0.0)
|
258
|
+
(gast + longitude.d2h) % 24.0
|
259
|
+
end
|
260
|
+
end
|
261
|
+
|
262
|
+
# A subclass of StandardError raised by wrapped MIRIAD code.
|
263
|
+
class MirlibError < StandardError
|
264
|
+
end
|
265
|
+
|
266
|
+
# In addition to the Uvio and Visibility classes, the Miriad module also
|
267
|
+
# provides some utility methods.
|
268
|
+
module Miriad
|
269
|
+
|
270
|
+
# The version of mirlib on which this package is based.
|
271
|
+
MIRLIB_VERSION = "4.1.0"
|
272
|
+
|
273
|
+
# Contains Polarization code constants. The values follow the AIPS/FITS
|
274
|
+
# conventions.
|
275
|
+
module Pol
|
276
|
+
# Stokes I
|
277
|
+
I = 1
|
278
|
+
# Stokes Q
|
279
|
+
Q = 2
|
280
|
+
# Stokes U
|
281
|
+
U = 3
|
282
|
+
# Stokes V
|
283
|
+
V = 4
|
284
|
+
# Circular RR
|
285
|
+
RR = -1
|
286
|
+
# Circular LL
|
287
|
+
LL = -2
|
288
|
+
# Circular RL
|
289
|
+
RL = -3
|
290
|
+
# Circular LR
|
291
|
+
LR = -4
|
292
|
+
# Linear XX
|
293
|
+
XX = -5
|
294
|
+
# Linear YY
|
295
|
+
YY = -6
|
296
|
+
# Linear XY
|
297
|
+
XY = -7
|
298
|
+
# Linear YX
|
299
|
+
YX = -8
|
300
|
+
end
|
301
|
+
|
302
|
+
# Compute the [u,v,w] projection of a baseline with endpoints <tt>xyz1</tt>
|
303
|
+
# and <tt>xyz2</tt> in the direction of +obsra+, +obsdec+ (i.e. right
|
304
|
+
# ascension and declination in the current epoch) at the local apparent
|
305
|
+
# sidereal time +lst+. <tt>xyz1</tt> and <tt>xyz2</tt> are three element
|
306
|
+
# arrays containing geocentric coordinates of the baseline endpoints, and
|
307
|
+
# +obsra+, +obsdec+, and +lst+ are all in radians
|
308
|
+
#
|
309
|
+
# The body of this method was transcribed from the MIRIAD source file
|
310
|
+
# <tt>uvcal.for</tt>.
|
311
|
+
def self.xyz2uvw(xyz1,xyz2,obsra,obsdec,lst)
|
312
|
+
x1,y1,z1 = xyz1
|
313
|
+
x2,y2,z2 = xyz2
|
314
|
+
|
315
|
+
ha = lst - obsra
|
316
|
+
sinha = Math.sin(ha)
|
317
|
+
cosha = Math.cos(ha)
|
318
|
+
sind = Math.sin(obsdec)
|
319
|
+
cosd = Math.cos(obsdec)
|
320
|
+
|
321
|
+
bxx = x2 - x1
|
322
|
+
byy = y2 - y1
|
323
|
+
bzz = z2 - z1
|
324
|
+
|
325
|
+
u = bxx * sinha + byy * cosha
|
326
|
+
v = -(bxx * cosha - byy * sinha)*sind + bzz*cosd
|
327
|
+
w = (bxx * cosha - byy * sinha)*cosd + bzz*sind
|
328
|
+
|
329
|
+
[u,v,w]
|
330
|
+
end
|
331
|
+
|
332
|
+
# Precess from one mean RA,DEC to another.
|
333
|
+
#
|
334
|
+
# A simple precession routine, to precess from one set of mean
|
335
|
+
# equatorial coordinates (RA,DEC), to another at a different epoch.
|
336
|
+
# This is accurate to order 0.3 arcsec over 50 years.
|
337
|
+
#
|
338
|
+
# Reference:
|
339
|
+
# Explanatory Supplement to the Astronomical Almanac, 1993. p 105-106.
|
340
|
+
#
|
341
|
+
# NOTE: This does not take account of atmospheric refraction,
|
342
|
+
# nutation, aberration nor gravitational deflection.
|
343
|
+
#
|
344
|
+
# Input:
|
345
|
+
# ra,dec RA,DEC at the from_jd epoch (radians).
|
346
|
+
# to_jd Julian day of the new epoch. (defaults to current time)
|
347
|
+
# from_jd Julian day of the known epoch. (defaults to J2000)
|
348
|
+
#
|
349
|
+
# Output:
|
350
|
+
# [ra+,dec] Precessed coordinates (radians).
|
351
|
+
#
|
352
|
+
# The body of this method was transcribed from the miriad source file
|
353
|
+
# <tt>ephem.for</tt> originally created by Bob Sault.
|
354
|
+
def self.precess(ra, dec, to_jd=DateTime.now.ajd, from_jd=DateTime::J2000.ajd)
|
355
|
+
t = (from_jd - 2451545)/36525
|
356
|
+
m = Math::PI/180 * (1.2812323 + (0.0003879 + 0.0000101*t)*t)*t
|
357
|
+
n = Math::PI/180 * (0.5567530 - (0.0001185 + 0.0000116*t)*t)*t
|
358
|
+
rm = ra - 0.5*(m + n*Math.sin(ra)*Math.tan(dec))
|
359
|
+
dm = dec - 0.5*n*Math.cos(rm)
|
360
|
+
#
|
361
|
+
# J2000 coordinates.
|
362
|
+
#
|
363
|
+
r0 = ra - m - n*Math.sin(rm)*Math.tan(dm)
|
364
|
+
d0 = dec - n*Math.cos(rm)
|
365
|
+
#
|
366
|
+
# Coordinates of the other epoch.
|
367
|
+
#
|
368
|
+
t = (to_jd - 2451545)/36525
|
369
|
+
m = Math::PI/180 * (1.2812323 + (0.0003879 + 0.0000101*t)*t)*t
|
370
|
+
n = Math::PI/180 * (0.5567530 - (0.0001185 + 0.0000116*t)*t)*t
|
371
|
+
rm = r0 + 0.5*(m + n*Math.sin(r0)*Math.tan(d0))
|
372
|
+
dm = d0 - 0.5*n*Math.cos(rm)
|
373
|
+
|
374
|
+
ra = r0 + m + n*Math.sin(rm)*Math.tan(dm)
|
375
|
+
dec = d0 + n*Math.cos(rm)
|
376
|
+
|
377
|
+
[ra, dec]
|
378
|
+
end
|
379
|
+
|
380
|
+
# Format a MIRIAD baseline number as "A1-A2".
|
381
|
+
def self.basstr(baseline)
|
382
|
+
baseline = baseline.to_i
|
383
|
+
"%d-%d" % basant(baseline)
|
384
|
+
end
|
385
|
+
|
386
|
+
# Convert a MIRIAD baseline number into two antenna numbers.
|
387
|
+
def self.basant(baseline)
|
388
|
+
baseline = baseline.to_i
|
389
|
+
[baseline/256, baseline%256]
|
390
|
+
end
|
391
|
+
|
392
|
+
# Convert two antenna numbers into a MIRIAD baseline number
|
393
|
+
def self.antbas(a1,a2)
|
394
|
+
a1, a2 = a2, a1 if a2 < a1
|
395
|
+
a1.to_i*256 + a2.to_i
|
396
|
+
end
|
397
|
+
|
398
|
+
# Convert two antenna numbers, <tt>a1</tt> and <tt>a2</tt>, into a baseline
|
399
|
+
# index (NOT a MIRIAD baseline number) using +n+ as the maximum antenna
|
400
|
+
# number.
|
401
|
+
def self.basidx(a1,a2,n)
|
402
|
+
a1, a2 = a2, a1 if a2 < a1
|
403
|
+
return a1 + ((2*n+1)*(a2-a1) - (a2-a1)**2) / 2
|
404
|
+
end
|
405
|
+
|
406
|
+
# Convert a baseline index (NOT a MIRIAD baseline number) +i+ into two
|
407
|
+
# antenna numbers using +n+ as the maximum antenna number.
|
408
|
+
def self.idxbas(i,n)
|
409
|
+
b = -(2*n+1)
|
410
|
+
ac = 2*i
|
411
|
+
r = Math.sqrt(b**2-4*ac)
|
412
|
+
d = (-b-r.floor)/2
|
413
|
+
d -= 1 while (a1 = i + (b*d + d**2)/2) < 0
|
414
|
+
a2 = a1 + d
|
415
|
+
[a1, a2]
|
416
|
+
end
|
417
|
+
|
418
|
+
# The Visibility class holds preamble, visdata, and flags for one integration
|
419
|
+
# on one baseline. It also provides convenience methods to query and access
|
420
|
+
# these attributes and their sub-attributes.
|
421
|
+
class Visibility
|
422
|
+
# The MIRIAD preamble
|
423
|
+
attr_accessor :preamble
|
424
|
+
# The MIRIAD visdata
|
425
|
+
attr_accessor :data
|
426
|
+
# The MIRIAD flags
|
427
|
+
attr_accessor :flags
|
428
|
+
# Constructs a new Visibility object containing the given +preamble+,
|
429
|
+
# +data+, and +flags+ objects. Not used often. Usually Visibility objects
|
430
|
+
# are obtained from Uvio#read.
|
431
|
+
def initialize(preamble, data, flags)
|
432
|
+
@preamble = preamble
|
433
|
+
@data = data
|
434
|
+
@flags = flags
|
435
|
+
end
|
436
|
+
# call-seq: Visibility[preamble, data, flags]
|
437
|
+
#
|
438
|
+
# Alternate way to contruct a Visibility object.
|
439
|
+
def self.[](preamble, data, flags)
|
440
|
+
self.new(preamble, data, flags)
|
441
|
+
end
|
442
|
+
# Returns the [u,v,w] coordinates from the preamble.
|
443
|
+
def coord() preamble[0..2]; end
|
444
|
+
# Returns the Julian date from the preamble.
|
445
|
+
def jd() preamble[3]; end
|
446
|
+
# Returns the baseline number from the preamble.
|
447
|
+
def baseline() preamble[4].to_i; end
|
448
|
+
# Returns a DateTime object corresponding to the Julian date from the
|
449
|
+
# preamble.
|
450
|
+
def time() DateTime.ajd(jd); end
|
451
|
+
# Returns the two antenna numbers corresponding to the baseline number
|
452
|
+
# from the preamble.
|
453
|
+
def ants() Miriad.basant(baseline); end
|
454
|
+
# True if the baseline is an autocorrelation.
|
455
|
+
def auto?() a1,a2=Miriad.basant(baseline); a1 == a2; end
|
456
|
+
# True if the baseline is a cross correlation.
|
457
|
+
def cross?() a1,a2=Miriad.basant(baseline); a1 != a2; end
|
458
|
+
## TODO Make this more robust (i.e. less hard-coded)
|
459
|
+
#def lags()
|
460
|
+
# i = NArray.int(1024).indgen!(512) % 1024
|
461
|
+
# d = data[i]
|
462
|
+
# d[0] = 0 # Zero-out the DC channel
|
463
|
+
# d -= d.mean # Remove the mean
|
464
|
+
# FFTW3.dft(d,1)/1024
|
465
|
+
#end
|
466
|
+
end
|
467
|
+
|
468
|
+
# The Uvio class is mostly a SWIG wrapper around the UVIO C routines from
|
469
|
+
# MIRIAD. Some convenience methods are added in
|
470
|
+
# miriad.rb[link:files/miriad_rb.html].
|
471
|
+
class Uvio
|
472
|
+
# Calls <tt>putvr(var, data, ?a)</tt>
|
473
|
+
def putvra(var,data) putvr(var, data, ?a); end
|
474
|
+
# Calls <tt>putvr(var, data, ?i)</tt>
|
475
|
+
def putvri(var,data) putvr(var, data, ?i); end
|
476
|
+
# Calls <tt>putvr(var, data, ?r)</tt>
|
477
|
+
def putvrr(var,data) putvr(var, data, ?r); end
|
478
|
+
# Calls <tt>putvr(var, data, ?d)</tt>
|
479
|
+
def putvrd(var,data) putvr(var, data, ?d); end
|
480
|
+
|
481
|
+
# Convenience wrapper around self.new. Self.new may become private, so use
|
482
|
+
# this method instead.
|
483
|
+
def self.open(name,mode='r')
|
484
|
+
raise 'invalid dataset name' if name.nil? or name.empty?
|
485
|
+
case mode[0]
|
486
|
+
when ?r then
|
487
|
+
raise 'invalid dataset given' unless test ?d, name
|
488
|
+
when ?w then
|
489
|
+
raise 'dataset exists' if test ?d, name
|
490
|
+
when ?a then
|
491
|
+
raise 'invalid dataset given' unless test ?d, name
|
492
|
+
end
|
493
|
+
|
494
|
+
self.new(name,mode)
|
495
|
+
end
|
496
|
+
|
497
|
+
# call-seq:
|
498
|
+
# read() -> uvread(5, nchan, nchan) -> Visibility
|
499
|
+
# read(nil) -> uvread(5, nchan, nchan) -> Visibility
|
500
|
+
# read(vis) -> uvread(vis.preamble, vis.data, vis.flags) -> Visibility
|
501
|
+
# read(*args) -> uvread(*args) -> Visibility
|
502
|
+
#
|
503
|
+
# Convenience wrapper around uvread. Shortens data and flags if they were
|
504
|
+
# passed in longer than necessary. Always returns a Visibility, except at
|
505
|
+
# end of file in which case it returns +nil+.
|
506
|
+
#
|
507
|
+
# See uvread for details.
|
508
|
+
#
|
509
|
+
# <b>This method should be preferred over uvread. uvread may disappear in
|
510
|
+
# future versions!</b>
|
511
|
+
def read(*args)
|
512
|
+
if args.length == 0 || args[0].nil?
|
513
|
+
n, p, d, f = uvread(5,nchan,nchan)
|
514
|
+
elsif args.length == 1 && Visibility === args[0]
|
515
|
+
n, p, d, f = uvread(args[0].preamble,args[0].data,args[0].flags)
|
516
|
+
else
|
517
|
+
n, p, d, f = uvread(*args)
|
518
|
+
end
|
519
|
+
|
520
|
+
# Return nil on EOF
|
521
|
+
return nil if n == 0
|
522
|
+
|
523
|
+
# FIXME for Array inputs
|
524
|
+
# If nread is different than what was passed in
|
525
|
+
if n != d.length
|
526
|
+
# Shorten data and flags
|
527
|
+
d = d[0...n]
|
528
|
+
f = f[0...n]
|
529
|
+
end
|
530
|
+
|
531
|
+
# Return Visibility
|
532
|
+
return args[0] if Visibility === args[0]
|
533
|
+
Visibility[p,d,f]
|
534
|
+
end
|
535
|
+
|
536
|
+
# call-seq: baseline -> [ant1, ant2]
|
537
|
+
#
|
538
|
+
# Decodes the value of the +baseline+ uv variable and returns a two element
|
539
|
+
# array containing the two antenna numbers.
|
540
|
+
def baseline
|
541
|
+
bl = getvr('baseline')
|
542
|
+
bl = [bl.to_i/256, bl.to_i%256] if bl
|
543
|
+
end
|
544
|
+
|
545
|
+
# Uvio.foo, if foo is not a predefined attribute or method, will return the
|
546
|
+
# current value of the MIRIAD UV variable +foo+ or +nil+ if it doesn't
|
547
|
+
# (yet) exist.
|
548
|
+
#
|
549
|
+
# Uvio.foo=bar, if foo= is not a predefined attribute or method, will set
|
550
|
+
# the value of the MIRIAD UV variable +foo+ to +bar+. Only valid for
|
551
|
+
# datasets opened in write mode. [SETTER FUNCTIONALITY NOT YET
|
552
|
+
# IMPLEMENTED!]
|
553
|
+
def method_missing(sym,*args)
|
554
|
+
val = nil
|
555
|
+
var = sym.to_s
|
556
|
+
case var
|
557
|
+
when /=$/: break
|
558
|
+
else val = getvr(var)
|
559
|
+
end
|
560
|
+
val
|
561
|
+
end
|
562
|
+
end
|
563
|
+
|
564
|
+
end
|