0001 % This script processes light, flat, dark, and bias frames into master light,
0002 % flat, dark, and bias frames. The master frames are saved as .mat files. A
0003 % master bias frame is only necessary if you are interested in scaling a dark
0004 % frame to better match the dark current in a light frame. The flat frame is
0005 % demosaiced, desaturated (made gray), normalized, then re-mosaiced. The flat
0006 % frame is demosaiced because it is easier to desaturate it in this form; it is
0007 % re-mosaiced because it is less computationally intense to flat correct a light
0008 % frame when it is still a Bayer raw.
0009 %
0010 
0011 initialize_spectrometer_workspace
0012 
0013 dir_lightdarks = [so.bd s 'dark_frames' s 'light_darks' s so.exposure s so.ftype];
0014 dir_flatdarks = [so.bd s 'dark_frames' s 'flat_darks' s so.ftype];
0015 dir_flats = [so.bd s 'flat_frames' s so.ftype];
0016 dir_bias = [so.bd s 'bias_frames' s so.ftype];
0017 
0018 g = waitbar(0, ['Processing ' so.ftype ' dark, flat, and bias frames. ' ...
0019                 'This may take several minutes.']);
0020 waitbar(0.001, g); % Octave's buggy waitbar doesn't like 0 or 1
0021 wblen = 6;
0022 
0023 waitbar(1/wblen, g);
0024 dark = ensemble_average(dir_lightdarks);
0025 waitbar(2/wblen, g);
0026 
0027 FD = ensemble_average(dir_flatdarks);
0028 waitbar(3/wblen, g);
0029 F = ensemble_average(dir_flats);
0030 F = F - FD;
0031 waitbar(4/wblen, g); % finished processing darks and flats
0032 
0033 if strcmpi(so.ftype, 'PGM')
0034     F = bayer_demosaic(F); % separate Bayer raw into channels
0035 
0036     % shift each channel's average gray level so that they are all the same,
0037     % by using the green channel's gray level, mn(2), as a reference.
0038     mn = reshape(image_mean(F), [1 1 3]);
0039     mn_shift = repmat(mn(2)-mn, [size(F,1), size(F,2), 1]);
0040     Fgray = F + mn_shift;
0041 
0042     mx = max(Fgray(:));
0043     Fnormal = Fgray./mx;
0044     % re-mosaic so flat frame correction can be performed on Bayer raws,
0045     % which is less computationally intense.
0046     F = bayer_mosaic(Fnormal);
0047 else
0048     % shift each channel's average gray level so that they are all the same,
0049     % by using the green channel's gray level, mn(2), as a reference.
0050     mn = reshape(image_mean(F), [1 1 3]);
0051     mn_shift = repmat(mn(2)-mn, [size(F,1), size(F,2), 1]);
0052     Fgray = F + mn_shift;
0053 
0054     mx = max(Fgray(:));
0055     Fnormal = Fgray./mx;
0056     F = Fnormal;
0057 end
0058 flat = F;
0059 clear F FD Fgray Fnormal;
0060 
0061 bias = ensemble_average(dir_bias);
0062 waitbar(5/wblen, g);
0063 
0064 %save calibration frames
0065 [ign, pdirpath] = pop_dirname(dir_lightdarks);
0066 [ign, pdirpath] = pop_dirname(pdirpath);
0067 matname = [so.ftype '_master_dark_' so.exposure '.mat'];
0068 save('-V6', [pdirpath s matname], 'dark');
0069 
0070 [ign, pdirpath] = pop_dirname(dir_flats);
0071 matname = [so.ftype '_master_flat.mat'];
0072 save('-V6', [pdirpath s matname], 'flat');
0073 
0074 [ign, pdirpath] = pop_dirname(dir_bias);
0075 matname = [so.ftype '_master_bias.mat'];
0076 save('-V6', [pdirpath s matname], 'bias');
0077 
0078 waitbar((6/wblen)-0.001, g);
0079 
0080 disp('')
0081 disp([mfilename() ' finished.'])
0082 clear all