function [ceil_utc,ceil_date,ceil_range,ceil_b,cloudcode,cloud1,cloud2,cloud3,ceilo_15_sec]=load_CL31_BigSur_2018(date,ceil_filename)
% LCload_CL31: load a Lidar Ceilometer CL31 file and return time series of
% cloud heights and a time-height series of backscatter.
%
% USAGE:
%  [ceil_utc,ceil_date,ceil_range,ceil_b,cloud1,cloud2,cloud3,ceilo_15_sec]=LCload_CL31(date,ceil_filename);
%
% INPUTS: 
%    date=[yyyy mm dd];
%    ceil_filename is the full-path name of the file to load
% OUTPUTS:
%    ceil_utc is the time in decimal hours of each day
%    ceil_date is the date of each ray as a float that looks like yyyymmdd 
%    ceil_range is the range of each gate in metres
%    ceil_b is the backscatter coefficient in the units (srad km)**(-1)
%    cloud1, cloud2 and cloud3 are the heights of the first three cloud
%         bases as determined by the CL31 data aquisition system from
%         the backscatter profile.
%
% AUTHORS:
% Dana, Chris, Dan, Ludovic, and Simon
% 
% 2008 September 17
% -eliminated hex2dec calls, sped code up ~30x
% -declared temporary arrays in fast orientation, truncated at end of read
% -fixed feet/meters unit conversion
% -cleaned up loop and logic
% -fixed 2's complement unwrapping for 20-bit integers
% -reads range gates from file
% -returns ceil_b in VOLUME BACKSCATTER COEFFICIENT (p.75 CL31 manual)
% -alarms flagged with cloudcode=-1

% %for testing:
%  clear; close all;
%  date=[2007 10 17];
%  ceil_filename='C:\Data\STRATUS_2007\RHB\ceilometer\Raw\A7101700.DAT';

nbits=20; % number of bits for reflectivity
resolution=10; %10m resolution, to be updated from file
gates_number=770;  %number of gates, to be updated from file
%resolution*gates_number;   %10m x 770 samples, range 7700m (ms1_10x770)
nn=7000; %largest possible number of samples --should be exactly 5760 samples, but who knows?
start_height = 0; % in m % SPdeS ?should be height of ceilometer on deck?

% fix single digit years in date (e.g. 7-->2007):
if date(1)<70
    date(1)=date(1)+2000;
elseif date(1)>=70 && date(1)<1000
    date(1)=date(1)+1900;
end

ceil_year=date(1);
ceil_month=date(2);
ceil_day=date(3);

% Declare Arrays
% transposed for faster indexing, SPdeS
% Since we don't know the final size, 
% use temp arrays and truncate copy to final arrays at end.
tempcloud1=NaN+zeros(nn,1);
tempcloud2=NaN+zeros(nn,1);
tempcloud3=NaN+zeros(nn,1);
tempcloudcode=NaN+zeros(nn,1);

tempceil_sec=NaN+zeros(nn,1);
tempceil_min=NaN+zeros(nn,1);
tempceil_hour=NaN+zeros(nn,1);
tempceil_b=NaN+zeros(gates_number,nn);

% open file
fid=fopen(ceil_filename,'r');
if fid == -1
    error(['Cannot read ' ceil_filename]);
end

% frewind(fid) % start reading at top of file here
% dump header
dmp=fgetl(fid);   %dump line -Ceilometer Logfile
dmp1=fgetl(fid);  %dump line -File created: 2/24/2007 12:00:00 AM

% Start gargantuan read loop
k=0; % count time samples
while ~feof(fid)
    %for pp = 1:20  % short loop for testing
    if strcmp(fscanf(fid,'%s',[1 1]),'-File'); break; end; %dump -2007-02-24 and break on last '-File Closed:' line
    k=k+1;
    time=fscanf(fid,'%2d:%2d:%2d',[3 1]); %dump date, read hh:mm:ss
    if ~isempty(time);% catch other errors and empty at last line of file
        tempceil_hour(k)=time(1);
        tempceil_min(k)=time(2);
        tempceil_sec(k)=time(3);

        fgetl(fid);       %go to end of line
        temp=fgetl(fid);  %get rid of CL017121
        %range_flag=str2num(temp(8));
        tempht=fgetl(fid); %cloud base heights
        if tempht(1)=='/' || tempht(2)=='A' % Alarms present!
            tempcloudcode(k)=-1; % flag error
        else % no alarms present
            tempcloudcode(k)=sscanf(tempht(1:2),'%1d%*1c'); % data is number of clouds detected: 0,1,2, or 3
            if tempcloudcode(k) < 4 % codes 4:fully obscured, no base detected; 5:some obscuration, but determined transparent
                if tempcloudcode(k) > 0
                    tempcloud1(k)=sscanf(tempht(4:20),'%5d',1);
                    if tempcloudcode(k) > 1
                        tempcloud2(k)=sscanf(tempht(10:20),'%5d',1);
                        if tempcloudcode(k) == 3
                            tempcloud3(k)=sscanf(tempht(16:20),'%5d',1);
                        end
                    end
                end
            end
        end % no alarms present
        % position 21 is a space before the detection status bits in 12
        if k<2 % only check detection status once per file
            Detection_status=tempht(22:22+12-1); % hexadecimal digits
            units_bit=sscanf(Detection_status(11),'%1x',1)>7;
            % units_bit true if meters; see table of hexadecimal digits and detection bits in ceilo manual
            if units_bit  %units in cloud heights line are meters
                mm=1;     %no conversion coefficient
            else          %units in cloud heights line are feet
                mm=0.303; %conversion coefficient from feet to meters
            end;
        end
        line2p5=fgetl(fid); % line2.5: -1 ///  0 ///  0 ///  0 ///  0 ///
        line3=fgetl(fid);   % line3: 00100 10 0770 100 +28 097 02 0005 L0016HN15 238
        if k<2 % update scale and resolution once per file
            scaleres=sscanf(line3,'%5d %2d %4d');
            scale=scaleres(1)/100;
            resolution=scaleres(2);
            gates_number=scaleres(3);
        end
        % read the long line of ranged data...
        line = fgetl(fid);
        if size(line,2)==5*gates_number
            tempceil_b(:,k)=sscanf(line,'%5x');
        else
            tempceil_b(:,k)=NaN;
        end;
    end %if ~isempty(time)
    fgetl(fid); % dump 6 character line
    fgetl(fid);  %get rid of blank line (if k>1?)
end % while

fclose(fid);

% truncate data  x=tempx(1:k)
ceil_b=tempceil_b(:,1:k);
% wrap 2s complement for nbits=20
ceil_b2=ceil_b;
index=find(ceil_b>=2^(nbits-1));
if ~isempty(index), ceil_b2(index)=ceil_b(index)-2^nbits;end
% % for comparison puposes, compute backscatter with wrong 16-bit 2s complement
% ceil_bwrong=ceil_b;
% ceil_bwrong(ceil_b>=2^15)=ceil_b(ceil_b>=2^15)-2^16;
% ceil_bwrong=ceil_bwrong*1e-5;

if scale==1
    ceil_b=ceil_b2*1e-5; % scaled by default in units 1e5/(km srad)
else
    ceil_b=ceil_b2*scale*1e-5;
end
% ceil_b is now VOLUME BACKSCATTER COEFFICIENT [units 1/(km*steradians)].
% It is the extinction-normalized power backward-scattered per
% atmospheric scattering volume drdOmega [m*srad]. This is
% related to the power transmitted and recieved at the instrument
% by the lidar equation (CL31 manual p. 75).
% In practice it is sometimes negative, presumably because of noise.

% convert units to meters if necessary
if ~units_bit
    cloud1=tempcloud1(1:k)*mm;    %feet to meters
    cloud2=tempcloud2(1:k)*mm;
    cloud3=tempcloud3(1:k)*mm;
else
    cloud1=tempcloud1(1:k);
    cloud2=tempcloud2(1:k);
    cloud3=tempcloud3(1:k);
end
cloudcode=tempcloudcode(1:k);
ceil_sc=tempceil_sec(1:k);
ceil_mn=tempceil_min(1:k);
ceil_hr=tempceil_hour(1:k);
ceil_utc=tempceil_hour(1:k)+tempceil_min(1:k)/60.0+tempceil_sec(1:k)/3600.0;
ceil_date(1:k,1)=ceil_year*10000+ceil_month*100+ceil_day;

ceil_range=(start_height+(1:gates_number)*resolution)/1000.0; % km

% % plot
% %subplot(2,1,1)
% imagesc(ceil_utc,ceil_range,ceil_b); axis xy; colorbar;
% xlabel('hour UTC'); ylabel('range (km)'); title({num2str([date(1) date(2) date(3)]),'CL31 log_{10}backscatter (m^{-1} srad^{-1})'});
% % plot the wrong 2s complement ceil_b:
% % subplot(2,1,2)
% % imagesc(ceil_utc,ceil_range,log10(max(0,ceil_bwrong))); axis xy; colorbar;
% % xlabel('hour UTC'); ylabel('range (km)'); title('CL31 log_{10}backscatter (m^{-1} srad^{-1})');

% ceilo_15_sec is data in the form required by the calling program
ceilo_15_sec=[cloudcode cloud1 cloud2 cloud3 ceil_hr ceil_mn ceil_sc];% this is the raw 1-D time series data

return

