<SYSTEM_TASK:>
Given the following text description, write Python code to implement the functionality described below step by step
<END_TASK>
<USER_TASK:>
Description:
 Bias Ramps
The "bias ramps" were large gradients along detector columns in 2015 data, particularly in CCD3 (and also CCD2 to some degree). The gradients could be as large as 50 ADU in dynamic range. I searched for these gradients in bias frames taken in 2015 and 2016 by taking a slice along rows near the center of each amplifier image, collapsing along columns with a median to get an average 1D row profile, and then smoothing that profile further with a gaussian filter. The 'sliceRangeAdu' is the difference between the maximum and minimum of this smoothed profile.
The improvement from 2015 to 2016 is clear.
Step1:  Joe F. found that the gradient features do still exist in 2016 biases, by visually inspecting all of the bias images. They are, however, at a very low frequency (few percent) and a much lower amplitude (~20 ADU for IM9)
Step2:  Bias roll-off
A "feature" where the bias counts drop considerably at the edge of the image. Only observed to occur during bias sequences. The frequency has dropped from ~27% to ~2%.
<ASSISTANT_TASK:>
Python Code:
for ccdNum in [2,3]:
    exts = 4*(ccdNum-1) + arange(1,5)
    figure(figsize=(10,6))
    for pnum,ext in enumerate(exts,start=1):
        subplot(2,2,pnum)
        for t,lbl,clr in zip([t15,t16],#,s15[b15],s16[b16],s15[o15],s16[o16]],
                             ['2015','2016'],#,'2015b','2016b','2015o','2016o'],
                             'gbcrmk'):
            hist(t['sliceRangeAdu'][:,ext-1].compressed(),30,(0,60),normed=True,
                 histtype='step',label=lbl,color=clr)
        title('HDU[%d]'%ext)
        legend(loc='upper right',ncol=3,fontsize=9)
    figtext(0.5,0.01,'Range of pixels in bias center slice [ADU]',ha='center')
Explanation: Bias Ramps
The "bias ramps" were large gradients along detector columns in 2015 data, particularly in CCD3 (and also CCD2 to some degree). The gradients could be as large as 50 ADU in dynamic range. I searched for these gradients in bias frames taken in 2015 and 2016 by taking a slice along rows near the center of each amplifier image, collapsing along columns with a median to get an average 1D row profile, and then smoothing that profile further with a gaussian filter. The 'sliceRangeAdu' is the difference between the maximum and minimum of this smoothed profile.
The improvement from 2015 to 2016 is clear.
End of explanation
def check_ext(t,ext,badval=None):
    j = ext-1
    print "MIN: ",t['sliceRangeAdu'][:,j].min()
    print "MAX: ",t['sliceRangeAdu'][:,j].max()
    m = sigma_clip(t['sliceRangeAdu'][:,j]).mean()
    s = sigma_clip(t['sliceRangeAdu'][:,j]).std()
    print "MEAN: ",m
    print "STD: ",s
    nbias = (~t['sliceRangeAdu'][:,j].mask).sum()
    if badval is None: badval = m+5*s
    bad = t['sliceRangeAdu'][:,j] > badval
    print "BAD: %d/%d = %.2f%%" % (sum(bad),nbias,100*float(sum(bad))/nbias)
    return where(bad.filled(False))[0]
# IM9
print '---- 2015 ----'
_ = check_ext(t15,9,badval=10)
#_ = check_ext(s15[b15],9,badval=10)
#_ = check_ext(s15[o15],9,badval=10)
print '---- 2016 ----'
ii = check_ext(t16,9)
#_ = check_ext(s16[b16],9)
#_ = check_ext(s16[o16],9)
# the offending biases
print t16['fileName'][ii]
# IM5
print '---- 2015 ----'
ii = check_ext(t15,8,badval=10)
print '---- 2016 ----'
ii = check_ext(t16,8)
# the offending biases
print t16['fileName'][ii]
Explanation: Joe F. found that the gradient features do still exist in 2016 biases, by visually inspecting all of the bias images. They are, however, at a very low frequency (few percent) and a much lower amplitude (~20 ADU for IM9):
End of explanation
def count_rolloffs(t):
    nbias = (~t['dropFlag'].mask).sum(axis=0)
    froll = t['dropFlag'].sum(axis=0)/nbias.astype(float)
    return froll
f15 = count_rolloffs(t15)
f16 = count_rolloffs(t16)
f15b = count_rolloffs(s15[b15])
f16b = count_rolloffs(s16[b16])
f15o = count_rolloffs(s15[o15])
f16o = count_rolloffs(s16[o16])
#froll = Table([arange(1,17),f15,f16,f15b,f16b,f15o,f16o],
#              names=['hduNum','freq2015','freq2016','b15','b16','o15','o16'])
froll = Table([arange(1,17),f15,f16,f15o,f16o],
              names=['hduNum','freq2015(bias)','freq2016(bias)',
                     'freq2015(obj)','freq2016(obj)'])
for col in froll.itercols(): 
    if col.name != 'hduNum': 
        col.format='%.4f'
print(froll)
Explanation: Bias roll-off
A "feature" where the bias counts drop considerably at the edge of the image. Only observed to occur during bias sequences. The frequency has dropped from ~27% to ~2%.
End of explanation
<END_TASK>