Skip to content

Commit f92a81c

Browse files
committed
Merge pull request #11 from radio-astro/usesfitsformat
Usesfitsformat
2 parents f811c85 + 0a7ea50 commit f92a81c

File tree

6 files changed

+107
-72
lines changed

6 files changed

+107
-72
lines changed

Sourcery/CHANGES.md

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
1-
##Current version: 0.2.8
1+
##Current version: 0.2.9
22

33

4-
##From version 0.2.7 to 0.2.8, the changes made were;
4+
##From version 0.2.8 to 0.2.9, the changes made were;
55

6-
#### Threshold for local variance is 0.8 not 0.4. The local and PSF correlation are computed inside reliability script to solve assigning tags to wrong sources.
6+
#### Shapes are corrected: sourcery able to assign pnt and Gau appropriately, and uses DC_Maj/Min as a model and Maj/Min for reliability computation.
7+
#### The flux estimations are corrected. Uses masked image to create islands and the actual image for detection (model fitting)
8+
#### Takes the radius of sources to exclude inside the reliability script (previously it was done inside main-- had problems)
9+
#### Has an option to remove sources with correlation < 0.002 and reliability > 0.60

Sourcery/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
__version__ = "0.2.8"
1+
__version__ = "0.2.9"

Sourcery/config.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
"do_psf_corr": true,
1010
"do_local_var": true,
1111
"do_nearsources":false,
12+
"reset_rel": false,
1213
"increase_beam_cluster": true,
1314
"psf_corr_region" : 5,
1415
"local_var_region" : 10,

Sourcery/main.py

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -67,8 +67,9 @@ def main():
6767
default=True, help="Make reliability density plot. Default is True."
6868
" To disable add -dmp on the command line.")
6969

70-
add("-rel", "--rel-thresh", dest="rel_thresh", default=None, type=float,
71-
help= "Sets a reliability threshold. Default is None.")
70+
add("-drel", "--reset-rel", dest="reset_rel", action="store_true",
71+
default=False, help=" Assigns R=0 for sources with cf < 0.002 and"
72+
"R > 0.60.")
7273

7374
add("-beam", "--beam-cluster", dest="do_beam", default=False,
7475
action="store_true", help= "Increases the Gaussian groupings by 20 percent the"
@@ -82,7 +83,7 @@ def main():
8283
help="The area to compute the local variance, in beam sizes."
8384
" Default value is 10 beam sizes.")
8485

85-
add("-rel_rm", "--rel-sources-excl", dest="rel_src_excl",
86+
add("-rel_rm", "--rel-rmsrc", dest="rel_rmsrc",
8687
action="append", default=None, help="Delete sources within a radius;"
8788
" e.g ra, dec, radius (in degrees). For more than"
8889
" one region: ra1,dec1,radius1:ra2,dec2,radius2. Default is None.")
@@ -131,7 +132,7 @@ def main():
131132

132133
add("-phrm", "--phasecenter-remove", dest="phase_center_rm",
133134
type=float, default=None, help="The radius excluded from"
134-
" direction-dependent source selection. NB: this radius is wrt to"
135+
" direction-dependent source selection. NB: this radius is w.r.t to"
135136
" the phase center. Default is None.")
136137

137138
add('-jc', '--json-config', dest='config', default=None,
@@ -148,13 +149,9 @@ def main():
148149
pybdsm_opts = dict([ items.split("=") for items in args.to_pybdsm ] ) \
149150
if args.to_pybdsm else {}
150151

151-
if args.rel_src_excl:
152-
rel_rmsrc = args.rel_src_excl[0].split(':')
153-
else:
154-
rel_rmsrc = None
155-
156152
if not args.image:
157153
print("ATTENTION: No image provided. Aborting")
154+
158155

159156
# making outdirectory
160157
def get_prefix(prefix, imagename, outdir):
@@ -268,11 +265,11 @@ def get_prefix(prefix, imagename, outdir):
268265
args.source_finder, makeplots=args.do_relplots,
269266
do_psf_corr=args.add_psfcorr, do_local_var=args.add_locvar,
270267
psf_corr_region=psfregion, local_var_region=locregion,
271-
rel_excl_src=rel_rmsrc, pos_smooth=args.pos_smooth,
268+
rel_excl_src=args.rel_rmsrc, pos_smooth=args.pos_smooth,
272269
neg_smooth=args.neg_smooth, loglevel=args.log_level,
273270
thresh_isl=args.thresh_isl, thresh_pix=args.thresh_pix,
274271
neg_thresh_isl=args.neg_thresh_isl, neg_thresh_pix=
275-
args.neg_thresh_pix, prefix=prefix,
272+
args.neg_thresh_pix, prefix=prefix, reset_rel=args.reset_rel,
276273
do_nearsources=args.do_nearsources, increase_beam_cluster=
277274
args.do_beam, savemask_neg=args.savemask_neg,
278275
savemask_pos=args.savemask_pos, **pybdsm_opts)

Sourcery/reliabilityestimates.py

Lines changed: 73 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,10 @@ def __init__(self, imagename, psfname=None, sourcefinder_name='pybdsm',
2525
makeplots=True, do_psf_corr=True, do_local_var=True,
2626
psf_corr_region=5, local_var_region=10, rel_excl_src=None,
2727
pos_smooth=2, neg_smooth=2, loglevel=0, thresh_pix=5,
28-
thresh_isl=3, neg_thresh_isl=3, neg_thresh_pix=5,
29-
prefix=None, do_nearsources=False, increase_beam_cluster=False,
30-
savemask_pos=False, savemask_neg=False, **kw):
28+
thresh_isl=3, neg_thresh_isl=3, neg_thresh_pix=5, reset_rel=None,
29+
prefix=None, do_nearsources=False, savefits=False,
30+
increase_beam_cluster=False, savemask_pos=False, savemask_neg=False,
31+
**kw):
3132

3233
""" Takes in image and extracts sources and makes
3334
reliability estimations..
@@ -89,6 +90,10 @@ def __init__(self, imagename, psfname=None, sourcefinder_name='pybdsm',
8990
savefits: boolean. Default is False.
9091
If True a negative image is saved.
9192
93+
reset_rel: boolean. Default is False. If true then
94+
sources with correlation < 0.002 and rel >0.60
95+
have their reliabilities set to 0.
96+
9297
increase_beam_cluster: boolean, optional. If True, sources
9398
groupings will be increase by 20% the beam size. If False,
9499
the actual beam size will be used. Default is False.
@@ -137,7 +142,8 @@ def __init__(self, imagename, psfname=None, sourcefinder_name='pybdsm',
137142
self.do_psf_corr = do_psf_corr
138143
self.savemaskpos = savemask_pos
139144
self.savemaskneg = savemask_neg
140-
self.savefits = False
145+
self.savefits = savefits
146+
self.derel = reset_rel
141147

142148
if not self.psfname:
143149
self.log.info(" No psf provided, do_psf_corr is set to False.")
@@ -148,7 +154,7 @@ def __init__(self, imagename, psfname=None, sourcefinder_name='pybdsm',
148154
self.psfdata = utils.image_data(psfdata, prefix)
149155

150156
# computing negative noise
151-
self.noise = utils.negative_noise(self.imagedata, self.prefix) #here is 2X2 data here
157+
self.noise, self.mean = utils.negative_noise(self.imagedata, self.prefix) #here is 2X2 data here
152158

153159
self.log.info(" The negative noise is %e Jy/beam"%self.noise)
154160
if self.noise == 0:
@@ -163,7 +169,7 @@ def __init__(self, imagename, psfname=None, sourcefinder_name='pybdsm',
163169

164170
negativedata = utils.invert_image(
165171
self.imagename, self.imagedata,
166-
self.header, self.negimage)
172+
self.header, self.negimage, prefix)
167173
self.negimage2by2 = numpy.array(utils.image_data(negativedata, prefix),
168174
dtype=numpy.float32)
169175
self.negativedata = numpy.array(negativedata, numpy.float32)
@@ -178,12 +184,7 @@ def __init__(self, imagename, psfname=None, sourcefinder_name='pybdsm',
178184
self.radiusrm = rel_excl_src
179185
self.do_beam = increase_beam_cluster
180186

181-
182-
# conversion
183-
self.d2r = math.pi/180.0
184-
self.r2d = 180.0/math.pi
185-
186-
beam_pix = int(round(self.bmaj * self.r2d/self.pixelsize))
187+
beam_pix = int(round(numpy.rad2deg(self.bmaj)/self.pixelsize))
187188
self.locstep = self.localstep * beam_pix
188189
self.cfstep = self.corrstep * beam_pix
189190
self.bmin, self.bpa = self.header["BMIN"], self.header["BPA"]
@@ -206,14 +207,16 @@ def __init__(self, imagename, psfname=None, sourcefinder_name='pybdsm',
206207
self.opts_neg["thresh_isl"] = self.neg_thresh_isl
207208
self.opts_neg["thresh_pix"] = self.neg_thresh_pix
208209

209-
210+
210211
def source_finder(self, image=None, imagedata=None, thresh=None, prefix=None,
211212
noise=None, output=None, savemask=None, **kw):
212213

213214
ext = utils.fits_ext(image)
214215
tpos = tempfile.NamedTemporaryFile(suffix="."+ext, dir=".")
215216
tpos.flush()
216-
217+
kwards = {}
218+
#kw.update(kwards)
219+
217220
# data smoothing
218221
mask, noise = utils.thresh_mask(image,
219222
imagedata, tpos.name, hdr=self.header,
@@ -224,24 +227,29 @@ def source_finder(self, image=None, imagedata=None, thresh=None, prefix=None,
224227
boundary = numpy.array([self.locstep, self.cfstep])
225228
trim_box = (boundary.max(), naxis - boundary.max(),
226229
boundary.max(), naxis - boundary.max())
227-
230+
231+
# using the masked image for forming islands
232+
kwards["detection_image"] = tpos.name
233+
kw.update(kwards)
234+
228235
# source extraction
229236
utils.sources_extraction(
230-
image=tpos.name, output=output,
231-
sourcefinder_name=self.sourcefinder_name,
232-
blank_limit=self.noise/1000.0, trim_box=trim_box, prefix=self.prefix,
233-
**kw)
237+
image=image, output=output,
238+
sourcefinder_name=self.sourcefinder_name,
239+
blank_limit=self.noise/1.0e5, trim_box=trim_box,
240+
prefix=self.prefix, **kw)
234241
tpos.close()
235242

236243

237244
def remove_sources_within(self, model):
238245

239246
sources = model.sources
240-
for i in range(len(self.radiusrm)):
241-
ra, dec, tolerance = self.radiusrm[i].split(",")
242-
ra_r = float(ra) * self.d2r
243-
dec_r = float(dec) * self.d2r
244-
tolerance_r = float(tolerance) * self.d2r
247+
rel_remove = self.radiusrm[0].split(":")
248+
for i in range(len(rel_remove)):
249+
ra, dec, tolerance = rel_remove[i].split(",")
250+
ra_r = numpy.deg2rad(float(ra))
251+
dec_r = numpy.deg2rad(float(dec))
252+
tolerance_r = numpy.deg2rad(float(tolerance))
245253
within = model.getSourcesNear(ra_r, dec_r, tolerance_r)
246254
for src in sorted(sources):
247255
if src in within:
@@ -255,40 +263,45 @@ def params(self, modelfits, data_image):
255263
data = pyfits.open(modelfits)[1].data
256264
tfile = tempfile.NamedTemporaryFile(suffix=".txt")
257265
tfile.flush()
266+
258267
# writes a catalogue in a temporaty txt file
259-
260268
with open(tfile.name, "w") as std:
261-
std.write("#format:name ra_d dec_d i emaj_r emin_r pa_d\n")
269+
std.write("#format:name ra_rad dec_rad i emaj_r emin_r pa_r\n")
262270

263271
model = Tigger.load(tfile.name) # open a tmp. file
264272

265273
peak, total, area, loc, corr = [], [], [], [], []
266274
for i in range(len(data)):
267275
flux = data["Total_flux"][i]
268-
emaj, emin = data["Maj"][i], data["Min"][i]
276+
dc_emaj, dc_emin = data["DC_Maj"][i], data["DC_Min"][i]
269277
ra, dec = data["RA"][i], data["DEC"][i]
270-
pa = data["PA"][i]
278+
pa = data["DC_PA"][i]
271279
name = "SRC%d"%i
280+
peak_flux = data["Peak_flux"][i]
272281

273-
pos = [self.wcs.wcs2pix(*(ra, dec))][0] #deg to pixel
274-
275-
posrd = ModelClasses.Position(ra*self.d2r, dec*self.d2r)
282+
posrd = ModelClasses.Position(numpy.deg2rad(ra), numpy.deg2rad(dec))
276283
flux_I = ModelClasses.Polarization(flux, 0, 0, 0)
277-
shape = ModelClasses.Gaussian(emaj*self.d2r, emin*self.d2r, pa*self.d2r)
284+
if dc_emaj == 0 and dc_emin == 0:
285+
shape = None
286+
else:
287+
shape = ModelClasses.Gaussian(numpy.deg2rad(dc_emaj), numpy.deg2rad(dc_emin),
288+
numpy.deg2rad(pa))
289+
278290
srs = SkyModel.Source(name, posrd, flux_I, shape=shape)
279-
291+
292+
# using convolved maj and min for reliability estimate
293+
emaj, emin = data["Maj"][i], data["Min"][i]
294+
280295
# area: find ex and ey if are 0 assign beam size
281296
if emaj or emin == 0:
282-
srcarea = math.pi * (self.bmaj * self.r2d) * pow(3600.0,-2) *\
283-
(self.bmin * self.r2d)
297+
srcarea = math.pi * (numpy.rad2deg(self.bmaj)) * pow(3600.0, 2) *\
298+
(numpy.rad2deg(self.bmin))
284299
if emaj and emin > 0:
285-
srcarea = emaj * emin * math.pi * pow(3600.0,-2)
300+
srcarea = emaj * emin * math.pi * pow(3600.0, 2) # arcsecond
286301

287-
288-
peak_flux = data["Peak_flux"][i]
289-
290302
# only accepts sources with flux > 0 and not nan RA and DEC
291303
# and local variance
304+
pos = [self.wcs.wcs2pix(*(ra, dec))][0] #positions from deg to pixel
292305
if flux > 0 and peak_flux > 0 and not math.isnan(float(ra))\
293306
and not math.isnan(float(dec)):
294307

@@ -305,6 +318,9 @@ def params(self, modelfits, data_image):
305318
cf = (numpy.diag((numpy.rot90(c_region))**2)
306319
.sum())**0.5/2**0.5
307320
srs.setAttribute("cf", cf)
321+
#srs.setAttribute("ex", emaj)
322+
#srs.setAttribute("ey", emin)
323+
#srs.setAttribute("I_err", data["E_Total_flux"][i])
308324
corr.append(cf)
309325
model.sources.append(srs)
310326
peak.append(peak_flux)
@@ -313,6 +329,9 @@ def params(self, modelfits, data_image):
313329
loc.append(local)
314330
else:
315331
model.sources.append(srs)
332+
#srs.setAttribute("ex", emaj)
333+
#srs.setAttribute("ey", emin)
334+
#srs.setAttribute("I_err", data["E_Total_flux"][i])
316335
peak.append(peak_flux)
317336
total.append(flux)
318337
area.append(srcarea)
@@ -334,7 +353,6 @@ def params(self, modelfits, data_image):
334353
nsrc = len(model.sources)
335354
out = numpy.zeros([nsrc, len(labels)])
336355

337-
338356
# returning parameters
339357
for i, src in enumerate(model.sources):
340358

@@ -376,7 +394,6 @@ def params(self, modelfits, data_image):
376394
return model, numpy.log10(output), labels
377395

378396

379-
380397
def get_reliability(self):
381398

382399

@@ -399,7 +416,7 @@ def get_reliability(self):
399416

400417
self.log.info(" Source Finder completed successfully ")
401418
if not self.savefits:
402-
self.log.info("Deleting the negative image.")
419+
self.log.info(" Deleting the negative image.")
403420
os.system("rm -r %s"%self.negimage)
404421

405422

@@ -416,19 +433,20 @@ def get_reliability(self):
416433
cov = numpy.zeros([nplanes, nplanes])
417434
nnsrc = len(negative)
418435
npsrc = len(positive)
419-
436+
437+
self.log.info(" There are %d positive and %d negtive detections "%(npsrc, nnsrc))
438+
420439
if nnsrc == 0 or npsrc ==0:
421-
self.log.info("The resulting array has length of 0 thus cannot compute"
440+
self.log.error("The resulting array has length of 0 thus cannot compute"
422441
" the reliability. Aborting.")
423-
self.log.info(" There are %s positive detections "%npsrc)
424-
self.log.info(" There are %s negative detections "%nnsrc)
425442

426443
self.log.info(" Computing the reliabilities ")
427444
for i in range(nplanes):
428445
for j in range(nplanes):
429446
if i == j:
430447
cov[i, j] = bandwidth[i]*((4.0/((nplanes+2)*
431448
nnsrc))**(1.0/(nplanes+4.0)))
449+
self.log.info("The resulting covariance matrix is %r"%cov)
432450

433451
pcov = utils.gaussian_kde_set_covariance(positive.T, cov)
434452
ncov = utils.gaussian_kde_set_covariance(negative.T, cov)
@@ -442,7 +460,15 @@ def get_reliability(self):
442460
for src, rf in zip(pmodel.sources, rel):
443461
src.setAttribute("rel", rf)
444462
self.log.info(" Saved the reliabilities values.")
445-
463+
464+
# remove sources with poor correlation and high reliability,
465+
# the values are currently arbitrary
466+
if self.do_psf_corr and self.derel:
467+
for s in pmodel.sources:
468+
cf, r = s.cf, s.rel
469+
if cf < 0.002 and r > 0.60:
470+
s.rel = 0.0
471+
446472
if self.makeplots:
447473
savefig = self.prefix + "_planes.png"
448474
utils.plot(positive, negative, rel=rel, labels=labels,

0 commit comments

Comments
 (0)