@@ -701,6 +701,7 @@ def get(
701701 seqNum : int ,
702702 doSubtractMedian : bool = True ,
703703 columnMaskK : float = 50.0 ,
704+ biasPercentile : float = 10.0 ,
704705 scienceDetNum : int = 94 ,
705706 ) -> GuiderData :
706707 """
@@ -713,9 +714,12 @@ def get(
713714 seqNum : `int`
714715 Sequence number.
715716 doSubtractMedian : `bool`, optional
716- If True, subtract median row bias from each stamp.
717+ If True, subtract column bias from each stamp.
717718 columnMaskK : `float`, optional
718719 Threshold factor for column mask detection.
720+ biasPercentile : `float`, optional
721+ Percentile (0-100) for column bias estimation.
722+ Lower values avoid star/trail contamination.
719723 scienceDetNum : `int`, optional
720724 Science detector number for WCS reference.
721725
@@ -748,6 +752,7 @@ def get(
748752 rawStampsDict ,
749753 doSubtractMedian ,
750754 columnMaskK ,
755+ biasPercentile ,
751756 )
752757 guiderData = GuiderData (
753758 seqNum = seqNum ,
@@ -797,19 +802,22 @@ def processStamps(
797802 rawStampsDict : dict [str , Stamps ],
798803 doSubtractMedian : bool ,
799804 columnMaskK : float ,
805+ biasPercentile : float = 10.0 ,
800806 ) -> dict [str , Stamps ]:
801807 """
802- Apply median row bias subtraction and per-stamp column masking.
808+ Apply column bias subtraction and per-stamp column masking.
803809
804810
805811 Parameters
806812 ----------
807813 rawStampsDict : `dict[str, Stamps]`
808814 ROI view of stamps from butler `guider_raw`.
809815 doSubtractMedian : `bool`, optional
810- If True, subtract median row bias.
816+ If True, subtract column bias.
811817 columnMaskK : `float`, optional
812818 Threshold factor for column mask detection.
819+ biasPercentile : `float`, optional
820+ Percentile for column bias estimation.
813821
814822 Returns
815823 -------
@@ -829,23 +837,28 @@ def processStamps(
829837 # Work on a copy - never modify original
830838 data = stamps [i ].stamp_im .image .array .copy ()
831839
832- # Compute median row bias
833- medianRows = np .nanmedian (data , axis = 0 )
840+ # Compute column bias using low percentile to avoid
841+ # star contamination (median pulls dark dips at star cols).
842+ percRows = np .nanpercentile (data , biasPercentile , axis = 0 )
843+ rPerc = np .nanpercentile (data , biasPercentile )
834844 medianValue = np .nanmedian (data )
835- # Replace NaN medians (fully masked columns) with global median
836- medianRows = np .where (np .isnan (medianRows ), medianValue , medianRows )
845+ # Replace NaN values (fully masked columns) with global median
846+ percRows = np .where (np .isnan (percRows ), medianValue , percRows )
837847
838848 # Compute column mask on bias-subtracted data
839- colMask = getColumnMask (data - medianRows [np .newaxis , :], k = columnMaskK )
849+ colMask = getColumnMask (
850+ data - percRows [np .newaxis , :] - (rPerc - medianValue ),
851+ k = columnMaskK ,
852+ )
840853
841854 # Create mask array for MaskedImageF (BAD=1 for masked cols)
842855 nRows , nCols = data .shape
843856 maskArray = np .zeros ((nRows , nCols ), dtype = np .uint32 )
844857 maskArray [colMask ] = 1 # Set BAD bit for masked columns
845858
846- # Apply median row bias subtraction
859+ # Apply column bias subtraction
847860 if doSubtractMedian :
848- data = data - medianRows [np .newaxis , :]
861+ data = data - percRows [np .newaxis , :] - ( rPerc - medianValue )
849862
850863 # Fill masked columns with global median
851864 if colMask .any ():
0 commit comments