forked from tammojan/facet-calibration
-
Notifications
You must be signed in to change notification settings - Fork 0
/
facet_utilities.py
216 lines (191 loc) · 6 KB
/
facet_utilities.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
# Module for globally useful utilities
import os
from subprocess import Popen
import logging
import time
from math import floor
import os
import resource
####
# Run parallel commands
def run(c,proceed=False,quiet=False):
'''
Run command c, throwing an exception if the return value is
non-zero (which means that the command failed). By default
(proceed==False) catches bad return values and raises an
exception.
'''
if not(quiet):
logging.debug('Running: '+c)
retval=os.system(c)
if retval!=0:
report='FAILED to run '+c+' -- return value was '+str(retval)
logging.error(report)
if not(proceed):
raise Exception(report)
return retval
class bg:
'''
Simple wrapper class around Popen that lets you run a number of
processes in the background and then wait for them to end
successfully. The list of processes is maintained internally so
you don't have to manage it yourself: just start by creating a
class instance. By default (proceed==False) catches bad return
values, kills all other background processes and raises an exception.
Optionally you can set a value maxp on creating the instance. If
you do this then run will block if you attempt to have more than
this number of processes running concurrently.
'''
def __init__(self,quiet=False,pollint=1,proceed=False,maxp=None):
self.pl=[]
self.quiet=quiet
self.pollint=pollint
self.proceed=proceed
self.maxp=maxp
def run(self,c):
if self.maxp:
if len(self.pl)>=self.maxp:
# too many processes running already. Wait till one finishes
self.wait(queuelen=self.maxp-1)
p=Popen('exec '+c,shell=True)
if not(self.quiet):
logging.debug('Process '+str(p.pid)+' started: '+c)
self.pl.append(p)
return p.pid
def wait(self,queuelen=0):
pl=self.pl
while len(pl)>queuelen:
for p in pl:
retval=p.poll()
if retval is not None:
pl.remove(p)
if retval==0:
if not(self.quiet):
logging.debug('Process '+str(p.pid)+' ended OK')
else:
report='Process '+str(p.pid)+' ended with return value '+str(retval)
logging.error(report)
if not(self.proceed):
for p2 in pl:
p2.kill()
raise Exception(report)
else:
print 'WARNING:',report
time.sleep(self.pollint)
self.pl=pl
return
####
# Coordinates
def angsep(ra1deg, dec1deg, ra2deg, dec2deg):
"""
Returns angular separation between two coordinates (all in degrees)
Input:
* ra1deg - RA of the first position
* dec1deg - dec of the first position
* ra2deg - RA of the second position
* dec2deg - dec of the second position
Output:
* Angular separation in degrees.
"""
ra1rad = ra1deg*numpy.pi/180.0
dec1rad = dec1deg*numpy.pi/180.0
ra2rad = ra2deg*numpy.pi/180.0
dec2rad = dec2deg*numpy.pi/180.0
# calculate scalar product for determination
# of angular separation
x = numpy.cos(ra1rad)*numpy.cos(dec1rad)*numpy.cos(ra2rad)*numpy.cos(dec2rad)
y = numpy.sin(ra1rad)*numpy.cos(dec1rad)*numpy.sin(ra2rad)*numpy.cos(dec2rad)
z = numpy.sin(dec1rad)*numpy.sin(dec2rad)
if x+y+z >= 1:
rad = 0
else:
rad=numpy.acos(x+y+z)
# Angular separation
deg = rad*180/numpy.pi
return deg
def ra_to_str(dra, ndec=2,delim=':'):
'''
converts a single decimal degrees ra to hh:mm:ss.s
'''
if delim == 'h':
delim1 = 'h'
delim2 = 'm'
else:
delim1 = delim
delim2 = delim
dra = dra/15.
dd = floor(dra)
dfrac = dra - dd
dmins = dfrac*60.
dm = floor(dmins)
dsec = (dmins-dm)*60.
if round(dsec, ndec) == 60.00:
dsec = 0.
dm += 1
if dm == 60.:
dm = 0.
dd += 1
sra = '%02d%s%02d%s%05.2f' %(dd,delim1,dm,delim2,dsec)
return sra
def dec_to_str(ddec,ndec=1,delim=':'):
'''
converts a single decimal degrees dec to dd:mm:ss.s
'''
if delim == 'd':
delim1 = 'd'
delim2 = 'm'
else:
delim1 = delim
delim2 = delim
if ddec < 0:
neg = True
else:
neg = False
ddec = abs(ddec)
dd = floor(ddec)
dfrac = ddec - dd
dmins = dfrac*60.
dm = floor(dmins)
dsec = (dmins-dm)*60.
if round(dsec, ndec) == 60.0:
dsec = 0.
dm += 1
if dm == 60.:
dm = 0.
dd += 1
if neg:
sdec = '-%02d%s%02d%s%04.1f' %(dd,delim1,dm,delim2,dsec)
else:
sdec = '%02d%s%02d%s%04.1f' %(dd,delim1,dm,delim2,dsec)
return sdec
# Memory and CPU use for wsclean
def getcpu():
# check if there is a PBS NODEFILE
nodefile=os.environ.get('PBS_NODEFILE')
if nodefile is not None:
lines=open(nodefile).readlines()
return len(lines)
else:
# find total number of *physical* CPUs.
cpus=os.popen('lscpu').readlines()
for l in cpus:
bits=l.split(':')
if bits[0]=='Core(s) per socket':
cores=int(bits[1])
if bits[0]=='Socket(s)':
sockets=int(bits[1])
try:
ncpus=cores*sockets
except UnboundLocalError:
# we failed to get the info from lscpu for some reason, so just go with the number of cores
import multiprocessing
ncpus=multiprocessing.cpu_count()
return ncpus
def getmem():
# Torque puts the memory limit in the (unused) RLIMIT_DATA. If
# this is set, use it to work out how much RAM we have in total
limit=resource.getrlimit(resource.RLIMIT_DATA)[0]
if limit>0:
return limit*getcpu()
else:
return None