559def electrostaticBrighterFatterCorrection(exposure, electroBfDistortionMatrix, applyGain, gains=None):
560 """
561 Evaluates the correction of CCD images affected by the
562 brighter-fatter effect, as described in
563 https://arxiv.org/abs/2301.03274. Requires as input the result of
564 an electrostatic fit to flat covariance data (or any other
565 determination of pixel boundary shifts under the influence of a
566 single electron).
567
568 The filename refers to an input tuple that contains the
569 boundary shifts for one electron. This file is produced by an
570 electrostatic fit to data extracted from flat-field statistics,
571 implemented in https://gitlab.in2p3.fr/astier/bfptc/tools/fit_cov.py.
572 """
573
574
575 r = electroBfDistortionMatrix.fitRange - 1
576 aN = electroBfDistortionMatrix.aN
577 aS = electroBfDistortionMatrix.aS
578 aE = electroBfDistortionMatrix.aE
579 aW = electroBfDistortionMatrix.aW
580
581
582 kN = np.zeros((2 * r + 1, 2 * r + 1))
583 kE = np.zeros_like(kN)
584
585
586 kN[r:, r:] = aN
587 kN[:r+1, r:] = np.flipud(aN)
588 kN[r:, :r+1] = np.fliplr(aS)
589 kN[:r+1, :r+1] = np.flipud(np.fliplr(aS))
590
591
592 kE[r:, r:] = aE
593 kE[:r+1, r:] = np.flipud(aW)
594 kE[r:, :r+1] = np.fliplr(aE)
595 kE[:r+1, :r+1] = np.flipud(np.fliplr(aW))
596
597
598 kN[:, 0] = -kN[:, -1]
599 kE[0, :] = -kE[-1, :]
600
601
602
603
604
605
606 kN *= 0.25
607 kE *= 0.25
608
609
610
611 kN = kN.T
612 kE = kE.T
613
614
615 image = exposure.getMaskedImage().getImage()
616
617
618 with gainContext(exposure, image, applyGain, gains):
619
620
621
622 im = image.getArray().copy()
623 convolver = CustomFFTConvolution(im, kN)
624 convolutions = convolver(im, [kN, kE])
625
626
627
628
629 delta = np.zeros_like(im)
630 boundaryCharge = np.zeros_like(im)
631
632
633
634
635 boundaryCharge[:-1, :] = im[1:, :] + im[:-1, :]
636
637
638
639
640
641
642 dq = boundaryCharge * convolutions[0]
643 delta += dq
644
645
646 delta[1:, :] -= dq[:-1, :]
647
648
649 boundaryCharge = np.zeros_like(im)
650 boundaryCharge[:, :-1] = im[:, 1:] + im[:, :-1]
651 dq = boundaryCharge * convolutions[1]
652 delta += dq
653
654
655 delta[:, 1:] -= dq[:, :-1]
656
657
658
659
660 exposure.image.array -= delta
661
662 return exposure