aboutsummaryrefslogtreecommitdiff
path: root/noao/imred/crutil/src/t_cosmicrays.x
blob: fa68a39db58aa7b46fe7b0b1066ff98f50ef0ffa (plain) (blame)
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
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
include	<error.h>
include <imhdr.h>
include <imset.h>
include	<math/gsurfit.h>
include	<gset.h>
include	<pkg/gtools.h>
include	"crlist.h"

# T_COSMICRAYS -- Detect and remove cosmic rays in images.
# A list of images is examined for cosmic rays which are then replaced
# by values from neighboring pixels.  The output image may be the same
# as the input image.  This is the top level procedure which manages
# the input and output image data.  The actual algorithm for detecting
# cosmic rays is in CR_FIND.

procedure t_cosmicrays ()

int	list1			# List of input images to be cleaned
int	list2			# List of output images
int	list3			# List of output bad pixel files
real	threshold		# Detection threshold
real	fluxratio		# Luminosity boundary for stars
int	npasses			# Number of cleaning passes
int	szwin			# Size of detection window
bool	train			# Use training objects?
pointer	savefile		# Save file for training objects
bool	interactive		# Examine cosmic ray parameters?
char	ans			# Answer to interactive query

int	nc, nl, c, c1, c2, l, l1, l2, szhwin, szwin2
int	i, j, k, m, ncr, ncrlast, nreplaced, flag
pointer	sp, input, output, badpix, str, gp, gt, im, in, out
pointer	x, y, z, w, sf1, sf2, cr, data, ptr

bool	clgetb(), streq(), strne()
char	clgetc()
int	imtopenp(), imtlen(), imtgetim(), clpopnu(), clgfil(), clgeti()
real	clgetr()
pointer	immap(), impl2r(), imgs2r(), gopen(), gt_init()
errchk	immap, impl2r, imgs2r
errchk	cr_find, cr_examine, cr_replace, cr_plot, cr_crmask

begin
	call smark (sp)
	call salloc (input, SZ_FNAME, TY_CHAR)
	call salloc (output, SZ_FNAME, TY_CHAR)
	call salloc (badpix, SZ_FNAME, TY_CHAR)
	call salloc (savefile, SZ_FNAME, TY_CHAR)
	call salloc (str, SZ_LINE, TY_CHAR)

	# Get the task parameters.  Check that the number of output images
	# is either zero, in which case the cosmic rays will be removed
	# in place, or equal to the number of input images.

	list1 = imtopenp ("input")
	list2 = imtopenp ("output")
	i = imtlen (list1)
	j = imtlen (list2)
	if (j > 0 && j != i)
	    call error (0, "Input and output image lists do not match")

	list3 = clpopnu ("crmasks")
	threshold = clgetr ("threshold")
	fluxratio = clgetr ("fluxratio")
	npasses = clgeti ("npasses")
	szwin = clgeti ("window")
	train = clgetb ("train")
	call clgstr ("savefile", Memc[savefile], SZ_FNAME)
	interactive = clgetb ("interactive")
	call clpstr ("answer", "yes")
	ans = 'y'

	# Set up the graphics.
	call clgstr ("graphics", Memc[str], SZ_LINE)
	if (interactive) {
	    gp = gopen (Memc[str], NEW_FILE+AW_DEFER, STDGRAPH)
	    gt = gt_init()
	    call gt_sets (gt, GTTYPE, "mark")
	    call gt_sets (gt, GTXTRAN, "log")
	    call gt_setr (gt, GTXMIN, 10.)
	    call gt_setr (gt, GTYMIN, 0.)
	    call gt_sets (gt, GTTITLE, "Parameters of cosmic rays candidates")
	    call gt_sets (gt, GTXLABEL, "Flux")
	    call gt_sets (gt, GTYLABEL, "Flux Ratio")
	}

	# Set up surface fitting.  The background points are placed together
	# at the beginning of the arrays.  There are two surface pointers,
	# one for using the fast refit if there are no points excluded and
	# one for doing a full fit with points excluded.

	szhwin = szwin / 2
	szwin2 = szwin * szwin
	call salloc (data, szwin, TY_INT)
	call salloc (x, szwin2, TY_REAL)
	call salloc (y, szwin2, TY_REAL)
	call salloc (z, szwin2, TY_REAL)
	call salloc (w, szwin2, TY_REAL)

	k = 0
	do i = 1, szwin {
	    Memr[x+k] = i
	    Memr[y+k] = 1
	    k = k + 1
	}
	do i = 2, szwin {
	    Memr[x+k] = szwin
	    Memr[y+k] = i
	    k = k + 1
	}
	do i = szwin-1, 1, -1 {
	    Memr[x+k] = i
	    Memr[y+k] = szwin
	    k = k + 1
	}
	do i = szwin-1, 2, -1 {
	    Memr[x+k] = 1
	    Memr[y+k] = i
	    k = k + 1
	}
	do i = 2, szwin-1 {
	    do j = 2, szwin-1 {
	        Memr[x+k] = j
	        Memr[y+k] = i
	        k = k + 1
	    }
	}
	call aclrr (Memr[z], szwin2)
	call amovkr (1., Memr[w], 4*szwin-4)
	call gsinit (sf1, GS_POLYNOMIAL, 2, 2, NO, 1., real(szwin),
	    1., real(szwin))
	call gsinit (sf2, GS_POLYNOMIAL, 2, 2, NO, 1., real(szwin),
	    1., real(szwin))
	call gsfit (sf1, Memr[x], Memr[y], Memr[z], Memr[w], 4*szwin-4,
	    WTS_USER, j)

	# Process each input image.  Either work in place or create a
	# new output image.  If an error mapping the images occurs
	# issue a warning and go on to the next input image.

	while (imtgetim (list1, Memc[input], SZ_FNAME) != EOF) {
	    if (imtgetim (list2, Memc[output], SZ_FNAME) == EOF)
		call strcpy (Memc[input], Memc[output], SZ_FNAME)
	    if (clgfil (list3, Memc[badpix], SZ_FNAME) == EOF)
		Memc[badpix] = EOS

	    iferr {
		in = NULL
		out = NULL
		cr = NULL

		# Map the input image.  If the output image is
		# the same as the input image work in place.
		# Initialize IMIO to use a scrolling buffer of lines.

	        if (streq (Memc[input], Memc[output])) {
	            im = immap (Memc[input], READ_WRITE, 0)
		} else
		    im = immap (Memc[input], READ_ONLY, 0)
		in = im

	        nc = IM_LEN(in,1)
	        nl = IM_LEN(in,2)
	        if ((nl < szwin) || (nc < szwin))
	            call error (0, "Image size is too small")
	        call imseti (in, IM_NBUFS, szwin)
	        call imseti (in, IM_TYBNDRY, BT_NEAREST)
	        call imseti (in, IM_NBNDRYPIX, szhwin)

		# Open the output image if needed.
	        if (strne (Memc[input], Memc[output]))
		    im = immap (Memc[output], NEW_COPY, in)
		out = im

		# Open a cosmic ray list structure.
	        call cr_open (cr)
		ncrlast = 0
		nreplaced = 0

		# Now proceed through the image line by line, scrolling
		# the line buffers at each step.  If creating a new image
		# also write out each line as it is read.  A procedure is
		# called to find the cosmic ray candidates in the line
		# and add them to the list maintained by CRLIST.
		# Note that cosmic rays are not replaced at this point
		# in order to allow the user to modify the criteria for
		# a cosmic ray and review the results.

	        c1 = 1-szhwin
	        c2 = nc+szhwin
		do i = 1, szwin-1 
		    Memi[data+i] =
			imgs2r (in, c1, c2, i-szhwin, i-szhwin)

	        do l = 1, nl {
		    do i = 1, szwin-1
			Memi[data+i-1] = Memi[data+i]
		    Memi[data+szwin-1] =
			imgs2r (in, c1, c2, l+szhwin, l+szhwin)
		    if (out != in)
		        call amovr (Memr[Memi[data+szhwin]+szhwin],
			    Memr[impl2r(out,l)], nc)

	            call cr_find (cr, threshold, Memi[data],
		        c2-c1+1, szwin, c1, l,
		        sf1, sf2, Memr[x], Memr[y], Memr[z], Memr[w])
	        }
		if (interactive && train) {
		    call cr_train (cr, gp, gt, in, fluxratio, Memc[savefile])
		    train = false
		}
	        call cr_flags (cr, fluxratio)

		# If desired examine the cosmic ray list interactively.
	        if (interactive && ans != 'N') {
		    if (ans != 'Y') {
		        call eprintf ("%s - ")
		            call pargstr (Memc[input])
		        call flush (STDERR)
		        ans = clgetc ("answer")
		    }
		    if ((ans == 'Y') || (ans == 'y'))
	                call cr_examine (cr, gp, gt, in, fluxratio, 'r')
	        }

		# Now replace the selected cosmic rays in the output image.

		call imflush (out)
		call imseti (out, IM_ADVICE, RANDOM)
	        call cr_replace (cr, ncrlast, out, nreplaced)

		# Do additional passes through the data.  We work in place
		# in the output image.  Note that we only have to look in
		# the vicinity of replaced cosmic rays for secondary
		# events since we've already looked at every pixel once.
		# Instead of scrolling through the image we will extract
		# subrasters around each replaced cosmic ray.  However,
		# we use pointers into the subraster to maintain the same
		# format expected by CR_FIND.

	        if (npasses > 1) {
	            if (out != in)
	                call imunmap (out)
	            call imunmap (in)
		    im = immap (Memc[output], READ_WRITE, 0)
		    in = im
		    out = im
	            call imseti (in, IM_TYBNDRY, BT_NEAREST)
	            call imseti (in, IM_NBNDRYPIX, szhwin)

	            for (i=2; i<=npasses; i=i+1) {
			# Loop through each cosmic ray in the previous pass.
		        ncr = CR_NCR(cr)
		        do j = ncrlast+1, ncr {
			    flag = Memi[CR_FLAG(cr)+j-1]
			    if (flag==NO || flag==ALWAYSNO)
			        next
			    c = Memr[CR_COL(cr)+j-1]
			    l = Memr[CR_LINE(cr)+j-1]
			    c1 = max (1-szhwin, c - (szwin-1))
			    c2 = min (nc+szhwin, c + (szwin-1))
			    k = c2 - c1 + 1
			    l1 = max (1-szhwin, l - (szwin-1))
			    l2 = min (nl+szhwin, l + (szwin-1))

			    # Set the line pointers off an image section
			    # centered on a previously replaced cosmic ray.

			    ptr = imgs2r (in, c1, c2, l1, l2) - k

			    l1 = max (1, l - szhwin)
			    l2 = min (nl, l + szhwin)
			    do l = l1, l2 {
				do m = 1, szwin
				    Memi[data+m-1] = ptr + m * k
				ptr = ptr + k

	                        call cr_find ( cr, threshold, Memi[data],
				    k, szwin, c1, l, sf1, sf2,
				    Memr[x], Memr[y], Memr[z], Memr[w])
			    }
	                }
		        call cr_flags (cr, fluxratio)

			# Replace any new cosmic rays found.
	                call cr_replace (cr, ncr, in, nreplaced)
			ncrlast = ncr
		    }
	        }

		# Output header log, log, plot, and bad pixels.
		call sprintf (Memc[str], SZ_LINE,
		    "Threshold=%5.1f, fluxratio=%6.2f, removed=%d")
		    call pargr (threshold)
		    call pargr (fluxratio)
		    call pargi (nreplaced)
		call imastr (out, "crcor", Memc[str])

		call cr_plot (cr, in, fluxratio)
		call cr_crmask (cr, Memc[badpix], in)

	        call cr_close (cr)
	        if (out != in)
	            call imunmap (out)
	        call imunmap (in)
	    } then {
		# In case of error clean up and go on to the next image.
		if (in != NULL) {
		    if (out != NULL && out != in)
			call imunmap (out)
		    call imunmap (in)
		}
		if (cr != NULL)
		    call cr_close (cr)
		call erract (EA_WARN)
	    }
	}

	if (interactive) {
	    call gt_free (gt)
	    call gclose (gp)
	}
	call imtclose (list1)
	call imtclose (list2)
	call clpcls (list3)
	call gsfree (sf1)
	call gsfree (sf2)
	call sfree (sp)
end