source: fact/tools/pyscripts/pyfact/cleaners.py@ 14912

Last change on this file since 14912 was 13226, checked in by neise, 13 years ago
corrected typo
  • Property svn:executable set to *
File size: 7.4 KB
Line 
1#!/usr/bin/python -tti
2#
3# Dominik Neise
4# TU Dortmund
5# March 2012
6import numpy as np
7import random
8from coor import Coordinator # class which prepares next neighbor dictionary
9
10# just a dummy callback function
11def _dummy( data, core_c, core, surv ):
12 pass
13
14class AmplitudeCleaner( object ):
15 """ Image Cleaning based on signal strength
16
17 signal strength is a very general term here
18 it could be:
19 * max amplitude
20 * integral
21 * max of sliding sum
22 * ...
23 The Cleaning procedure or algorith is based on the
24 3 step precedute on the diss of M.Gauk called 'absolute cleaning'
25 """
26
27 def __init__(self, coreTHR, edgeTHR=None):
28 """ initialize object
29
30 set the two needed thresholds
31 in case only one is given:
32 edgeTHR is assumen to be coreTHR/2.
33 """
34 self.coreTHR = coreTHR
35 if edgeTHR==None:
36 self.edgeTHR = coreTHR/2.
37 else:
38 self.edgeTHR = edgeTHR
39
40 self.return_bool_mask = True # default value!
41
42 # init coordinator
43 self.coordinator = Coordinator()
44 # retrieve next neighbor dict
45 self.nn = self.coordinator.nn
46
47 def __call__( self, data, return_bool_mask=None , callback=_dummy ):
48 """ compute cleaned image
49
50 the return value might be:
51 np.array of same shape as data (dtype=bool)
52 or
53 an np.array (dtype=int), which lengths is the number of
54 pixel which survived the cleaning, and which contains the CHIDs
55 of these survivors
56
57 the default is to return the bool array
58 but if you set it once, differently, eg like this:
59 myAmplitudeCleaner.return_bool_mask = False
60 or like
61 myAmplitudeCleaner( mydata, False)
62
63 it will be stored, until you change it again...
64 """
65 #shortcuts
66 coreTHR = self.coreTHR
67 edgeTHR = self.edgeTHR
68 nn = self.nn
69
70 # once set, never forget :-)
71 if return_bool_mask != None:
72 self.return_bool_mask = return_bool_mask
73 return_bool_mask = self.return_bool_mask
74
75 # these will hold the outcome of..
76 core_c = np.zeros( len(data), dtype=bool ) # ... step 1
77 core = np.zeros( len(data), dtype=bool ) # ... step 2
78 surv = np.zeros( len(data), dtype=bool ) # ... step 3
79 # It could be done in one variable, but for debugging and simplicity,
80 # I use more ...
81
82 # this is Gauks step 1
83 core_c = data > coreTHR
84 # loop over all candidates and check if it has a next neighbor core pixel
85
86 for c in np.where(core_c)[0]:
87 # loop over all n'eighbors of c'andidate
88 for n in nn[c]:
89 # if c has a neighbor, beeing also a candidate
90 # then c is definitely a core.
91 # Note: DN 13.03.12
92 # actually the neighbor is also now found to be core pixel,
93 # and still this knowledge is thrown away and later this
94 # neighbor itself is treated again as a c'andidate.
95 # this should be improved.
96 if core_c[n]:
97 core[c]=True
98 break
99 # at this moment step 2 is done
100
101 # start of step 3.
102 # every core pixel is automaticaly a survivor, --> copy it
103 surv = core.copy()
104 for c in np.where(core)[0]:
105 for n in nn[c]:
106 # if neighbor is a core pixel, then do nothing
107 if core[n]:
108 pass
109 # if neighbor is over edgeTHR, it is lucky and survived.
110 elif data[n] > edgeTHR:
111 surv[n] = True
112
113
114 # calculate number of islands
115 surv_id = np.where(surv)[0]
116 # make a copy of survivors:
117 self.surv_copy = list(surv_id.copy())
118 surv_copy = self.surv_copy
119 # the first survivor belongs to the first island, by definition
120 self.islands = []
121 islands = self.islands
122 if len(surv_copy) > 0:
123 islands.append([surv_copy[0]])
124 del surv_copy[0]
125 nn_found = True
126 while len(surv_copy) > 0:
127 if nn_found:
128 nn_found = False
129 for i in islands[-1]:
130 #print 'i:',i
131 #print 'nn[i]:', nn[i]
132 #print 'type(nn[i]):', type(nn[i])
133 for n in nn[i]:
134 if n in surv_copy:
135 del surv_copy[surv_copy.index(n)]
136 islands[-1].append(n)
137 nn_found = True
138 #print 'islands'
139 #print islands, len(islands)
140 #print 'surv_copy'
141 #print surv_copy, len(surv_copy)
142 #print '*'*80
143 #print 'END of for i in islands[-1]:'
144 #print '*'*80
145
146 else:
147 islands.append( [ surv_copy[0] ])
148 del surv_copy[0]
149 nn_found = True
150
151 #print 'cleaner found' ,len(islands), 'islands'
152
153 callback( data, core_c, core, surv)
154
155 if return_bool_mask:
156 return surv
157 else:
158 return np.where(surv)[0]
159
160
161 def info(self):
162 """ print Cleaner Informatio
163
164 """
165 print 'coreTHR: ', self.coreTHR
166 print 'edgeTHR: ', self.edgeTHR
167 print 'return_bool_mask:', self.return_bool_mask
168
169def _test_callback( data, core_c, core, surv ):
170 """ test callback functionality of AmplitudeCleaner"""
171 print 'core_c', np.where(core_c)[0], '<--', core_c.sum()
172 print 'core', np.where(core)[0], '<--', core.sum()
173 print 'surv', np.where(surv)[0], '<--', surv.sum()
174 print 'data', '*'*60
175 print data
176
177
178def _test_cleaner():
179 """ test for class AmplitudeCleaner"""
180 from plotters import CamPlotter
181 NPIX = 1440
182 SIGMA = 1
183
184 CORE_THR = 45
185 EDGE_THR = 18
186
187 harvey_keitel = AmplitudeCleaner( CORE_THR, EDGE_THR)
188 harvey_keitel.info()
189 # if you wonder why the cleaner object is called is it is:
190 # http://www.youtube.com/watch?v=pf-Amvro2SY
191
192 nn = Coordinator().nn
193
194 testdata = np.zeros( NPIX )
195 #add some noise
196 testdata += 3
197
198 # 'make' 3 doubleflowers
199 cores = []
200 for i in range(3):
201 cores.append( random.randint(0, NPIX-1) )
202 nene = nn[ cores[-1] ] # shortcut
203 luckynn = random.sample( nene, 1)[0] # shortcut
204 #print nene
205 #print luckynn
206 cores.append( luckynn )
207 edges = []
208 for c in cores:
209 for n in nn[c]:
210 if n not in cores:
211 edges.append(n)
212
213 # add those doubleflowers to the testdata
214 for c in cores:
215 testdata[c] += 1.2*CORE_THR
216 for e in edges:
217 testdata[e] += 1.2*EDGE_THR
218
219
220 #cleaning_mask = harvey_keitel(testdata, callback=_test_callback)
221 cleaning_mask = harvey_keitel(testdata)
222
223 plotall = CamPlotter('all')
224 plotclean = CamPlotter('cleaned')
225
226 plotall(testdata)
227 plotclean(testdata, cleaning_mask)
228
229
230
231if __name__ == '__main__':
232 """ tests """
233
234 _test_cleaner()
Note: See TracBrowser for help on using the repository browser.