source: trunk/python/asaplinefind.py@ 917

Last change on this file since 917 was 907, checked in by vor010, 19 years ago

LineFinder & auto_poly_baseline: a support of
new scantable format has been added. Now findLines accept a mask and edge
parameters, which can therefore be different for different rows. Constructor
need now just a scan table. Boost types removed from STLineFinder. auto_poly_baseline can accept a nested tuple of edges, which would be interpreted as
different edge parameters for different IFs

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 5.2 KB
RevLine 
[297]1import _asap
2
3class linefinder:
4 """
5 The class for automated spectral line search in ASAP.
[370]6
7 Example:
8 fl=linefinder()
[907]9 fl.set_scan(sc)
[370]10 fl.set_options(threshold=3)
[907]11 nlines=fl.find_lines(edge=(50,0))
[370]12 if nlines!=0:
13 print "Found ",nlines," spectral lines"
14 print fl.get_ranges(False)
15 else:
16 print "No lines found!"
[516]17 sc2=sc.poly_baseline(fl.get_mask(),7)
[880]18
[370]19 The algorithm involves a simple threshold criterion. The line is
20 considered to be detected if a specified number of consequtive
21 channels (default is 3) is brighter (with respect to the current baseline
22 estimate) than the threshold times the noise level. This criterion is
23 applied in the iterative procedure updating baseline estimate and trying
24 reduced spectral resolutions to detect broad lines as well. The off-line
25 noise level is determined at each iteration as an average of 80% of the
26 lowest variances across the spectrum (i.e. histogram equalization is
27 used to avoid missing weak lines if strong ones are present). For
[880]28 bad baseline shapes it is recommended to increase the threshold and
[370]29 possibly switch the averaging option off (see set_options) to
30 detect strong lines only, fit a high order baseline and repeat the line
[880]31 search.
[370]32
[297]33 """
34
35 def __init__(self):
[880]36 """
37 Create a line finder object.
38 """
39 self.finder = _asap.linefinder()
40 return
[297]41
[369]42 def set_options(self,threshold=1.7320508075688772,min_nchan=3,
43 avg_limit=8,box_size=0.2):
[880]44 """
45 Set the parameters of the algorithm
46 Parameters:
47 threshold a single channel S/N ratio above which the
48 channel is considered to be a detection
49 Default is sqrt(3), which together with
50 min_nchan=3 gives a 3-sigma criterion
51 min_nchan a minimal number of consequtive channels,
[369]52 which should satisfy a threshold criterion to
[880]53 be a detection. Default is 3.
54 avg_limit A number of consequtive channels not greater than
55 this parameter can be averaged to search for
56 broad lines. Default is 8.
57 box_size A running mean box size specified as a fraction
[369]58 of the total spectrum length. Default is 1/5
[880]59 Note: For bad baselines threshold should be increased,
60 and avg_limit decreased (or even switched off completely by
61 setting this parameter to 1) to avoid detecting baseline
62 undulations instead of real lines.
[369]63 """
64 self.finder.setoptions(threshold,min_nchan,avg_limit,box_size)
[880]65 return
66
[907]67 def set_scan(self, scan):
[297]68 """
[880]69 Set the 'data' (scantable) to work with.
70 Parameters:
71 scan: a scantable
[907]72 """
73 if not scan:
74 raise RuntimeError, 'Please give a correct scan'
75 return
76 def find_lines(self,nRow=0,mask=None,edge=(0,0)):
77 """
78 Search for spectral lines in the scan assigned in set_scan.
79 Parameters:
80 nRow: a row in the scantable to work with
81 mask: an optional mask (e.g. retreived from scantable)
82 edge: an optional number of channels to drop at
83 the edge of the spectrum. If only one value is
[880]84 specified, the same number will be dropped from
85 both sides of the spectrum. Default is to keep
86 all channels
[907]87 A number of lines found will be returned
[880]88 """
89 if isinstance(edge,int):
90 edge=(edge,)
91
[516]92 from asap import _is_sequence_or_number as _is_valid
93
94 if not _is_valid(edge, int):
[522]95 raise RuntimeError, "Parameter 'edge' has to be an integer or \
96 a pair of integers specified as a tuple"
[516]97
[880]98 if len(edge)>2:
99 raise RuntimeError, "The edge parameter should have two \
[297]100 or less elements"
[880]101 if mask is None:
102 from numarray import ones
[907]103 return self.finder.findlines(ones(scan.nchan(nRow)),list(edge),nRow)
[880]104 else:
[907]105 return self.finder.setscan(mask,list(edge),nRow)
[297]106 def get_mask(self,invert=False):
[880]107 """
108 Get the mask to mask out all lines that have been found (default)
[297]109
[880]110 Parameters:
111 invert if True, only channels belong to lines will be unmasked
[297]112
[880]113 Note: all channels originally masked by the input mask or
114 dropped out by the edge parameter will still be excluded
115 regardless on the invert option
[297]116 """
[880]117 return self.finder.getmask(invert)
[297]118 def get_ranges(self,defunits=True):
[880]119 """
120 Get ranges (start and end channels or velocities) for all spectral
121 lines found.
[297]122
[880]123 Parameters:
124 defunits if True (default), the range will use the same units
125 as set for the scan (e.g. LSR velocity)
126 if False, the range will be expressed in channels
127 """
128 if (defunits):
129 return self.finder.getlineranges()
130 else:
131 return self.finder.getlinerangesinchannels()
Note: See TracBrowser for help on using the repository browser.