lsst.meas.algorithms  13.0-18-gc4ad4228
Interp.cc
Go to the documentation of this file.
1 // -*- LSST-C++ -*-
2 
3 /*
4  * LSST Data Management System
5  * Copyright 2008-2015 LSST Corporation.
6  *
7  * This product includes software developed by the
8  * LSST Project (http://www.lsst.org/).
9  *
10  * This program is free software: you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation, either version 3 of the License, or
13  * (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the LSST License Statement and
21  * the GNU General Public License along with this program. If not,
22  * see <http://www.lsstcorp.org/LegalNotices/>.
23  */
24 
32 #include <stdexcept>
33 #include <algorithm>
34 #include <cassert>
35 #include <string>
36 #include <typeinfo>
37 #include <limits>
38 #include "boost/format.hpp"
39 
40 #include "lsst/afw/geom.h"
41 #include "lsst/pex/exceptions.h"
42 #include "lsst/afw/image/MaskedImage.h"
44 
45 namespace lsst {
46 namespace meas {
47 namespace algorithms {
48 
49 namespace image = lsst::afw::image;
50 namespace geom = lsst::afw::geom;
51 
52 typedef std::vector<Defect::Ptr>::const_iterator DefectCIter;
53 
54 /************************************************************************************************************/
55 /*
56  * Classify an vector of Defect::Ptr for the given row, returning a vector of 1-D
57  * Defects (i.e. y0 == y1). In general we can merge in saturated pixels at
58  * this step, although we don't currently do so.
59  *
60  * See comment above do_defects for a description of how to interpret DefectType
61  */
62 static std::vector<Defect::Ptr>
63 classify_defects(std::vector<Defect::Ptr> const & badList, // list of bad things
64  int const y, // the row to process
65  int const ncol, // number of columns in image
66  int = 0 // number of rows in image
67  ) {
68 
69  std::vector<Defect::Ptr> badList1D;
70 
71  for (DefectCIter begin = badList.begin(), end = badList.end(), bri = begin; bri != end; ++bri) {
72  Defect::Ptr defect = *bri;
73 
74  if (y < defect->getY0() || y > defect->getY1() || ncol < defect->getX0()) {
75  continue;
76  }
77 
78  int const x0 = defect->getX0();
79  int x1 = defect->getX1();
80  //
81  // Look for other defects that touch this one, and push them onto badList1d
82  //
83  for (++bri; bri != end; ++bri) {
84  defect = *bri;
85 
86  if (y < defect->getY0() || y > defect->getY1()) { // this defect doesn't concern this row
87  continue;
88  }
89  if (x1 < defect->getX0() - 1) { // no further defects can touch this one
90  --bri;
91  break;
92  }
93  if (defect->getX1() > x1) {
94  x1 = defect->getX1();
95  }
96  }
97 
98  int const nbad = x1 - x0 + 1;
99  assert(nbad >= 1);
100 
101  defect = Defect::Ptr(
102  new Defect(
103  geom::BoxI(
104  geom::Point2I(x0, y),
105  geom::Extent2I(nbad, 1)
106  )
107  )
108  );
109  badList1D.push_back(defect);
110 
111  if (bri == end) {
112  break;
113  }
114  }
115  //
116  // Now process our new list
117  //
118  for (DefectCIter begin = badList1D.begin(), end = badList1D.end(), bri = begin; bri != end; ++bri) {
119  Defect::Ptr defect = *bri;
120 
121  int const nbad = defect->getX1() - defect->getX0() + 1;
122  assert(nbad >= 1);
123 
124  if (defect->getX0() == 0) {
125  if (nbad >= Defect::WIDE_DEFECT) {
126  defect->classify(Defect::WIDE_LEFT, 03);
127  } else {
128  defect->classify(Defect::LEFT, 03 << nbad);
129  }
130  } else if (defect->getX0() == 1) { /* only second column is usable */
131  if (nbad >= Defect::WIDE_DEFECT) {
132  defect->classify(Defect::WIDE_NEAR_LEFT, (01 << 2) | 03);
133  } else {
134  defect->classify(Defect::NEAR_LEFT, (01 << (nbad + 2)) | 03);
135  }
136  } else if (defect->getX1() == ncol - 2) { /* use only penultimate column */
137  if (nbad >= Defect::WIDE_DEFECT) {
138  defect->classify(Defect::WIDE_NEAR_RIGHT, (03 << 2) | 02);
139  } else {
140  defect->classify(Defect::NEAR_RIGHT, (03 << (nbad + 2)) | 02);
141  }
142  } else if (defect->getX1() == ncol - 1) {
143  if (nbad >= Defect::WIDE_DEFECT) {
144  defect->classify(Defect::WIDE_RIGHT, 03);
145  } else {
146  defect->classify(Defect::RIGHT, 03 << nbad);
147  }
148  } else if (nbad >= Defect::WIDE_DEFECT) {
149  defect->classify(Defect::WIDE, (03 << 2) | 03);
150  } else {
151  defect->classify(Defect::MIDDLE, (03 << (nbad + 2)) | 03);
152  }
153 /*
154  * look for bad columns in regions that we'll get `good' values from.
155  *
156  * We know that no two Defects are adjacent.
157  */
158  int nshift = 0; // number of bits to shift to get to left edge of defect pattern
159  switch (defect->getPos()) {
160  case Defect::WIDE: // no bits
161  case Defect::WIDE_NEAR_LEFT: // are used to encode
162  case Defect::WIDE_NEAR_RIGHT: // the bad section of data
163  nshift = 0;
164  break;
165  default:
166  nshift = nbad;
167  break;
168  }
169 
170  if (bri != begin) {
171  Defect::Ptr const defect_m = *(bri - 1);
172  assert(defect_m->getX1() < defect->getX0());
173 
174  if (defect_m->getX1() == defect->getX0() - 2) {
175  defect->classify(defect->getPos(), (defect->getType() & ~(02 << (nshift + 2))));
176  }
177  }
178 
179  if (bri + 1 != end) {
180  Defect::Ptr const defect_p = *(bri + 1);
181 
182  if (defect->getX1() == defect_p->getX0() - 2) {
183  Defect::DefectPosition defectPos = defect->getPos();
184  if (defectPos == Defect::LEFT || defectPos == Defect::NEAR_LEFT) {
185  defect->classify(defect->getPos(), (defect->getType() & ~(02 << nshift)));
186  } else {
187  defect->classify(defectPos, (defect->getType() & ~01));
188  }
189  }
190  }
191  }
192 
193  return badList1D;
194 }
195 
196 /*****************************************************************************/
197 /*
198  * Interpolate over the defects in a given line of data. In the comments,
199  * a bad pixel is written as ., a good one as #, and unknown but non-interpolated pixels as ?.
200  *
201  * This may be mapped to an int by replacing # with 1 and . or ? with 0. So "##..##" would mean, "I have two
202  * adjacent bad pixels with 2 good neighbours to both the left and right", and have a defectType of 110011 or
203  * 063. This defect is in the middle of the chip, so has DefectPosition MIDDLE.
204  *
205  * The other options are LEFT, NEAR_LEFT, WIDE_NEAR_LEFT, and the corresponding RIGHT positions, and WIDE.
206  * LEFT are defects that touch the left side, and NEAR_LEFT ones that come within a pixel. WIDE are encoded
207  * omitting the .. so "##..................##" would be 1111 == 017 and WIDE.
208 
209  * The LEFT ones are actually a bit tricky as they'd have leading 0s, so they are inverted ("....##" is
210  * written as 110000 not 000011).
211  */
212 template<typename ImageT>
213 static void do_defects(std::vector<Defect::Ptr> const & badList, // list of bad things
214  int const y, // Row that we should fix
215  ImageT& data, // data to fix
216  typename ImageT::Pixel min, // minimum acceptable value
217  double fallbackValue, // Value to fallback to if all else fails
218  bool useFallbackValueAtEdge, // use fallbackValue at edge of chip?
219  int nUseInterp // no. of pixels to interpolate towards edge
220  )
221 {
222  typedef typename ImageT::Pixel ImagePixel;
223  ImagePixel out1_2, out1_1, out2_1, out2_2; // == out[badX1-2], ..., out[bad_x2+2]
224  ImagePixel val; // unpack a pixel value
225  //
226  // Get pointer to this row of data
227  //
228  int const ncol = data.getWidth();
229  typename ImageT::x_iterator out = data.row_begin(y);
230 
231  for (DefectCIter ptr = badList.begin(), end = badList.end(); ptr != end; ++ptr) {
232  Defect::Ptr const defect = *ptr;
233 
234  if (y < defect->getY0() || y > defect->getY1()) {
235  continue;
236  }
237 
238  int badX0 = defect->getX0();
239  int badX1 = defect->getX1();
240 
241  Defect::DefectPosition defectPos = defect->getPos();
242  unsigned int defectType = defect->getType();
243 
244  int nbad = badX1 - badX0 + 1;
245 
246  if (nbad > nUseInterp && useFallbackValueAtEdge) {
247  switch (defectPos) {
248  case Defect::LEFT:
249  case Defect::WIDE_LEFT:
250  assert(badX0 == 0);
251 
252  if (badX1 == ncol - 1) { // also RIGHT --- spans the entire image
253  for (int i = 0; i != ncol; ++i) {
254  out[i] = fallbackValue;
255  }
256  continue;
257  }
258 
259  for (; badX0 <= badX1 - nUseInterp; ++badX0) {
260  out[badX0] = fallbackValue;
261  }
262 
263  if (defectPos == Defect::LEFT) {
264  defectType >>= nbad; // we just want the last 2 bits
265  switch (defectType) {
266  case 01: defectType = 02; break;
267  case 03: defectType = 03; break;
268  default:
269  throw std::runtime_error(str(boost::format("Impossible value of defectType: 0%o") %
270  defectType));
271  }
272  }
273  nbad = badX1 - badX0 + 1;
274  defectType = (03 << (nbad + 2)) | defectType;
275  defectPos = (badX0 > 1) ? ((badX1 < ncol - 2) ? Defect::MIDDLE : Defect::NEAR_RIGHT) :
277  break;
278  case Defect::RIGHT:
279  case Defect::WIDE_RIGHT:
280  assert(badX1 == ncol - 1);
281  for (; badX1 >= badX0 + nUseInterp; --badX1) {
282  out[badX1] = fallbackValue;
283  }
284  nbad = badX1 - badX0 + 1;
285  defectType = (03 << (nbad + 2)) | 03;
286  defectPos = (badX1 < ncol - 2) ? Defect::MIDDLE : Defect::NEAR_RIGHT;
287  break;
288  default:
289  break;
290  }
291  }
292 
293  switch (defectPos) {
294  case Defect::LEFT:
295  assert(badX0 >= 0 && badX1 + 2 < ncol);
296 
297  out2_1 = out[badX1 + 1];
298  out2_2 = out[badX1 + 2];
299 
300  switch (defectType) {
301  case 02: /* .#?, <noise^2> = 0 */
302  val = 1.0000*out2_1;
303  out[badX1] = (val < min) ? out2_1 : val;
304 
305  break;
306  case 06: /* .##, <noise^2> = 0 */
307  val = 1.4288*out2_1 - 0.4288*out2_2;
308  out[badX1] = (val < min) ? out2_1 : val;
309 
310  break;
311  case 014: /* ..##, <noise^2> = 0 */
312  val = 1.0933*out2_1 - 0.0933*out2_2;
313  out[badX0] = (val < min) ? out2_1 : val;
314 
315  val = 1.4288*out2_1 - 0.4288*out2_2;
316  out[badX1] = (val < min) ? out2_1 : val;
317 
318  break;
319  case 04: /* ..#?, <noise^2> = 0 */
320  val = 1.000*out2_1;
321  out[badX0] = (val < min) ? out2_1 : val;
322  out[badX1] = (val < min) ? out2_1 : val;
323 
324  break;
325  case 030: /* ...##, <noise^2> = 0 */
326  val = 0.6968*out2_1 + 0.3032*out2_2;
327  out[badX0] = (val < min) ? out2_1 : val;
328 
329  val = 1.0933*out2_1 - 0.0933*out2_2;
330  out[badX1 - 1] = (val < min) ? out2_1 : val;
331 
332  val = 1.4288*out2_1 - 0.4288*out2_2;
333  out[badX1] = (val < min) ? out2_1 : val;
334 
335  break;
336  case 010: /* ...#?, <noise^2> = 0 */
337  val = 1.000*out2_1;
338 
339  out[badX0] = (val < min) ? out2_1 : val;
340  out[badX1 - 1] = (val < min) ? out2_1 : val;
341  out[badX1] = (val < min) ? out2_1 : val;
342 
343  break;
344  case 060: /* ....##, <noise^2> = 0 */
345  val = 0.5370*out2_1 + 0.4630*out2_2;
346  out[badX0] = (val < min) ? out2_1 : val;
347 
348  val = 0.6968*out2_1 + 0.3032*out2_2;
349  out[badX0 + 1] = (val < min) ? out2_1 : val;
350 
351  val = 1.0933*out2_1 - 0.0933*out2_2;
352  out[badX1 - 1] = (val < min) ? out2_1 : val;
353 
354  val = 1.4288*out2_1 - 0.4288*out2_2;
355  out[badX1] = (val < min) ? out2_1 : val;
356 
357  break;
358  case 020: /* ....#?, <noise^2> = 0 */
359  val = 1.0000*out2_1;
360 
361  out[badX0] = (val < min) ? out2_1 : val;
362  out[badX0 + 1] = (val < min) ? out2_1 : val;
363  out[badX1 - 1] = (val < min) ? out2_1 : val;
364  out[badX1] = (val < min) ? out2_1 : val;
365 
366  break;
367  case 0140: /* .....##, <noise^2> = 0 */
368  val = 0.5041*out2_1 + 0.4959*out2_2;
369  out[badX0] = (val < min) ? out2_1 : val;
370 
371  val = 0.5370*out2_1 + 0.4630*out2_2;
372  out[badX0 + 1] = (val < min) ? out2_1 : val;
373 
374  val = 0.6968*out2_1 + 0.3032*out2_2;
375  out[badX1 - 2] = (val < min) ? out2_1 : val;
376 
377  val = 1.0933*out2_1 - 0.0933*out2_2;
378  out[badX1 - 1] = (val < min) ? out2_1 : val;
379 
380  val = 1.4288*out2_1 - 0.4288*out2_2;
381  out[badX1] = (val < min) ? out2_1 : val;
382 
383  break;
384  case 040: /* .....#?, <noise^2> = 0 */
385  val = 1.0000*out2_1;
386  out[badX0] = (val < min) ? out2_1 : val;
387  out[badX0 + 1] = (val < min) ? out2_1 : val;
388  out[badX1 - 2] = (val < min) ? out2_1 : val;
389  out[badX1 - 1] = (val < min) ? out2_1 : val;
390  out[badX1] = (val < min) ? out2_1 : val;
391 
392  break;
393  case 0300: /* ......##, <noise^2> = 0 */
394  val = 0.5003*out2_1 + 0.4997*out2_2;
395  out[badX0] = (val < min) ? out2_1 : val;
396 
397  val = 0.5041*out2_1 + 0.4959*out2_2;
398  out[badX0 + 1] = (val < min) ? out2_1 : val;
399 
400  val = 0.5370*out2_1 + 0.4630*out2_2;
401  out[badX0 + 2] = (val < min) ? out2_1 : val;
402 
403  val = 0.6968*out2_1 + 0.3032*out2_2;
404  out[badX1 - 2] = (val < min) ? out2_1 : val;
405 
406  val = 1.0933*out2_1 - 0.0933*out2_2;
407  out[badX1 - 1] = (val < min) ? out2_1 : val;
408 
409  val = 1.4288*out2_1 - 0.4288*out2_2;
410  out[badX1] = (val < min) ? out2_1 : val;
411 
412  break;
413  case 0100: /* ......#?, <noise^2> = 0 */
414  val = 1.0000*out2_1;
415 
416  out[badX0] = (val < min) ? out2_1 : val;
417  out[badX0 + 1] = (val < min) ? out2_1 : val;
418  out[badX0 + 2] = (val < min) ? out2_1 : val;
419  out[badX1 - 2] = (val < min) ? out2_1 : val;
420  out[badX1 - 1] = (val < min) ? out2_1 : val;
421  out[badX1] = (val < min) ? out2_1 : val;
422 
423  break;
424  case 0600: /* .......##, <noise^2> = 0 */
425  val = 0.5000*out2_1 + 0.5000*out2_2;
426  out[badX0] = (val < min) ? out2_1 : val;
427 
428  val = 0.5003*out2_1 + 0.4997*out2_2;
429  out[badX0 + 1] = (val < min) ? out2_1 : val;
430 
431  val = 0.5041*out2_1 + 0.4959*out2_2;
432  out[badX0 + 2] = (val < min) ? out2_1 : val;
433 
434  val = 0.5370*out2_1 + 0.4630*out2_2;
435  out[badX1 - 3] = (val < min) ? out2_1 : val;
436 
437  val = 0.6968*out2_1 + 0.3032*out2_2;
438  out[badX1 - 2] = (val < min) ? out2_1 : val;
439 
440  val = 1.0933*out2_1 - 0.0933*out2_2;
441  out[badX1 - 1] = (val < min) ? out2_1 : val;
442 
443  val = 1.4288*out2_1 - 0.4288*out2_2;
444  out[badX1] = (val < min) ? out2_1 : val;
445 
446  break;
447  case 0200: /* .......#?, <noise^2> = 0 */
448  val = 1.0000*out2_1;
449  out[badX0] = (val < min) ? out2_1 : val;
450  out[badX0 + 1] = (val < min) ? out2_1 : val;
451  out[badX0 + 2] = (val < min) ? out2_1 : val;
452  out[badX1 - 3] = (val < min) ? out2_1 : val;
453  out[badX1 - 2] = (val < min) ? out2_1 : val;
454  out[badX1 - 1] = (val < min) ? out2_1 : val;
455  out[badX1] = (val < min) ? out2_1 : val;
456 
457  break;
458  case 01400: /* ........##, <noise^2> = 0 */
459  val = 0.5000*out2_1 + 0.5000*out2_2;
460  out[badX0] = (val < min) ? out2_1 : val;
461 
462  val = 0.5000*out2_1 + 0.5000*out2_2;
463  out[badX0 + 1] = (val < min) ? out2_1 : val;
464 
465  val = 0.5003*out2_1 + 0.4997*out2_2;
466  out[badX0 + 2] = (val < min) ? out2_1 : val;
467 
468  val = 0.5041*out2_1 + 0.4959*out2_2;
469  out[badX0 + 3] = (val < min) ? out2_1 : val;
470 
471  val = 0.5370*out2_1 + 0.4630*out2_2;
472  out[badX1 - 3] = (val < min) ? out2_1 : val;
473 
474  val = 0.6968*out2_1 + 0.3032*out2_2;
475  out[badX1 - 2] = (val < min) ? out2_1 : val;
476 
477  val = 1.0933*out2_1 - 0.0933*out2_2;
478  out[badX1 - 1] = (val < min) ? out2_1 : val;
479 
480  val = 1.4288*out2_1 - 0.4288*out2_2;
481  out[badX1] = (val < min) ? out2_1 : val;
482 
483  break;
484  case 0400: /* ........#?, <noise^2> = 0 */
485  val = 1.0000*out2_1;
486  out[badX0] = (val < min) ? out2_1 : val;
487  out[badX0 + 1] = (val < min) ? out2_1 : val;
488  out[badX0 + 2] = (val < min) ? out2_1 : val;
489  out[badX0 + 3] = (val < min) ? out2_1 : val;
490  out[badX1 - 3] = (val < min) ? out2_1 : val;
491  out[badX1 - 2] = (val < min) ? out2_1 : val;
492  out[badX1 - 1] = (val < min) ? out2_1 : val;
493  out[badX1] = (val < min) ? out2_1 : val;
494 
495  break;
496  case 03000: /* .........##, <noise^2> = 0 */
497  val = 0.5000*out2_1 + 0.5000*out2_2;
498  out[badX0] = (val < min) ? out2_1 : val;
499 
500  val = 0.5000*out2_1 + 0.5000*out2_2;
501  out[badX0 + 1] = (val < min) ? out2_1 : val;
502 
503  val = 0.5000*out2_1 + 0.5000*out2_2;
504  out[badX0 + 2] = (val < min) ? out2_1 : val;
505 
506  val = 0.5003*out2_1 + 0.4997*out2_2;
507  out[badX0 + 3] = (val < min) ? out2_1 : val;
508 
509  val = 0.5041*out2_1 + 0.4959*out2_2;
510  out[badX1 - 4] = (val < min) ? out2_1 : val;
511 
512  val = 0.5370*out2_1 + 0.4630*out2_2;
513  out[badX1 - 3] = (val < min) ? out2_1 : val;
514 
515  val = 0.6968*out2_1 + 0.3032*out2_2;
516  out[badX1 - 2] = (val < min) ? out2_1 : val;
517 
518  val = 1.0933*out2_1 - 0.0933*out2_2;
519  out[badX1 - 1] = (val < min) ? out2_1 : val;
520 
521  val = 1.4288*out2_1 - 0.4288*out2_2;
522  out[badX1] = (val < min) ? out2_1 : val;
523 
524  break;
525  case 01000: /* .........#?, <noise^2> = 0 */
526  val = 1.0000*out2_1;
527  out[badX0] = (val < min) ? out2_1 : val;
528  out[badX0 + 1] = (val < min) ? out2_1 : val;
529  out[badX0 + 2] = (val < min) ? out2_1 : val;
530  out[badX0 + 3] = (val < min) ? out2_1 : val;
531  out[badX1 - 4] = (val < min) ? out2_1 : val;
532  out[badX1 - 3] = (val < min) ? out2_1 : val;
533  out[badX1 - 2] = (val < min) ? out2_1 : val;
534  out[badX1 - 1] = (val < min) ? out2_1 : val;
535  out[badX1] = (val < min) ? out2_1 : val;
536 
537  break;
538  case 06000: /* ..........##, <noise^2> = 0 */
539  val = 0.5000*out2_1 + 0.5000*out2_2;
540  out[badX0] = (val < min) ? out2_1 : val;
541 
542  val = 0.5000*out2_1 + 0.5000*out2_2;
543  out[badX0 + 1] = (val < min) ? out2_1 : val;
544 
545  val = 0.5000*out2_1 + 0.5000*out2_2;
546  out[badX0 + 2] = (val < min) ? out2_1 : val;
547 
548  val = 0.5000*out2_1 + 0.5000*out2_2;
549  out[badX0 + 3] = (val < min) ? out2_1 : val;
550 
551  val = 0.5003*out2_1 + 0.4997*out2_2;
552  out[badX0 + 4] = (val < min) ? out2_1 : val;
553 
554  val = 0.5041*out2_1 + 0.4959*out2_2;
555  out[badX1 - 4] = (val < min) ? out2_1 : val;
556 
557  val = 0.5370*out2_1 + 0.4630*out2_2;
558  out[badX1 - 3] = (val < min) ? out2_1 : val;
559 
560  val = 0.6968*out2_1 + 0.3032*out2_2;
561  out[badX1 - 2] = (val < min) ? out2_1 : val;
562 
563  val = 1.0933*out2_1 - 0.0933*out2_2;
564  out[badX1 - 1] = (val < min) ? out2_1 : val;
565 
566  val = 1.4288*out2_1 - 0.4288*out2_2;
567  out[badX1] = (val < min) ? out2_1 : val;
568 
569  break;
570  case 02000: /* ..........#?, <noise^2> = 0 */
571  val = 1.0000*out2_1;
572 
573  out[badX0] = (val < min) ? out2_1 : val;
574  out[badX0 + 1] = (val < min) ? out2_1 : val;
575  out[badX0 + 2] = (val < min) ? out2_1 : val;
576  out[badX0 + 3] = (val < min) ? out2_1 : val;
577  out[badX0 + 4] = (val < min) ? out2_1 : val;
578  out[badX1 - 4] = (val < min) ? out2_1 : val;
579  out[badX1 - 3] = (val < min) ? out2_1 : val;
580  out[badX1 - 2] = (val < min) ? out2_1 : val;
581  out[badX1 - 1] = (val < min) ? out2_1 : val;
582  out[badX1] = (val < min) ? out2_1 : val;
583 
584  break;
585  default:
586  //shFatal("Unsupported defect type: LEFT 0%o", defectType);
587  break; /* NOTREACHED */
588  }
589  break;
590  case Defect::WIDE_LEFT:
591  assert(badX0 >= 0);
592  if (badX1 + 2 >= ncol) { /* left defect extends near
593  right edge of data! */
594  if (badX1 == ncol - 2) { /* one column remains */
595  val = out[ncol - 1];
596  } else {
597  val = fallbackValue; /* there is no information */
598  }
599  for (int j = badX0; j <= badX1; j++) {
600  out[j] = val;
601  }
602  break;
603  }
604  out2_1 = out[badX1 + 1];
605  out2_2 = out[badX1 + 2];
606 
607  switch (defectType) {
608  case 02: /* ?#., <noise^2> = 0 */
609  val = 1.0000*out2_1;
610  val = (val < min) ? out2_1 : val;
611 
612  for (int j = badX0; j <= badX1; j++) {
613  out[j] = val;
614  }
615  break;
616  case 03: /* ?##, <noise^2> = 0 */
617  val = 0.5000*out2_1 + 0.5000*out2_2;
618  if (val < min) {
619  val = out2_1;
620  }
621 
622  for (int j = badX0; j < badX1 - 5; j++) {
623  out[j] = val;
624  }
625 
626  val = 0.5003*out2_1 + 0.4997*out2_2;
627  out[badX1 - 5] = (val < min) ? out2_1 : val;
628 
629  val = 0.5041*out2_1 + 0.4959*out2_2;
630  out[badX1 - 4] = (val < min) ? out2_1 : val;
631 
632  val = 0.5370*out2_1 + 0.4630*out2_2;
633  out[badX1 - 3] = (val < min) ? out2_1 : val;
634 
635  val = 0.6968*out2_1 + 0.3032*out2_2;
636  out[badX1 - 2] = (val < min) ? out2_1 : val;
637 
638  val = 1.0933*out2_1 - 0.0933*out2_2;
639  out[badX1 - 1] = (val < min) ? out2_1 : val;
640 
641  val = 1.4288*out2_1 - 0.4288*out2_2;
642  out[badX1] = (val < min) ? out2_1 : val;
643 
644  break;
645  default:
646  //shFatal("Unsupported defect type: WIDE_LEFT 0%o",defect[i].type);
647  break; /* NOTREACHED */
648  }
649 
650  break;
651  case Defect::RIGHT:
652  assert(badX0 >= 2 && badX1 < ncol);
653 
654  out1_2 = out[badX0 - 2];
655  out1_1 = out[badX0 - 1];
656 
657  switch (defectType) {
658  case 06: /* ##., <noise^2> = 0 */
659  val = -0.4288*out1_2 + 1.4288*out1_1;
660  out[badX1] = (val < min) ? out1_1 : val;
661 
662  break;
663  case 014: /* ##.., <noise^2> = 0 */
664  val = -0.4288*out1_2 + 1.4288*out1_1;
665  out[badX0] = (val < min) ? out1_1 : val;
666 
667  val = -0.0933*out1_2 + 1.0933*out1_1;
668  out[badX1] = (val < min) ? out1_1 : val;
669 
670  break;
671  case 030: /* ##..., <noise^2> = 0 */
672  val = -0.4288*out1_2 + 1.4288*out1_1;
673  out[badX0] = (val < min) ? out1_1 : val;
674 
675  val = -0.0933*out1_2 + 1.0933*out1_1;
676  out[badX1 - 1] = (val < min) ? out1_1 : val;
677 
678  val = 0.3032*out1_2 + 0.6968*out1_1;
679  out[badX1] = (val < min) ? out1_1 : val;
680 
681  break;
682  case 060: /* ##...., <noise^2> = 0 */
683  val = -0.4288*out1_2 + 1.4288*out1_1;
684  out[badX0] = (val < min) ? out1_1 : val;
685 
686  val = -0.0933*out1_2 + 1.0933*out1_1;
687  out[badX0 + 1] = (val < min) ? out1_1 : val;
688 
689  val = 0.3032*out1_2 + 0.6968*out1_1;
690  out[badX1 - 1] = (val < min) ? out1_1 : val;
691 
692  val = 0.4630*out1_2 + 0.5370*out1_1;
693  out[badX1] = (val < min) ? out1_1 : val;
694 
695  break;
696  case 0140: /* ##....., <noise^2> = 0 */
697  val = -0.4288*out1_2 + 1.4288*out1_1;
698  out[badX0] = (val < min) ? out1_1 : val;
699 
700  val = -0.0933*out1_2 + 1.0933*out1_1;
701  out[badX0 + 1] = (val < min) ? out1_1 : val;
702 
703  val = 0.3032*out1_2 + 0.6968*out1_1;
704  out[badX1 - 2] = (val < min) ? out1_1 : val;
705 
706  val = 0.4630*out1_2 + 0.5370*out1_1;
707  out[badX1 - 1] = (val < min) ? out1_1 : val;
708 
709  val = 0.4959*out1_2 + 0.5041*out1_1;
710  out[badX1] = (val < min) ? out1_1 : val;
711 
712  break;
713  case 0300: /* ##......, <noise^2> = 0 */
714  val = -0.4288*out1_2 + 1.4288*out1_1;
715  out[badX0] = (val < min) ? out1_1 : val;
716 
717  val = -0.0933*out1_2 + 1.0933*out1_1;
718  out[badX0 + 1] = (val < min) ? out1_1 : val;
719 
720  val = 0.3032*out1_2 + 0.6968*out1_1;
721  out[badX0 + 2] = (val < min) ? out1_1 : val;
722 
723  val = 0.4630*out1_2 + 0.5370*out1_1;
724  out[badX1 - 2] = (val < min) ? out1_1 : val;
725 
726  val = 0.4959*out1_2 + 0.5041*out1_1;
727  out[badX1 - 1] = (val < min) ? out1_1 : val;
728 
729  val = 0.4997*out1_2 + 0.5003*out1_1;
730  out[badX1] = (val < min) ? out1_1 : val;
731 
732  break;
733  case 0600: /* ##......., <noise^2> = 0 */
734  val = -0.4288*out1_2 + 1.4288*out1_1;
735  out[badX0] = (val < min) ? out1_1 : val;
736 
737  val = -0.0933*out1_2 + 1.0933*out1_1;
738  out[badX0 + 1] = (val < min) ? out1_1 : val;
739 
740  val = 0.3032*out1_2 + 0.6968*out1_1;
741  out[badX0 + 2] = (val < min) ? out1_1 : val;
742 
743  val = 0.4630*out1_2 + 0.5370*out1_1;
744  out[badX1 - 3] = (val < min) ? out1_1 : val;
745 
746  val = 0.4959*out1_2 + 0.5041*out1_1;
747  out[badX1 - 2] = (val < min) ? out1_1 : val;
748 
749  val = 0.4997*out1_2 + 0.5003*out1_1;
750  out[badX1 - 1] = (val < min) ? out1_1 : val;
751 
752  val = 0.5000*out1_2 + 0.5000*out1_1;
753  out[badX1] = (val < min) ? out1_1 : val;
754 
755  break;
756  case 01400: /* ##........, <noise^2> = 0 */
757  val = -0.4288*out1_2 + 1.4288*out1_1;
758  out[badX0] = (val < min) ? out1_1 : val;
759 
760  val = -0.0933*out1_2 + 1.0933*out1_1;
761  out[badX0 + 1] = (val < min) ? out1_1 : val;
762 
763  val = 0.3032*out1_2 + 0.6968*out1_1;
764  out[badX0 + 2] = (val < min) ? out1_1 : val;
765 
766  val = 0.4630*out1_2 + 0.5370*out1_1;
767  out[badX0 + 3] = (val < min) ? out1_1 : val;
768 
769  val = 0.4959*out1_2 + 0.5041*out1_1;
770  out[badX1 - 3] = (val < min) ? out1_1 : val;
771 
772  val = 0.4997*out1_2 + 0.5003*out1_1;
773  out[badX1 - 2] = (val < min) ? out1_1 : val;
774 
775  val = 0.5000*out1_2 + 0.5000*out1_1;
776  out[badX1 - 1] = (val < min) ? out1_1 : val;
777 
778  val = 0.5000*out1_2 + 0.5000*out1_1;
779  out[badX1] = (val < min) ? out1_1 : val;
780 
781  break;
782  case 03000: /* ##........., <noise^2> = 0 */
783  val = -0.4288*out1_2 + 1.4288*out1_1;
784  out[badX0] = (val < min) ? out1_1 : val;
785 
786  val = -0.0933*out1_2 + 1.0933*out1_1;
787  out[badX0 + 1] = (val < min) ? out1_1 : val;
788 
789  val = 0.3032*out1_2 + 0.6968*out1_1;
790  out[badX0 + 2] = (val < min) ? out1_1 : val;
791 
792  val = 0.4630*out1_2 + 0.5370*out1_1;
793  out[badX0 + 3] = (val < min) ? out1_1 : val;
794 
795  val = 0.4959*out1_2 + 0.5041*out1_1;
796  out[badX1 - 4] = (val < min) ? out1_1 : val;
797 
798  val = 0.4997*out1_2 + 0.5003*out1_1;
799  out[badX1 - 3] = (val < min) ? out1_1 : val;
800 
801  val = 0.5000*out1_2 + 0.5000*out1_1;
802  out[badX1 - 2] = (val < min) ? out1_1 : val;
803 
804  val = 0.5000*out1_2 + 0.5000*out1_1;
805  out[badX1 - 1] = (val < min) ? out1_1 : val;
806 
807  val = 0.5000*out1_2 + 0.5000*out1_1;
808  out[badX1] = (val < min) ? out1_1 : val;
809 
810  break;
811  case 06000: /* ##.........., <noise^2> = 0 */
812  val = -0.4288*out1_2 + 1.4288*out1_1;
813  out[badX0] = (val < min) ? out1_1 : val;
814 
815  val = -0.0933*out1_2 + 1.0933*out1_1;
816  out[badX0 + 1] = (val < min) ? out1_1 : val;
817 
818  val = 0.3032*out1_2 + 0.6968*out1_1;
819  out[badX0 + 2] = (val < min) ? out1_1 : val;
820 
821  val = 0.4630*out1_2 + 0.5370*out1_1;
822  out[badX0 + 3] = (val < min) ? out1_1 : val;
823 
824  val = 0.4959*out1_2 + 0.5041*out1_1;
825  out[badX0 + 4] = (val < min) ? out1_1 : val;
826 
827  val = 0.4997*out1_2 + 0.5003*out1_1;
828  out[badX1 - 4] = (val < min) ? out1_1 : val;
829 
830  val = 0.5000*out1_2 + 0.5000*out1_1;
831  out[badX1 - 3] = (val < min) ? out1_1 : val;
832 
833  val = 0.5000*out1_2 + 0.5000*out1_1;
834  out[badX1 - 2] = (val < min) ? out1_1 : val;
835 
836  val = 0.5000*out1_2 + 0.5000*out1_1;
837  out[badX1 - 1] = (val < min) ? out1_1 : val;
838 
839  val = 0.5000*out1_2 + 0.5000*out1_1;
840  out[badX1] = (val < min) ? out1_1 : val;
841 
842  break;
843  default:
844  //shFatal("Unsupported defect type: RIGHT 0%o",defect[i].type);
845  break; /* NOTREACHED */
846  }
847  break;
848  case Defect::WIDE_RIGHT:
849  assert(badX1 < ncol);
850 
851  if (badX0 < 2) { /* right defect extends near
852  left edge of data! */
853  if (badX0 == 1) { /* one column remains */
854  val = out[0];
855  } else {
856  val = fallbackValue; /* there is no information */
857  }
858  for (int j = badX0; j <= badX1; j++) {
859  out[j] = val;
860  }
861  break;
862  }
863 
864  out1_2 = out[badX0 - 2];
865  out1_1 = out[badX0 - 1];
866 
867  switch (defectType) {
868  case 03: /* ##?, S/N = infty */
869  val = -0.4288*out1_2 + 1.4288*out1_1;
870  out[badX0] = (val < min) ? out1_1 : val;
871 
872  val = -0.0933*out1_2 + 1.0933*out1_1;
873  out[badX0 + 1] = (val < min) ? out1_1 : val;
874 
875  val = 0.3032*out1_2 + 0.6968*out1_1;
876  out[badX0 + 2] = (val < min) ? out1_1 : val;
877 
878  val = 0.4630*out1_2 + 0.5370*out1_1;
879  out[badX0 + 3] = (val < min) ? out1_1 : val;
880 
881  val = 0.4959*out1_2 + 0.5041*out1_1;
882  out[badX0 + 4] = (val < min) ? out1_1 : val;
883 
884  val = 0.4997*out1_2 + 0.5003*out1_1;
885  out[badX0 + 5] = (val < min) ? out1_1 : val;
886 
887  val = 0.5000*out1_2 + 0.5000*out1_1;
888  val = (val < min) ? out1_1 : val;
889 
890  for (int j = badX0 + 6; j <= badX1; j++) {
891  out[j] = val;
892  }
893  break;
894  default:
895  //shFatal("Unsupported defect type: WIDE_RIGHT 0%o",defect[i].type);
896  break; /* NOTREACHED */
897  }
898  break;
899  case Defect::MIDDLE:
900  case Defect::NEAR_LEFT:
901  case Defect::NEAR_RIGHT:
902  if (defectPos == Defect::MIDDLE) {
903  assert(badX0 >= 2 && badX1 + 2 < ncol);
904  out1_2 = out[badX0 - 2];
905  out2_2 = out[badX1 + 2];
906  } else if (defectPos == Defect::NEAR_LEFT) {
907  assert(badX0 >= 1 && badX1 + 2 < ncol);
908  out1_2 = -1; /* NOTUSED */
909  out2_2 = out[badX1 + 2];
910  } else if (defectPos == Defect::NEAR_RIGHT) {
911  assert(badX0 >= 2 && badX1 + 1 < ncol);
912  out1_2 = out[badX0 - 2];
913  out2_2 = -1; /* NOTUSED */
914  } else {
915  //shFatal("Unknown defect classification %d (%s:%d)",defectPos, __FILE__,__LINE__);
916  out1_2 = out2_2 = -1; /* NOTUSED */
917  }
918  out1_1 = out[badX0 - 1];
919  out2_1 = out[badX1 + 1];
920 
921  switch (defectType) {
922  case 012: /* #.#., <noise^2> = 0, sigma = 1 */
923  val = 0.5000*out1_1 + 0.5000*out2_1;
924  out[badX1] = (val < min) ? 0.5*(out1_1 + out2_1): val;
925 
926  break;
927  case 013: /* #.##, <noise^2> = 0 */
928  val = 0.4875*out1_1 + 0.8959*out2_1 - 0.3834*out2_2;
929  out[badX1] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
930 
931  break;
932  case 022: /* #..#., <noise^2> = 0, sigma = 1 */
933  val = 0.7297*out1_1 + 0.2703*out2_1;
934  out[badX0] = (val < 0) ? 0 : val;
935 
936  val = 0.2703*out1_1 + 0.7297*out2_1;
937  out[badX1] = (val < 0) ? 0 : val;
938 
939  break;
940  case 023: /* #..##, <noise^2> = 0 */
941  val = 0.7538*out1_1 + 0.5680*out2_1 - 0.3218*out2_2;
942  out[badX0] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
943 
944  val = 0.3095*out1_1 + 1.2132*out2_1 - 0.5227*out2_2;
945  out[badX1] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
946 
947  break;
948  case 032: /* ##.#., <noise^2> = 0 */
949  val = -0.3834*out1_2 + 0.8959*out1_1 + 0.4875*out2_1;
950  out[badX1] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
951 
952  break;
953  case 033: /* ##.##, <noise^2> = 0 */
954  /* These coefficients are also available as
955  interp::interp_1_c1 and interp::interp_1_c2 */
956  val = -0.2737*out1_2 + 0.7737*out1_1 + 0.7737*out2_1 - 0.2737*out2_2;
957  out[badX1] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
958 
959  break;
960  case 042: /* #...#., <noise^2> = 0, sigma = 1 */
961  val = 0.8430*out1_1 + 0.1570*out2_1;
962  out[badX0] = (val < min) ? 0.5*(out1_1 + out2_1): val;
963 
964  val = 0.5000*out1_1 + 0.5000*out2_1;
965  out[badX1 - 1] = (val < min) ? 0.5*(out1_1 + out2_1): val;
966 
967  val = 0.1570*out1_1 + 0.8430*out2_1;
968  out[badX1] = (val < min) ? 0.5*(out1_1 + out2_1): val;
969 
970  break;
971  case 043: /* #...##, <noise^2> = 0 */
972  val = 0.8525*out1_1 + 0.2390*out2_1 - 0.0915*out2_2;
973  out[badX0] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
974 
975  val = 0.5356*out1_1 + 0.8057*out2_1 - 0.3413*out2_2;
976  out[badX1 - 1] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
977 
978  val = 0.2120*out1_1 + 1.3150*out2_1 - 0.5270*out2_2;
979  out[badX1] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
980 
981  break;
982  case 062: /* ##..#., <noise^2> = 0 */
983  val = -0.5227*out1_2 + 1.2132*out1_1 + 0.3095*out2_1;
984  out[badX0] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
985 
986  val = -0.3218*out1_2 + 0.5680*out1_1 + 0.7538*out2_1;
987  out[badX1] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
988 
989  break;
990  case 063: /* ##..##, <noise^2> = 0 */
991  val = -0.4793*out1_2 + 1.1904*out1_1 + 0.5212*out2_1 - 0.2323*out2_2;
992  out[badX0] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
993 
994  val = -0.2323*out1_2 + 0.5212*out1_1 + 1.1904*out2_1 - 0.4793*out2_2;
995  out[badX1] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
996 
997  break;
998  case 0102: /* #....#., <noise^2> = 0, sigma = 1 */
999  val = 0.8810*out1_1 + 0.1190*out2_1;
1000  out[badX0] = (val < min) ? 0.5*(out1_1 + out2_1): val;
1001 
1002  val = 0.6315*out1_1 + 0.3685*out2_1;
1003  out[badX0 + 1] = (val < min) ? 0.5*(out1_1 + out2_1): val;
1004 
1005  val = 0.3685*out1_1 + 0.6315*out2_1;
1006  out[badX1 - 1] = (val < min) ? 0.5*(out1_1 + out2_1): val;
1007 
1008  val = 0.1190*out1_1 + 0.8810*out2_1;
1009  out[badX1] = (val < min) ? 0.5*(out1_1 + out2_1): val;
1010 
1011  break;
1012  case 0103: /* #....##, <noise^2> = 0 */
1013  val = 0.8779*out1_1 + 0.0945*out2_1 + 0.0276*out2_2;
1014  out[badX0] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1015 
1016  val = 0.6327*out1_1 + 0.3779*out2_1 - 0.0106*out2_2;
1017  out[badX0 + 1] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1018 
1019  val = 0.4006*out1_1 + 0.8914*out2_1 - 0.2920*out2_2;
1020  out[badX1 - 1] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1021 
1022  val = 0.1757*out1_1 + 1.3403*out2_1 - 0.5160*out2_2;
1023  out[badX1] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1024 
1025  break;
1026  case 0142: /* ##...#., <noise^2> = 0 */
1027  val = -0.5270*out1_2 + 1.3150*out1_1 + 0.2120*out2_1;
1028  out[badX0] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1029 
1030  val = -0.3413*out1_2 + 0.8057*out1_1 + 0.5356*out2_1;
1031  out[badX1 - 1] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1032 
1033  val = -0.0915*out1_2 + 0.2390*out1_1 + 0.8525*out2_1;
1034  out[badX1] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1035 
1036  break;
1037  case 0143: /* ##...##, <noise^2> = 0 */
1038  val = -0.5230*out1_2 + 1.3163*out1_1 + 0.2536*out2_1 - 0.0469*out2_2;
1039  out[badX0] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1040 
1041  val = -0.3144*out1_2 + 0.8144*out1_1 + 0.8144*out2_1 - 0.3144*out2_2;
1042  out[badX1 - 1] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1043 
1044  val = -0.0469*out1_2 + 0.2536*out1_1 + 1.3163*out2_1 - 0.5230*out2_2;
1045  out[badX1] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1046 
1047  break;
1048  case 0202: /* #.....#., <noise^2> = 0, sigma = 1 */
1049  val = 0.8885*out1_1 + 0.1115*out2_1;
1050  out[badX0] = (val < min) ? 0.5*(out1_1 + out2_1): val;
1051 
1052  val = 0.6748*out1_1 + 0.3252*out2_1;
1053  out[badX0 + 1] = (val < min) ? 0.5*(out1_1 + out2_1): val;
1054 
1055  val = 0.5000*out1_1 + 0.5000*out2_1;
1056  out[badX1 - 2] = (val < min) ? 0.5*(out1_1 + out2_1): val;
1057 
1058  val = 0.3252*out1_1 + 0.6748*out2_1;
1059  out[badX1 - 1] = (val < min) ? 0.5*(out1_1 + out2_1): val;
1060 
1061  val = 0.1115*out1_1 + 0.8885*out2_1;
1062  out[badX1] = (val < min) ? 0.5*(out1_1 + out2_1): val;
1063 
1064  break;
1065  case 0203: /* #.....##, <noise^2> = 0 */
1066  val = 0.8824*out1_1 + 0.0626*out2_1 + 0.0549*out2_2;
1067  out[badX0] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1068 
1069  val = 0.6601*out1_1 + 0.2068*out2_1 + 0.1331*out2_2;
1070  out[badX0 + 1] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1071 
1072  val = 0.4938*out1_1 + 0.4498*out2_1 + 0.0564*out2_2;
1073  out[badX1 - 2] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1074 
1075  val = 0.3551*out1_1 + 0.9157*out2_1 - 0.2708*out2_2;
1076  out[badX1 - 1] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1077 
1078  val = 0.1682*out1_1 + 1.3447*out2_1 - 0.5129*out2_2;
1079  out[badX1] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1080 
1081  break;
1082  case 0302: /* ##....#., <noise^2> = 0 */
1083  val = -0.5160*out1_2 + 1.3403*out1_1 + 0.1757*out2_1;
1084  out[badX0] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1085 
1086  val = -0.2920*out1_2 + 0.8914*out1_1 + 0.4006*out2_1;
1087  out[badX0 + 1] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1088 
1089  val = -0.0106*out1_2 + 0.3779*out1_1 + 0.6327*out2_1;
1090  out[badX1 - 1] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1091 
1092  val = 0.0276*out1_2 + 0.0945*out1_1 + 0.8779*out2_1;
1093  out[badX1] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1094 
1095  break;
1096  case 0303: /* ##....##, <noise^2> = 0 */
1097  val = -0.5197*out1_2 + 1.3370*out1_1 + 0.1231*out2_1 + 0.0596*out2_2;
1098  out[badX0] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1099 
1100  val = -0.2924*out1_2 + 0.8910*out1_1 + 0.3940*out2_1 + 0.0074*out2_2;
1101  out[badX0 + 1] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1102 
1103  val = 0.0074*out1_2 + 0.3940*out1_1 + 0.8910*out2_1 - 0.2924*out2_2;
1104  out[badX1 - 1] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1105 
1106  val = 0.0596*out1_2 + 0.1231*out1_1 + 1.3370*out2_1 - 0.5197*out2_2;
1107  out[badX1] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1108 
1109  break;
1110  case 0402: /* #......#., <noise^2> = 0, sigma = 1 */
1111  val = 0.8893*out1_1 + 0.1107*out2_1;
1112  out[badX0] = (val < min) ? 0.5*(out1_1 + out2_1): val;
1113 
1114  val = 0.6830*out1_1 + 0.3170*out2_1;
1115  out[badX0 + 1] = (val < min) ? 0.5*(out1_1 + out2_1): val;
1116 
1117  val = 0.5435*out1_1 + 0.4565*out2_1;
1118  out[badX0 + 2] = (val < min) ? 0.5*(out1_1 + out2_1): val;
1119 
1120  val = 0.4565*out1_1 + 0.5435*out2_1;
1121  out[badX1 - 2] = (val < min) ? 0.5*(out1_1 + out2_1): val;
1122 
1123  val = 0.3170*out1_1 + 0.6830*out2_1;
1124  out[badX1 - 1] = (val < min) ? 0.5*(out1_1 + out2_1): val;
1125 
1126  val = 0.1107*out1_1 + 0.8893*out2_1;
1127  out[badX1] = (val < min) ? 0.5*(out1_1 + out2_1): val;
1128 
1129  break;
1130  case 0403: /* #......##, <noise^2> = 0 */
1131  val = 0.8829*out1_1 + 0.0588*out2_1 + 0.0583*out2_2;
1132  out[badX0] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1133 
1134  val = 0.6649*out1_1 + 0.1716*out2_1 + 0.1635*out2_2;
1135  out[badX0 + 1] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1136 
1137  val = 0.5212*out1_1 + 0.2765*out2_1 + 0.2024*out2_2;
1138  out[badX0 + 2] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1139 
1140  val = 0.4477*out1_1 + 0.4730*out2_1 + 0.0793*out2_2;
1141  out[badX1 - 2] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1142 
1143  val = 0.3465*out1_1 + 0.9201*out2_1 - 0.2666*out2_2;
1144  out[badX1 - 1] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1145 
1146  val = 0.1673*out1_1 + 1.3452*out2_1 - 0.5125*out2_2;
1147  out[badX1] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1148 
1149  break;
1150  case 0602: /* ##.....#., <noise^2> = 0 */
1151  val = -0.5129*out1_2 + 1.3447*out1_1 + 0.1682*out2_1;
1152  out[badX0] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1153 
1154  val = -0.2708*out1_2 + 0.9157*out1_1 + 0.3551*out2_1;
1155  out[badX0 + 1] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1156 
1157  val = 0.0564*out1_2 + 0.4498*out1_1 + 0.4938*out2_1;
1158  out[badX1 - 2] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1159 
1160  val = 0.1331*out1_2 + 0.2068*out1_1 + 0.6601*out2_1;
1161  out[badX1 - 1] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1162 
1163  val = 0.0549*out1_2 + 0.0626*out1_1 + 0.8824*out2_1;
1164  out[badX1] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1165 
1166  break;
1167  case 0603: /* ##.....##, <noise^2> = 0 */
1168  val = -0.5179*out1_2 + 1.3397*out1_1 + 0.0928*out2_1 + 0.0854*out2_2;
1169  out[badX0] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1170 
1171  val = -0.2796*out1_2 + 0.9069*out1_1 + 0.2231*out2_1 + 0.1495*out2_2;
1172  out[badX0 + 1] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1173 
1174  val = 0.0533*out1_2 + 0.4467*out1_1 + 0.4467*out2_1 + 0.0533*out2_2;
1175  out[badX1 - 2] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1176 
1177  val = 0.1495*out1_2 + 0.2231*out1_1 + 0.9069*out2_1 - 0.2796*out2_2;
1178  out[badX1 - 1] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1179 
1180  val = 0.0854*out1_2 + 0.0928*out1_1 + 1.3397*out2_1 - 0.5179*out2_2;
1181  out[badX1] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1182 
1183  break;
1184  case 01002: /* #.......#., <noise^2> = 0, sigma = 1 */
1185  val = 0.8894*out1_1 + 0.1106*out2_1;
1186  out[badX0] = (val < min) ? 0.5*(out1_1 + out2_1): val;
1187 
1188  val = 0.6839*out1_1 + 0.3161*out2_1;
1189  out[badX0 + 1] = (val < min) ? 0.5*(out1_1 + out2_1): val;
1190 
1191  val = 0.5517*out1_1 + 0.4483*out2_1;
1192  out[badX0 + 2] = (val < min) ? 0.5*(out1_1 + out2_1): val;
1193 
1194  val = 0.5000*out1_1 + 0.5000*out2_1;
1195  out[badX1 - 3] = (val < min) ? 0.5*(out1_1 + out2_1): val;
1196 
1197  val = 0.4483*out1_1 + 0.5517*out2_1;
1198  out[badX1 - 2] = (val < min) ? 0.5*(out1_1 + out2_1): val;
1199 
1200  val = 0.3161*out1_1 + 0.6839*out2_1;
1201  out[badX1 - 1] = (val < min) ? 0.5*(out1_1 + out2_1): val;
1202 
1203  val = 0.1106*out1_1 + 0.8894*out2_1;
1204  out[badX1] = (val < min) ? 0.5*(out1_1 + out2_1): val;
1205 
1206  break;
1207  case 01003: /* #.......##, <noise^2> = 0 */
1208  val = 0.8829*out1_1 + 0.0585*out2_1 + 0.0585*out2_2;
1209  out[badX0] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1210 
1211  val = 0.6654*out1_1 + 0.1676*out2_1 + 0.1670*out2_2;
1212  out[badX0 + 1] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1213 
1214  val = 0.5260*out1_1 + 0.2411*out2_1 + 0.2329*out2_2;
1215  out[badX0 + 2] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1216 
1217  val = 0.4751*out1_1 + 0.2995*out2_1 + 0.2254*out2_2;
1218  out[badX1 - 3] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1219 
1220  val = 0.4390*out1_1 + 0.4773*out2_1 + 0.0836*out2_2;
1221  out[badX1 - 2] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1222 
1223  val = 0.3456*out1_1 + 0.9205*out2_1 - 0.2661*out2_2;
1224  out[badX1 - 1] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1225 
1226  val = 0.1673*out1_1 + 1.3452*out2_1 - 0.5125*out2_2;
1227  out[badX1] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1228 
1229  break;
1230  case 01402: /* ##......#., <noise^2> = 0 */
1231  val = -0.5125*out1_2 + 1.3452*out1_1 + 0.1673*out2_1;
1232  out[badX0] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1233 
1234  val = -0.2666*out1_2 + 0.9201*out1_1 + 0.3465*out2_1;
1235  out[badX0 + 1] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1236 
1237  val = 0.0793*out1_2 + 0.4730*out1_1 + 0.4477*out2_1;
1238  out[badX0 + 2] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1239 
1240  val = 0.2024*out1_2 + 0.2765*out1_1 + 0.5212*out2_1;
1241  out[badX1 - 2] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1242 
1243  val = 0.1635*out1_2 + 0.1716*out1_1 + 0.6649*out2_1;
1244  out[badX1 - 1] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1245 
1246  val = 0.0583*out1_2 + 0.0588*out1_1 + 0.8829*out2_1;
1247  out[badX1] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1248 
1249  break;
1250  case 01403: /* ##......##, <noise^2> = 0 */
1251  val = -0.5177*out1_2 + 1.3400*out1_1 + 0.0891*out2_1 + 0.0886*out2_2;
1252  out[badX0] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1253 
1254  val = -0.2771*out1_2 + 0.9095*out1_1 + 0.1878*out2_1 + 0.1797*out2_2;
1255  out[badX0 + 1] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1256 
1257  val = 0.0677*out1_2 + 0.4614*out1_1 + 0.2725*out2_1 + 0.1984*out2_2;
1258  out[badX0 + 2] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1259 
1260  val = 0.1984*out1_2 + 0.2725*out1_1 + 0.4614*out2_1 + 0.0677*out2_2;
1261  out[badX1 - 2] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1262 
1263  val = 0.1797*out1_2 + 0.1878*out1_1 + 0.9095*out2_1 - 0.2771*out2_2;
1264  out[badX1 - 1] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1265 
1266  val = 0.0886*out1_2 + 0.0891*out1_1 + 1.3400*out2_1 - 0.5177*out2_2;
1267  out[badX1] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1268 
1269  break;
1270  case 02002: /* #........#., <noise^2> = 0, sigma = 1 */
1271  val = 0.8894*out1_1 + 0.1106*out2_1;
1272  out[badX0] = (val < min) ? 0.5*(out1_1 + out2_1): val;
1273 
1274  val = 0.6839*out1_1 + 0.3161*out2_1;
1275  out[badX0 + 1] = (val < min) ? 0.5*(out1_1 + out2_1): val;
1276 
1277  val = 0.5526*out1_1 + 0.4474*out2_1;
1278  out[badX0 + 2] = (val < min) ? 0.5*(out1_1 + out2_1): val;
1279 
1280  val = 0.5082*out1_1 + 0.4918*out2_1;
1281  out[badX0 + 3] = (val < min) ? 0.5*(out1_1 + out2_1): val;
1282 
1283  val = 0.4918*out1_1 + 0.5082*out2_1;
1284  out[badX1 - 3] = (val < min) ? 0.5*(out1_1 + out2_1): val;
1285 
1286  val = 0.4474*out1_1 + 0.5526*out2_1;
1287  out[badX1 - 2] = (val < min) ? 0.5*(out1_1 + out2_1): val;
1288 
1289  val = 0.3161*out1_1 + 0.6839*out2_1;
1290  out[badX1 - 1] = (val < min) ? 0.5*(out1_1 + out2_1): val;
1291 
1292  val = 0.1106*out1_1 + 0.8894*out2_1;
1293  out[badX1] = (val < min) ? 0.5*(out1_1 + out2_1): val;
1294 
1295  break;
1296  case 02003: /* #........##, <noise^2> = 0 */
1297  val = 0.8829*out1_1 + 0.0585*out2_1 + 0.0585*out2_2;
1298  out[badX0] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1299 
1300  val = 0.6654*out1_1 + 0.1673*out2_1 + 0.1673*out2_2;
1301  out[badX0 + 1] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1302 
1303  val = 0.5265*out1_1 + 0.2370*out2_1 + 0.2365*out2_2;
1304  out[badX0 + 2] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1305 
1306  val = 0.4799*out1_1 + 0.2641*out2_1 + 0.2560*out2_2;
1307  out[badX0 + 3] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1308 
1309  val = 0.4664*out1_1 + 0.3038*out2_1 + 0.2298*out2_2;
1310  out[badX1 - 3] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1311 
1312  val = 0.4381*out1_1 + 0.4778*out2_1 + 0.0841*out2_2;
1313  out[badX1 - 2] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1314 
1315  val = 0.3455*out1_1 + 0.9206*out2_1 - 0.2661*out2_2;
1316  out[badX1 - 1] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1317 
1318  val = 0.1673*out1_1 + 1.3452*out2_1 - 0.5125*out2_2;
1319  out[badX1] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1320 
1321  break;
1322  case 03002: /* ##.......#., <noise^2> = 0 */
1323  val = -0.5125*out1_2 + 1.3452*out1_1 + 0.1673*out2_1;
1324  out[badX0] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1325 
1326  val = -0.2661*out1_2 + 0.9205*out1_1 + 0.3456*out2_1;
1327  out[badX0 + 1] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1328 
1329  val = 0.0836*out1_2 + 0.4773*out1_1 + 0.4390*out2_1;
1330  out[badX0 + 2] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1331 
1332  val = 0.2254*out1_2 + 0.2995*out1_1 + 0.4751*out2_1;
1333  out[badX1 - 3] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1334 
1335  val = 0.2329*out1_2 + 0.2411*out1_1 + 0.5260*out2_1;
1336  out[badX1 - 2] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1337 
1338  val = 0.1670*out1_2 + 0.1676*out1_1 + 0.6654*out2_1;
1339  out[badX1 - 1] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1340 
1341  val = 0.0585*out1_2 + 0.0585*out1_1 + 0.8829*out2_1;
1342  out[badX1] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1343 
1344  break;
1345  case 03003: /* ##.......##, <noise^2> = 0 */
1346  val = -0.5177*out1_2 + 1.3400*out1_1 + 0.0889*out2_1 + 0.0888*out2_2;
1347  out[badX0] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1348 
1349  val = -0.2768*out1_2 + 0.9098*out1_1 + 0.1838*out2_1 + 0.1832*out2_2;
1350  out[badX0 + 1] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1351 
1352  val = 0.0703*out1_2 + 0.4639*out1_1 + 0.2370*out2_1 + 0.2288*out2_2;
1353  out[badX0 + 2] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1354 
1355  val = 0.2130*out1_2 + 0.2870*out1_1 + 0.2870*out2_1 + 0.2130*out2_2;
1356  out[badX1 - 3] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1357 
1358  val = 0.2288*out1_2 + 0.2370*out1_1 + 0.4639*out2_1 + 0.0703*out2_2;
1359  out[badX1 - 2] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1360 
1361  val = 0.1832*out1_2 + 0.1838*out1_1 + 0.9098*out2_1 - 0.2768*out2_2;
1362  out[badX1 - 1] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1363 
1364  val = 0.0888*out1_2 + 0.0889*out1_1 + 1.3400*out2_1 - 0.5177*out2_2;
1365  out[badX1] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1366 
1367  break;
1368  case 04002: /* #.........#., <noise^2> = 0 */
1369  val = 0.8894*out1_1 + 0.1106*out2_1;
1370  out[badX0] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1371 
1372  val = 0.6839*out1_1 + 0.3161*out2_1;
1373  out[badX0 + 1] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1374 
1375  val = 0.5527*out1_1 + 0.4473*out2_1;
1376  out[badX0 + 2] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1377 
1378  val = 0.5091*out1_1 + 0.4909*out2_1;
1379  out[badX0 + 3] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1380 
1381  val = 0.5000*out1_1 + 0.5000*out2_1;
1382  out[badX1 - 4] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1383 
1384  val = 0.4909*out1_1 + 0.5091*out2_1;
1385  out[badX1 - 3] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1386 
1387  val = 0.4473*out1_1 + 0.5527*out2_1;
1388  out[badX1 - 2] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1389 
1390  val = 0.3161*out1_1 + 0.6839*out2_1;
1391  out[badX1 - 1] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1392 
1393  val = 0.1106*out1_1 + 0.8894*out2_1;
1394  out[badX1] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1395 
1396  break;
1397  case 04003: /* #.........##, <noise^2> = 0 */
1398  val = 0.8829*out1_1 + 0.0585*out2_1 + 0.0585*out2_2;
1399  out[badX0] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1400 
1401  val = 0.6654*out1_1 + 0.1673*out2_1 + 0.1673*out2_2;
1402  out[badX0 + 1] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1403 
1404  val = 0.5265*out1_1 + 0.2368*out2_1 + 0.2367*out2_2;
1405  out[badX0 + 2] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1406 
1407  val = 0.4804*out1_1 + 0.2601*out2_1 + 0.2595*out2_2;
1408  out[badX0 + 3] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1409 
1410  val = 0.4712*out1_1 + 0.2685*out2_1 + 0.2603*out2_2;
1411  out[badX1 - 4] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1412 
1413  val = 0.4654*out1_1 + 0.3043*out2_1 + 0.2302*out2_2;
1414  out[badX1 - 3] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1415 
1416  val = 0.4380*out1_1 + 0.4778*out2_1 + 0.0842*out2_2;
1417  out[badX1 - 2] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1418 
1419  val = 0.3455*out1_1 + 0.9206*out2_1 - 0.2661*out2_2;
1420  out[badX1 - 1] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1421 
1422  val = 0.1673*out1_1 + 1.3452*out2_1 - 0.5125*out2_2;
1423  out[badX1] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1424 
1425  break;
1426  case 06002: /* ##........#., <noise^2> = 0 */
1427  val = -0.5125*out1_2 + 1.3452*out1_1 + 0.1673*out2_1;
1428  out[badX0] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1429 
1430  val = -0.2661*out1_2 + 0.9206*out1_1 + 0.3455*out2_1;
1431  out[badX0 + 1] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1432 
1433  val = 0.0841*out1_2 + 0.4778*out1_1 + 0.4381*out2_1;
1434  out[badX0 + 2] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1435 
1436  val = 0.2298*out1_2 + 0.3038*out1_1 + 0.4664*out2_1;
1437  out[badX0 + 3] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1438 
1439  val = 0.2560*out1_2 + 0.2641*out1_1 + 0.4799*out2_1;
1440  out[badX1 - 3] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1441 
1442  val = 0.2365*out1_2 + 0.2370*out1_1 + 0.5265*out2_1;
1443  out[badX1 - 2] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1444 
1445  val = 0.1673*out1_2 + 0.1673*out1_1 + 0.6654*out2_1;
1446  out[badX1 - 1] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1447 
1448  val = 0.0585*out1_2 + 0.0585*out1_1 + 0.8829*out2_1;
1449  out[badX1] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1450 
1451  break;
1452  case 06003: /* ##........##, <noise^2> = 0 */
1453  val = -0.5177*out1_2 + 1.3400*out1_1 + 0.0888*out2_1 + 0.0888*out2_2;
1454  out[badX0] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1455 
1456  val = -0.2768*out1_2 + 0.9098*out1_1 + 0.1835*out2_1 + 0.1835*out2_2;
1457  out[badX0 + 1] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1458 
1459  val = 0.0705*out1_2 + 0.4642*out1_1 + 0.2329*out2_1 + 0.2324*out2_2;
1460  out[badX0 + 2] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1461 
1462  val = 0.2155*out1_2 + 0.2896*out1_1 + 0.2515*out2_1 + 0.2434*out2_2;
1463  out[badX0 + 3] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1464 
1465  val = 0.2434*out1_2 + 0.2515*out1_1 + 0.2896*out2_1 + 0.2155*out2_2;
1466  out[badX1 - 3] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1467 
1468  val = 0.2324*out1_2 + 0.2329*out1_1 + 0.4642*out2_1 + 0.0705*out2_2;
1469  out[badX1 - 2] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1470 
1471  val = 0.1835*out1_2 + 0.1835*out1_1 + 0.9098*out2_1 - 0.2768*out2_2;
1472  out[badX1 - 1] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1473 
1474  val = 0.0888*out1_2 + 0.0888*out1_1 + 1.3400*out2_1 - 0.5177*out2_2;
1475  out[badX1] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1476 
1477  break;
1478  case 010002: /* #..........#., <noise^2> = 0, sigma = 1 */
1479  val = 0.8894*out1_1 + 0.1106*out2_1;
1480  out[badX0] = (val < min) ? 0.5*(out1_1 + out2_1): val;
1481 
1482  val = 0.6839*out1_1 + 0.3161*out2_1;
1483  out[badX0 + 1] = (val < min) ? 0.5*(out1_1 + out2_1): val;
1484 
1485  val = 0.5527*out1_1 + 0.4473*out2_1;
1486  out[badX0 + 2] = (val < min) ? 0.5*(out1_1 + out2_1): val;
1487 
1488  val = 0.5092*out1_1 + 0.4908*out2_1;
1489  out[badX0 + 3] = (val < min) ? 0.5*(out1_1 + out2_1): val;
1490 
1491  val = 0.5009*out1_1 + 0.4991*out2_1;
1492  out[badX0 + 4] = (val < min) ? 0.5*(out1_1 + out2_1): val;
1493 
1494  val = 0.4991*out1_1 + 0.5009*out2_1;
1495  out[badX1 - 4] = (val < min) ? 0.5*(out1_1 + out2_1): val;
1496 
1497  val = 0.4908*out1_1 + 0.5092*out2_1;
1498  out[badX1 - 3] = (val < min) ? 0.5*(out1_1 + out2_1): val;
1499 
1500  val = 0.4473*out1_1 + 0.5527*out2_1;
1501  out[badX1 - 2] = (val < min) ? 0.5*(out1_1 + out2_1): val;
1502 
1503  val = 0.3161*out1_1 + 0.6839*out2_1;
1504  out[badX1 - 1] = (val < min) ? 0.5*(out1_1 + out2_1): val;
1505 
1506  val = 0.1106*out1_1 + 0.8894*out2_1;
1507  out[badX1] = (val < min) ? 0.5*(out1_1 + out2_1): val;
1508 
1509  break;
1510  case 010003: /* #..........##, <noise^2> = 0 */
1511  val = 0.8829*out1_1 + 0.0585*out2_1 + 0.0585*out2_2;
1512  out[badX0] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1513 
1514  val = 0.6654*out1_1 + 0.1673*out2_1 + 0.1673*out2_2;
1515  out[badX0 + 1] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1516 
1517  val = 0.5265*out1_1 + 0.2367*out2_1 + 0.2367*out2_2;
1518  out[badX0 + 2] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1519 
1520  val = 0.4804*out1_1 + 0.2598*out2_1 + 0.2598*out2_2;
1521  out[badX0 + 3] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1522 
1523  val = 0.4717*out1_1 + 0.2644*out2_1 + 0.2639*out2_2;
1524  out[badX0 + 4] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1525 
1526  val = 0.4703*out1_1 + 0.2690*out2_1 + 0.2608*out2_2;
1527  out[badX1 - 4] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1528 
1529  val = 0.4654*out1_1 + 0.3043*out2_1 + 0.2303*out2_2;
1530  out[badX1 - 3] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1531 
1532  val = 0.4380*out1_1 + 0.4778*out2_1 + 0.0842*out2_2;
1533  out[badX1 - 2] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1534 
1535  val = 0.3455*out1_1 + 0.9206*out2_1 - 0.2661*out2_2;
1536  out[badX1 - 1] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1537 
1538  val = 0.1673*out1_1 + 1.3452*out2_1 - 0.5125*out2_2;
1539  out[badX1] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1540 
1541  break;
1542  case 014002: /* ##.........#., <noise^2> = 0 */
1543  val = -0.5125*out1_2 + 1.3452*out1_1 + 0.1673*out2_1;
1544  out[badX0] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1545 
1546  val = -0.2661*out1_2 + 0.9206*out1_1 + 0.3455*out2_1;
1547  out[badX0 + 1] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1548 
1549  val = 0.0842*out1_2 + 0.4778*out1_1 + 0.4380*out2_1;
1550  out[badX0 + 2] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1551 
1552  val = 0.2302*out1_2 + 0.3043*out1_1 + 0.4654*out2_1;
1553  out[badX0 + 3] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1554 
1555  val = 0.2603*out1_2 + 0.2685*out1_1 + 0.4712*out2_1;
1556  out[badX1 - 4] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1557 
1558  val = 0.2595*out1_2 + 0.2601*out1_1 + 0.4804*out2_1;
1559  out[badX1 - 3] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1560 
1561  val = 0.2367*out1_2 + 0.2368*out1_1 + 0.5265*out2_1;
1562  out[badX1 - 2] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1563 
1564  val = 0.1673*out1_2 + 0.1673*out1_1 + 0.6654*out2_1;
1565  out[badX1 - 1] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1566 
1567  val = 0.0585*out1_2 + 0.0585*out1_1 + 0.8829*out2_1;
1568  out[badX1] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1569 
1570  break;
1571  case 014003: /* ##.........##, <noise^2> = 0 */
1572  val = -0.5177*out1_2 + 1.3400*out1_1 + 0.0888*out2_1 + 0.0888*out2_2;
1573  out[badX0] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1574 
1575  val = -0.2768*out1_2 + 0.9098*out1_1 + 0.1835*out2_1 + 0.1835*out2_2;
1576  out[badX0 + 1] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1577 
1578  val = 0.0705*out1_2 + 0.4642*out1_1 + 0.2326*out2_1 + 0.2326*out2_2;
1579  out[badX0 + 2] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1580 
1581  val = 0.2158*out1_2 + 0.2899*out1_1 + 0.2474*out2_1 + 0.2469*out2_2;
1582  out[badX0 + 3] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1583 
1584  val = 0.2459*out1_2 + 0.2541*out1_1 + 0.2541*out2_1 + 0.2459*out2_2;
1585  out[badX1 - 4] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1586 
1587  val = 0.2469*out1_2 + 0.2474*out1_1 + 0.2899*out2_1 + 0.2158*out2_2;
1588  out[badX1 - 3] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1589 
1590  val = 0.2326*out1_2 + 0.2326*out1_1 + 0.4642*out2_1 + 0.0705*out2_2;
1591  out[badX1 - 2] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1592 
1593  val = 0.1835*out1_2 + 0.1835*out1_1 + 0.9098*out2_1 - 0.2768*out2_2;
1594  out[badX1 - 1] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1595 
1596  val = 0.0888*out1_2 + 0.0888*out1_1 + 1.3400*out2_1 - 0.5177*out2_2;
1597  out[badX1] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1598 
1599  break;
1600  case 020003: /* #...........##, <noise^2> = 0 */
1601  val = 0.8829*out1_1 + 0.0585*out2_1 + 0.0585*out2_2;
1602  out[badX0] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1603 
1604  val = 0.6654*out1_1 + 0.1673*out2_1 + 0.1673*out2_2;
1605  out[badX0 + 1] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1606 
1607  val = 0.5265*out1_1 + 0.2367*out2_1 + 0.2367*out2_2;
1608  out[badX0 + 2] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1609 
1610  val = 0.4804*out1_1 + 0.2598*out2_1 + 0.2598*out2_2;
1611  out[badX0 + 3] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1612 
1613  val = 0.4718*out1_1 + 0.2641*out2_1 + 0.2641*out2_2;
1614  out[badX0 + 4] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1615 
1616  val = 0.4708*out1_1 + 0.2649*out2_1 + 0.2644*out2_2;
1617  out[badX1 - 5] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1618 
1619  val = 0.4702*out1_1 + 0.2690*out2_1 + 0.2608*out2_2;
1620  out[badX1 - 4] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1621 
1622  val = 0.4654*out1_1 + 0.3044*out2_1 + 0.2303*out2_2;
1623  out[badX1 - 3] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1624 
1625  val = 0.4380*out1_1 + 0.4778*out2_1 + 0.0842*out2_2;
1626  out[badX1 - 2] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1627 
1628  val = 0.3455*out1_1 + 0.9206*out2_1 - 0.2661*out2_2;
1629  out[badX1 - 1] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1630 
1631  val = 0.1673*out1_1 + 1.3452*out2_1 - 0.5125*out2_2;
1632  out[badX1] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1633 
1634  break;
1635  case 030002: /* ##..........#., <noise^2> = 0 */
1636  val = -0.5125*out1_2 + 1.3452*out1_1 + 0.1673*out2_1;
1637  out[badX0] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1638 
1639  val = -0.2661*out1_2 + 0.9206*out1_1 + 0.3455*out2_1;
1640  out[badX0 + 1] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1641 
1642  val = 0.0842*out1_2 + 0.4778*out1_1 + 0.4380*out2_1;
1643  out[badX0 + 2] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1644 
1645  val = 0.2303*out1_2 + 0.3043*out1_1 + 0.4654*out2_1;
1646  out[badX0 + 3] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1647 
1648  val = 0.2608*out1_2 + 0.2690*out1_1 + 0.4703*out2_1;
1649  out[badX0 + 4] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1650 
1651  val = 0.2639*out1_2 + 0.2644*out1_1 + 0.4717*out2_1;
1652  out[badX1 - 4] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1653 
1654  val = 0.2598*out1_2 + 0.2598*out1_1 + 0.4804*out2_1;
1655  out[badX1 - 3] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1656 
1657  val = 0.2367*out1_2 + 0.2367*out1_1 + 0.5265*out2_1;
1658  out[badX1 - 2] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1659 
1660  val = 0.1673*out1_2 + 0.1673*out1_1 + 0.6654*out2_1;
1661  out[badX1 - 1] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1662 
1663  val = 0.0585*out1_2 + 0.0585*out1_1 + 0.8829*out2_1;
1664  out[badX1] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1665 
1666  break;
1667  case 030003: /* ##..........##, <noise^2> = 0 */
1668  val = -0.5177*out1_2 + 1.3400*out1_1 + 0.0888*out2_1 + 0.0888*out2_2;
1669  out[badX0] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1670 
1671  val = -0.2768*out1_2 + 0.9098*out1_1 + 0.1835*out2_1 + 0.1835*out2_2;
1672  out[badX0 + 1] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1673 
1674  val = 0.0705*out1_2 + 0.4642*out1_1 + 0.2326*out2_1 + 0.2326*out2_2;
1675  out[badX0 + 2] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1676 
1677  val = 0.2158*out1_2 + 0.2899*out1_1 + 0.2472*out2_1 + 0.2471*out2_2;
1678  out[badX0 + 3] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1679 
1680  val = 0.2462*out1_2 + 0.2544*out1_1 + 0.2500*out2_1 + 0.2495*out2_2;
1681  out[badX0 + 4] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1682 
1683  val = 0.2495*out1_2 + 0.2500*out1_1 + 0.2544*out2_1 + 0.2462*out2_2;
1684  out[badX1 - 4] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1685 
1686  val = 0.2471*out1_2 + 0.2472*out1_1 + 0.2899*out2_1 + 0.2158*out2_2;
1687  out[badX1 - 3] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1688 
1689  val = 0.2326*out1_2 + 0.2326*out1_1 + 0.4642*out2_1 + 0.0705*out2_2;
1690  out[badX1 - 2] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1691 
1692  val = 0.1835*out1_2 + 0.1835*out1_1 + 0.9098*out2_1 - 0.2768*out2_2;
1693  out[badX1 - 1] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1694 
1695  val = 0.0888*out1_2 + 0.0888*out1_1 + 1.3400*out2_1 - 0.5177*out2_2;
1696  out[badX1] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1697 
1698  break;
1699  case 040003: /* #............##, <noise^2> = 0 */
1700  val = 0.8829*out1_1 + 0.0585*out2_1 + 0.0585*out2_2;
1701  out[badX0] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1702 
1703  val = 0.6654*out1_1 + 0.1673*out2_1 + 0.1673*out2_2;
1704  out[badX0 + 1] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1705 
1706  val = 0.5265*out1_1 + 0.2367*out2_1 + 0.2367*out2_2;
1707  out[badX0 + 2] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1708 
1709  val = 0.4804*out1_1 + 0.2598*out2_1 + 0.2598*out2_2;
1710  out[badX0 + 3] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1711 
1712  val = 0.4718*out1_1 + 0.2641*out2_1 + 0.2641*out2_2;
1713  out[badX0 + 4] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1714 
1715  val = 0.4708*out1_1 + 0.2646*out2_1 + 0.2646*out2_2;
1716  out[badX0 + 5] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1717 
1718  val = 0.4707*out1_1 + 0.2649*out2_1 + 0.2644*out2_2;
1719  out[badX1 - 5] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1720 
1721  val = 0.4702*out1_1 + 0.2690*out2_1 + 0.2608*out2_2;
1722  out[badX1 - 4] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1723 
1724  val = 0.4654*out1_1 + 0.3044*out2_1 + 0.2303*out2_2;
1725  out[badX1 - 3] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1726 
1727  val = 0.4380*out1_1 + 0.4778*out2_1 + 0.0842*out2_2;
1728  out[badX1 - 2] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1729 
1730  val = 0.3455*out1_1 + 0.9206*out2_1 - 0.2661*out2_2;
1731  out[badX1 - 1] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1732 
1733  val = 0.1673*out1_1 + 1.3452*out2_1 - 0.5125*out2_2;
1734  out[badX1] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1735 
1736  break;
1737  case 060002: /* ##...........#., <noise^2> = 0 */
1738  val = -0.5125*out1_2 + 1.3452*out1_1 + 0.1673*out2_1;
1739  out[badX0] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1740 
1741  val = -0.2661*out1_2 + 0.9206*out1_1 + 0.3455*out2_1;
1742  out[badX0 + 1] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1743 
1744  val = 0.0842*out1_2 + 0.4778*out1_1 + 0.4380*out2_1;
1745  out[badX0 + 2] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1746 
1747  val = 0.2303*out1_2 + 0.3044*out1_1 + 0.4654*out2_1;
1748  out[badX0 + 3] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1749 
1750  val = 0.2608*out1_2 + 0.2690*out1_1 + 0.4702*out2_1;
1751  out[badX0 + 4] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1752 
1753  val = 0.2644*out1_2 + 0.2649*out1_1 + 0.4708*out2_1;
1754  out[badX1 - 5] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1755 
1756  val = 0.2641*out1_2 + 0.2641*out1_1 + 0.4718*out2_1;
1757  out[badX1 - 4] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1758 
1759  val = 0.2598*out1_2 + 0.2598*out1_1 + 0.4804*out2_1;
1760  out[badX1 - 3] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1761 
1762  val = 0.2367*out1_2 + 0.2367*out1_1 + 0.5265*out2_1;
1763  out[badX1 - 2] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1764 
1765  val = 0.1673*out1_2 + 0.1673*out1_1 + 0.6654*out2_1;
1766  out[badX1 - 1] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1767 
1768  val = 0.0585*out1_2 + 0.0585*out1_1 + 0.8829*out2_1;
1769  out[badX1] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1770 
1771  break;
1772  default:
1773  //shFatal("Unsupported defect type: MIDDLE 0%o",defect[i].type);
1774  break; /* NOTREACHED */
1775  }
1776  break;
1777  case Defect::WIDE:
1780  if (defectPos == Defect::WIDE_NEAR_LEFT) {
1781  assert(badX0 >= 1);
1782 
1783  if (badX1 + 2 >= ncol) { /* left defect extends near
1784  right edge of data! */
1785  if (badX1 == ncol - 2) { /* one column remains */
1786  val = out[ncol - 1];
1787  } else {
1788  val = fallbackValue; /* there is no information */
1789  }
1790  for (int j = badX0; j <= badX1; j++) {
1791  out[j] = val;
1792  }
1793  break;
1794  }
1795  out1_2 = -1; /* NOTUSED */
1796  out2_2 = out[badX1 + 2];
1797  } else if (defectPos == Defect::WIDE) {
1798  assert(badX0 >= 2 && badX1 + 2 < ncol);
1799  out1_2 = out[badX0 - 2];
1800  out2_2 = out[badX1 + 2];
1801  } else if (defectPos == Defect::WIDE_NEAR_RIGHT) {
1802  assert(badX1 + 1 < ncol);
1803 
1804  if (badX0 < 2) { /* right defect extends near
1805  left edge of data! */
1806  if (badX0 == 1) { /* one column remains */
1807  val = out[0];
1808  } else {
1809  val = fallbackValue; /* there is no information */
1810  }
1811  for (int j = badX0; j <= badX1; j++) {
1812  out[j] = val;
1813  }
1814  break;
1815  }
1816  out1_2 = out[badX0 - 2];
1817  out2_2 = -1; /* NOTUSED */
1818  } else {
1819  //shFatal("Unknown defect classification %d (%s:%d)",defectPos, __FILE__,__LINE__);
1820  out1_2 = out2_2 = -1; /* NOTUSED */
1821  }
1822 
1823  out1_1 = out[badX0 - 1];
1824  out2_1 = out[badX1 + 1];
1825 
1826  switch (defectType) {
1827 
1828  case 06: /* #?#., <noise^2> = 0 */
1829  val = 0.8894*out1_1 + 0.1106*out2_1;
1830  out[badX0] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1831 
1832  val = 0.6839*out1_1 + 0.3161*out2_1;
1833  out[badX0 + 1] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1834 
1835  val = 0.5527*out1_1 + 0.4473*out2_1;
1836  out[badX0 + 2] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1837 
1838  val = 0.5092*out1_1 + 0.4908*out2_1;
1839  out[badX0 + 3] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1840 
1841  val = 0.5010*out1_1 + 0.4990*out2_1;
1842  out[badX0 + 4] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1843 
1844  val = 0.5001*out1_1 + 0.4999*out2_1;
1845  out[badX0 + 5] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1846 
1847  val = 0.5000*out1_1 + 0.5000*out2_1;
1848 
1849  for (int j = badX0 + 6; j < badX1 - 5; j++) {
1850  out[j] = val;
1851  }
1852 
1853  val = 0.4999*out1_1 + 0.5001*out2_1;
1854  out[badX1 - 5] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1855 
1856  val = 0.4990*out1_1 + 0.5010*out2_1;
1857  out[badX1 - 4] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1858 
1859  val = 0.4908*out1_1 + 0.5092*out2_1;
1860  out[badX1 - 3] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1861 
1862  val = 0.4473*out1_1 + 0.5527*out2_1;
1863  out[badX1 - 2] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1864 
1865  val = 0.3161*out1_1 + 0.6839*out2_1;
1866  out[badX1 - 1] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1867 
1868  val = 0.1106*out1_1 + 0.8894*out2_1;
1869  out[badX1] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1870 
1871  break;
1872  case 07: /* #?##, <noise^2> = 0 */
1873  val = 0.8829*out1_1 + 0.0585*out2_1 + 0.0585*out2_2;
1874  out[badX0] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1875 
1876  val = 0.6654*out1_1 + 0.1673*out2_1 + 0.1673*out2_2;
1877  out[badX0 + 1] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1878 
1879  val = 0.5265*out1_1 + 0.2367*out2_1 + 0.2367*out2_2;
1880  out[badX0 + 2] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1881 
1882  val = 0.4804*out1_1 + 0.2598*out2_1 + 0.2598*out2_2;
1883  out[badX0 + 3] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1884 
1885  val = 0.4718*out1_1 + 0.2641*out2_1 + 0.2641*out2_2;
1886  out[badX0 + 4] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1887 
1888  val = 0.4708*out1_1 + 0.2646*out2_1 + 0.2646*out2_2;
1889  out[badX0 + 5] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1890 
1891  val = 0.4707*out[badX0 - 1] + 0.2646*out[badX1 + 1] + 0.2646*out[badX1 + 2];
1892 
1893  for (int j = badX0 + 6; j < badX1 - 5; j++) {
1894  out[j] = val;
1895  }
1896 
1897  val = 0.4707*out1_1 + 0.2649*out2_1 + 0.2644*out2_2;
1898  out[badX1 - 5] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1899 
1900  val = 0.4702*out1_1 + 0.2690*out2_1 + 0.2608*out2_2;
1901  out[badX1 - 4] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1902 
1903  val = 0.4654*out1_1 + 0.3044*out2_1 + 0.2303*out2_2;
1904  out[badX1 - 3] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1905 
1906  val = 0.4380*out1_1 + 0.4778*out2_1 + 0.0842*out2_2;
1907  out[badX1 - 2] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1908 
1909  val = 0.3455*out1_1 + 0.9206*out2_1 - 0.2661*out2_2;
1910  out[badX1 - 1] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1911 
1912  val = 0.1673*out1_1 + 1.3452*out2_1 - 0.5125*out2_2;
1913  out[badX1] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1914 
1915  break;
1916  case 016: /* ##?#., <noise^2> = 0 */
1917  val = -0.5125*out1_2 + 1.3452*out1_1 + 0.1673*out2_1;
1918  out[badX0] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1919 
1920  val = -0.2661*out1_2 + 0.9206*out1_1 + 0.3455*out2_1;
1921  out[badX0 + 1] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1922 
1923  val = 0.0842*out1_2 + 0.4778*out1_1 + 0.4380*out2_1;
1924  out[badX0 + 2] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1925 
1926  val = 0.2303*out1_2 + 0.3044*out1_1 + 0.4654*out2_1;
1927  out[badX0 + 3] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1928 
1929  val = 0.2608*out1_2 + 0.2690*out1_1 + 0.4702*out2_1;
1930  out[badX0 + 4] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1931 
1932  val = 0.2644*out1_2 + 0.2649*out1_1 + 0.4707*out2_1;
1933  out[badX0 + 5] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1934 
1935  val = 0.2646*out1_2 + 0.2646*out1_1 + 0.4707*out2_1;
1936  val = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1937 
1938  for (int j = badX0 + 6; j < badX1 - 5; j++) {
1939  out[j] = val;
1940  }
1941 
1942  val = 0.2646*out1_2 + 0.2646*out1_1 + 0.4708*out2_1;
1943  out[badX1 - 5] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1944 
1945  val = 0.2641*out1_2 + 0.2641*out1_1 + 0.4718*out2_1;
1946  out[badX1 - 4] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1947 
1948  val = 0.2598*out1_2 + 0.2598*out1_1 + 0.4804*out2_1;
1949  out[badX1 - 3] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1950 
1951  val = 0.2367*out1_2 + 0.2367*out1_1 + 0.5265*out2_1;
1952  out[badX1 - 2] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1953 
1954  val = 0.1673*out1_2 + 0.1673*out1_1 + 0.6654*out2_1;
1955  out[badX1 - 1] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1956 
1957  val = 0.0585*out1_2 + 0.0585*out1_1 + 0.8829*out2_1;
1958  out[badX1] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1959 
1960  break;
1961  case 017: /* ##?##, S/N = infty */
1962  val = -0.5177*out1_2 + 1.3400*out1_1 + 0.0888*out2_1 + 0.0888*out2_2;
1963  out[badX0] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1964 
1965  val = -0.2768*out1_2 + 0.9098*out1_1 + 0.1835*out2_1 + 0.1835*out2_2;
1966  out[badX0 + 1] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1967 
1968  val = 0.0705*out1_2 + 0.4642*out1_1 + 0.2326*out2_1 + 0.2326*out2_2;
1969  out[badX0 + 2] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1970 
1971  val = 0.2158*out1_2 + 0.2899*out1_1 + 0.2472*out2_1 + 0.2472*out2_2;
1972  out[badX0 + 3] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1973 
1974  val = 0.2462*out1_2 + 0.2544*out1_1 + 0.2497*out2_1 + 0.2497*out2_2;
1975  out[badX0 + 4] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1976 
1977  val = 0.2497*out1_2 + 0.2503*out1_1 + 0.2500*out2_1 + 0.2500*out2_2;
1978  out[badX0 + 5] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1979 
1980  val = 0.2500*out1_2 + 0.2500*out1_1 + 0.2500*out2_1 + 0.2500*out2_2;
1981  val = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1982 
1983  for (int j = badX0 + 6; j < badX1 - 5; j++) {
1984  out[j] = val;
1985  }
1986 
1987  val = 0.2500*out1_2 + 0.2500*out1_1 + 0.2503*out2_1 + 0.2497*out2_2;
1988  out[badX1 - 5] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1989 
1990  val = 0.2497*out1_2 + 0.2497*out1_1 + 0.2544*out2_1 + 0.2462*out2_2;
1991  out[badX1 - 4] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1992 
1993  val = 0.2472*out1_2 + 0.2472*out1_1 + 0.2899*out2_1 + 0.2158*out2_2;
1994  out[badX1 - 3] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1995 
1996  val = 0.2326*out1_2 + 0.2326*out1_1 + 0.4642*out2_1 + 0.0705*out2_2;
1997  out[badX1 - 2] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
1998 
1999  val = 0.1835*out1_2 + 0.1835*out1_1 + 0.9098*out2_1 - 0.2768*out2_2;
2000  out[badX1 - 1] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
2001 
2002  val = 0.0888*out1_2 + 0.0888*out1_1 + 1.3400*out2_1 - 0.5177*out2_2;
2003  out[badX1] = (val < min) ? 0.5*(out1_1 + out2_1) : val;
2004 
2005  break;
2006  default:
2007  //shFatal("Unsupported defect type: WIDE 0%o",defect[i].type);
2008  break; /* NOTREACHED */
2009  }
2010  break;
2011  }
2012  }
2013 }
2014 
2015 template<typename MaskT>
2016 static void do_defects(std::vector<Defect::Ptr> const & badList, // list of bad things
2017  int const y, // Row that we should fix
2018  MaskT& mask, // mask to set
2019  typename MaskT::Pixel const interpBit, // bit to set for bad pixels
2020  bool useFallbackValueAtEdge, // use fallbackValue at edge of chip?
2021  int nUseInterp // no. of pixels to interpolate towards edge
2022  )
2023 {
2024  typename MaskT::x_iterator mask_row = mask.row_begin(y); // pointer to this row of mask
2025 
2026  for (DefectCIter ptr = badList.begin(), end = badList.end(); ptr != end; ++ptr) {
2027  Defect::Ptr const defect = *ptr;
2028 
2029  if (y < defect->getY0() || y > defect->getY1()) {
2030  continue;
2031  }
2032 
2033  int const badX0 = defect->getX0();
2034  int const badX1 = defect->getX1();
2035 
2036  for (int c = badX0; c <= badX1; ++c) {
2037  mask_row[c] |= interpBit;
2038  }
2039  }
2040 }
2041 
2042 /************************************************************************************************************/
2043 
2044 namespace {
2045  template<typename T>
2046  struct Sort_ByX0 : public std::binary_function<std::shared_ptr<T> const, std::shared_ptr<T> const, bool> {
2047  bool operator() (std::shared_ptr<T> const a, std::shared_ptr<T> const b) const {
2048  return a->getX0() < b->getX0();
2049  }
2050  };
2051 }
2052 
2056 template<typename MaskedImageT>
2057 void interpolateOverDefects(MaskedImageT& mimage,
2058  lsst::afw::detection::Psf const &,
2059  std::vector<Defect::Ptr> &_badList,
2060  double fallbackValue,
2061  bool useFallbackValueAtEdge
2062  ) {
2063 /*
2064  * Allow for image's origin
2065  */
2066  int const width = mimage.getWidth();
2067  int const height = mimage.getHeight();
2068 
2069  std::vector<Defect::Ptr> badList;
2070  badList.reserve(_badList.size());
2071  for (std::vector<Defect::Ptr>::iterator ptr = _badList.begin(), end = _badList.end(); ptr != end; ++ptr) {
2072  geom::BoxI bbox = (*ptr)->getBBox();
2073  bbox.shift(geom::ExtentI(-mimage.getX0(), -mimage.getY0())); //allow for image's origin
2074  geom::PointI min = bbox.getMin(), max = bbox.getMax();
2075  if(min.getX() >= width){
2076  continue;
2077  } else if (min.getX() < 0) {
2078  if (max.getX() < 0) {
2079  continue;
2080  } else {
2081  min.setX(0);
2082  }
2083  }
2084 
2085  if (max.getX() < 0) {
2086  continue;
2087  } else if (max.getX() >= width) {
2088  max.setX(width - 1);
2089  }
2090 
2091  bbox = geom::BoxI(min, max);
2092  Defect::Ptr ndefect(new Defect(bbox));
2093  ndefect->classify((*ptr)->getPos(), (*ptr)->getType());
2094  badList.push_back(ndefect);
2095  }
2096 
2097  sort(badList.begin(), badList.end(), Sort_ByX0<Defect>());
2098 /*
2099  * Go through the frame looking at each pixel (except the edge ones which we ignore)
2100  */
2101  typename MaskedImageT::Mask::Pixel const interpBit =
2102  mimage.getMask()->getPlaneBitMask("INTRP"); // interp'd pixels
2103 
2104  constexpr int nUseInterp = 6; // no. of pixels to interpolate towards edge
2105  static_assert(nUseInterp < Defect::WIDE_DEFECT, "make sure that we can handle these defects using"
2106  "the full interpolation not edge code");
2107 
2108  for (int y = 0; y != height; y++) {
2109  std::vector<Defect::Ptr> badList1D = classify_defects(badList, y, width);
2110 
2111  do_defects(badList1D, y, *mimage.getImage(),
2112  -std::numeric_limits<typename MaskedImageT::Image::Pixel>::max(),
2113  fallbackValue, useFallbackValueAtEdge, nUseInterp);
2114 
2115  do_defects(badList1D, y, *mimage.getMask(), interpBit, useFallbackValueAtEdge, nUseInterp);
2116 
2117  do_defects(badList1D, y, *mimage.getVariance(),
2118  -std::numeric_limits<typename MaskedImageT::Image::Pixel>::max(),
2119  fallbackValue, useFallbackValueAtEdge, nUseInterp);
2120  }
2121 }
2122 
2123 /*****************************************************************************/
2133 template <typename MaskedImageT>
2134 std::pair<bool, typename MaskedImageT::Image::Pixel> interp::singlePixel(
2135  int,
2136  int,
2137  MaskedImageT const&,
2138  bool,
2139  double
2140  )
2141 {
2142 #if defined(SDSS)
2143  BADCOLUMN defect; /* describe a bad column */
2144  PIX *data; /* temp array to interpolate in */
2145  int i;
2146  int i0, i1; /* data corresponds to range of
2147  {row,col} == [i0,i1] */
2148  int ndata; /* dimension of data */
2149  static int ndatamax = 40; /* largest allowable defect. XXX */
2150  int nrow, ncol; /* == reg->n{row,col} */
2151  PIX *val; /* pointer to pixel (rowc, colc) */
2152  int z1, z2; /* range of bad {row,columns} */
2153 
2154  shAssert(badmask != NULL && badmask->type == shTypeGetFromName("OBJMASK"));
2155  shAssert(reg != NULL && reg->type == TYPE_PIX);
2156  nrow = reg->nrow;
2157  ncol = reg->ncol;
2158 
2159  if (horizontal) {
2160  for (z1 = colc - 1; z1 >= 0; z1--) {
2161  if (!phPixIntersectMask(badmask, z1, rowc)) {
2162  break;
2163  }
2164  }
2165  z1++;
2166 
2167  for (z2 = colc + 1; z2 < ncol; z2++) {
2168  if (!phPixIntersectMask(badmask, z2, rowc)) {
2169  break;
2170  }
2171  }
2172  z2--;
2173 
2174  i0 = (z1 > 2) ? z1 - 2 : 0; /* origin of available required data */
2175  i1 = (z2 < ncol - 2) ? z2 + 2 : ncol - 1; /* end of " " " " */
2176 
2177  if (i0 < 2 || i1 >= ncol - 2) { /* interpolation will fail */
2178  return(-1); /* failure */
2179  }
2180 
2181  ndata = (i1 - i0 + 1);
2182  if (ndata > ndatamax) {
2183  return(-1); /* failure */
2184  }
2185 
2186  data = alloca(ndata*sizeof(PIX));
2187  for (i = i0; i <= i1; i++) {
2188  data[i - i0] = reg->ROWS[rowc][i];
2189  }
2190  val = &data[colc - i0];
2191  } else {
2192  for (z1 = rowc - 1; z1 >= 0; z1--) {
2193  if (!phPixIntersectMask(badmask, colc, z1)) {
2194  break;
2195  }
2196  }
2197  z1++;
2198 
2199  for (z2 = rowc + 1; z2 < nrow; z2++) {
2200  if (!phPixIntersectMask(badmask, colc, z2)) {
2201  break;
2202  }
2203  }
2204  z2--;
2205 
2206  i0 = (z1 > 2) ? z1 - 2 : 0; /* origin of available required data */
2207  i1 = (z2 < nrow - 2) ? z2 + 2 : nrow - 1; /* end of " " " " */
2208 
2209  if (i0 < 2 || i1 >= ncol - 2) { /* interpolation will fail */
2210  return(-1); /* failure */
2211  }
2212 
2213  ndata = (i1 - i0 + 1);
2214  if (ndata > ndatamax) {
2215  return(-1); /* failure */
2216  }
2217 
2218  data = alloca(ndata*sizeof(PIX));
2219  for (i = i0; i <= i1; i++) {
2220  data[i - i0] = reg->ROWS[i][colc];
2221  }
2222  val = &data[rowc - i0];
2223  }
2224 
2225  defect.x1 = z1 - i0;
2226  defect.x2 = z2 - i0;
2227  classify_defects(&defect, 1, ndata);
2228  do_defect(&defect, 1, data, ndata, minval);
2229 
2230  return(*val);
2231 #endif
2232 
2233  return std::make_pair(false, std::numeric_limits<typename MaskedImageT::Image::Pixel>::min());
2234 }
2235 
2236 /************************************************************************************************************/
2237 //
2238 // Explicit instantiations
2239 //
2240 // \cond
2241 
2242 typedef float ImagePixel;
2243 
2244 template
2245 void interpolateOverDefects(image::MaskedImage<ImagePixel, image::MaskPixel> &image,
2246  lsst::afw::detection::Psf const &, std::vector<Defect::Ptr> &badList, double, bool
2247  );
2248 template
2249 std::pair<bool, ImagePixel> interp::singlePixel(int x, int y,
2250  image::MaskedImage<ImagePixel, image::MaskPixel> const& image,
2251  bool horizontal, double minval);
2252 //
2253 // Why do we need double images?
2254 //
2255 #if 1
2256 template
2257 void interpolateOverDefects(image::MaskedImage<double, image::MaskPixel> &image,
2258  lsst::afw::detection::Psf const &, std::vector<Defect::Ptr> &badList, double, bool
2259  );
2260 
2261 template
2262 std::pair<bool, double> interp::singlePixel(int x, int y,
2263  image::MaskedImage<double, image::MaskPixel> const& image,
2264  bool horizontal, double minval);
2265 
2266 #endif
2267 // \endcond
2268 
2269 }}} // lsst::meas::algorithms
defect is wide at right boundary
Definition: Interp.h:83
defect is in middle, and wide
Definition: Interp.h:80
ImageT val
Definition: CR.cc:158
defect is in middle of frame
Definition: Interp.h:78
defect is near right boundary
Definition: Interp.h:82
std::vector< Defect::Ptr >::const_iterator DefectCIter
Definition: Interp.cc:52
afw::table::Key< double > b
defect is at left boundary
Definition: Interp.h:75
defect is near right, and wide
Definition: Interp.h:81
defect is wide at left boundary
Definition: Interp.h:77
defect is near left, and wide
Definition: Interp.h:79
std::shared_ptr< Defect > Ptr
shared pointer to Defect
Definition: Interp.h:72
std::pair< bool, typename MaskedImageT::Image::Pixel > singlePixel(int x, int y, MaskedImageT const &image, bool horizontal, double minval)
Return a boolean status (true: interpolation is OK) and the interpolated value for a pixel...
Definition: Interp.cc:2134
defect is near left boundary
Definition: Interp.h:76
void interpolateOverDefects(MaskedImageT &image, lsst::afw::detection::Psf const &psf, std::vector< Defect::Ptr > &badList, double fallbackValue=0.0, bool useFallbackValueAtEdge=false)
Process a set of known bad pixels in an image.
Definition: Interp.cc:2057
defect is at right boundary
Definition: Interp.h:84
Encapsulate information about a bad portion of a detector.
Definition: Interp.h:70