function oc = loadoc2(fid)
%LOADBANG reads version 1.0 *.oc2.gz files created by the the optoclamp.
%
%    y = LOADPIC(filename) takes as input the filename of a optoclamp
%    PIC2.GZ file and returns a struct containing:
%         meta          STRUCT  containing lots of metadata
%         time          [1 N]   vector of times of data points (in seconds)
%         targ          [1 N]   vector of target values
%         meas          [1 N]   vector of measurements.
%         filt          [1 N]   vector of filtered measurements.
%         erro          [1 N]   vector of error values.
%         erin          [1 N]   vector of error integral values.
%         clon          [1 N]   vector of controller engaged logicals.
%         mode          [1 N]   vector of stimulation modes
%         out1          [1 N]   vector of output 1 doubles.
%         out2          [1 N]   vector of output 2 doubles.
%         vlt1          [1 N]   vector of output 1 voltage amplitudes.
%         off1          [1 N]   vector of output 1 voltage offsets.
%         per1          [1 N]   vector of output 1 stimuluation periods.
%         wdt1          [1 N]   vector of output 1 stimuluation widths.
%         slp1          [1 N]   vector of output 1 stimuluation slopes.
%         vlt2          [1 N]   vector of output 2 voltage amplitudes.
%         off2          [1 N]   vector of output 2 voltage offsets.
% 
%    Created by: Jon Newman (jnewman6<snail>gatech<dot>edu)
%    Created on: Dec 7, 2013
%    Last modified: Dec 4, 2013
%
%    Licensed under the GPL: http://www.gnu.org/licenses/gpl.txt

if nargin < 1
    error('You must provide a file path')
end
if(~ (strcmp(fid(end-5:end),'oc2.gz') || strcmp(fid(end-2:end),'oc2')))
    warning(['This file does not have a .oc2.gz extension. '... 
             'trying to extract data anayway...'])
end

% Main code
if strcmp(fid(end-5:end),'oc2.gz')
    ftemp = gunzip(fid);
else
    ftemp = {fid};
end
h = fopen(ftemp{1},'r');

% Get file size
fseek(h,0,'eof');
len = ftell(h);
fseek(h,0,'bof');

% Read header info
% Version
str_len  = fread(h,1,'uint8'); % The number of bytes in the next string
oc.meta.oc_version = fread(h,str_len,'*char')';

if ~strcmp(oc.meta.oc_version,'Version 1.0')
    error(['This file was produced by a version of the Optoclamp ' ...
        'that is not compatible with this script.'])
end

% Date
oc.meta.date = fread(h,7,'int32'); % date and time

% Basic parameters
oc.meta.loop_rate_hz = fread(h,1,'double'); % sampling rate
str_len  = fread(h,1,'uint8'); % The number of bytes in the next string
oc.meta.meas_type = fread(h,str_len,'*char')';
str_len  = fread(h,1,'uint8'); % The number of bytes in the next string
oc.meta.ctl_type = fread(h,str_len,'*char')';
str_len  = fread(h,1,'uint8'); % The number of bytes in the next string
oc.meta.stm_drv_type = fread(h,str_len,'*char')';
str_len  = fread(h,1,'uint8'); % The number of bytes in the next string
oc.meta.array_type = fread(h,str_len,'*char')';
str_len  = fread(h,1,'uint8'); % The number of bytes in the next string
oc.meta.well_id = fread(h,str_len,'*char')';

% Output parameters
oc.meta.default_output_mode = fread(h,1,'uint8');
oc.meta.out1_on = fread(h,1,'bool');
oc.meta.out2_on = fread(h,1,'bool');
oc.meta.out1_min_freq_hz = fread(h,1,'double');
oc.meta.out1_max_freq_hz = fread(h,1,'double');
oc.meta.out1_max_width_sec = fread(h,1,'double');
oc.meta.out1_max_volt = fread(h,1,'double');
oc.meta.out1_min_slope_volt_per_ms = fread(h,1,'double');
oc.meta.out2_max_volt = fread(h,1,'double');
oc.meta.pre_pulse_freq = fread(h,1,'double');

% Control parameters
oc.meta.k = fread(h,1,'double');
oc.meta.ti = fread(h,1,'double');
oc.meta.tt = fread(h,1,'double');
oc.meta.delta1 = fread(h,1,'double');
oc.meta.delta2 = fread(h,1,'double');

% Timing parameters
oc.meta.start_time_sec = fread(h,1,'double');
oc.meta.pre_pre_pulse_dur_sec = fread(h,1,'double');
oc.meta.pre_pulse_dur_sec = fread(h,1,'double');
oc.meta.post_pre_pulse_dur_sec = fread(h,1,'double');

% Target parameters
oc.meta.num_targets = fread(h,1,'int32');
oc.meta.targets = fread(h,oc.meta.num_targets,'double'); 

% Number of recorded streams
oc.meta.numstreams = fread(h,1,'int32'); 

% Constants
HEADER_BYTES = ftell(h);
REC_BYTES = 8*(oc.meta.numstreams-2) + 1 + 1;

% Calculated number of stimuli
numdat = floor((len-HEADER_BYTES)/REC_BYTES);

% Display record info
fprintf('\nOPTOCLAMP RECORD\n');
fprintf(['\tOptoclamp version: ' oc.meta.oc_version '\n']);
fprintf(['\tRecording time (yr-mo-dy-hr-mi-sc-ms): ' ... 
        num2str(oc.meta.date(1)) '-' ...
        num2str(oc.meta.date(2)) '-' ...
        num2str(oc.meta.date(3)) '-' ...
        num2str(oc.meta.date(4)) '-' ...
        num2str(oc.meta.date(5)) '-' ...
        num2str(oc.meta.date(6)) '-' ...
        num2str(oc.meta.date(7)) '\n']);
fprintf(['\tLoop rate (Hz): ' num2str(oc.meta.loop_rate_hz) '\n']);
fprintf(['\tMeasurement used: ' oc.meta.meas_type '\n']);
fprintf(['\tController type: ' oc.meta.ctl_type '\n']);
fprintf(['\tDefault output mode: ' num2str(oc.meta.default_output_mode) '\n']);
fprintf(['\tMEA type: ' oc.meta.array_type '\n']);
fprintf(['\tNumber of streams recorded: ' num2str(oc.meta.numstreams) '\n\n']);


% Read the actual 'daturs

% Time
oc.time = fread(h,numdat,'double',REC_BYTES - 8)';

% Target
laststop = HEADER_BYTES + 8;
fseek(h,laststop,'bof');
oc.targ = fread(h,numdat,'double', REC_BYTES - 8)';

% Raw Firing Rate
laststop = laststop + 8;
fseek(h,laststop,'bof');
oc.meas = fread(h,numdat,'double', REC_BYTES - 8)';

% Filtered Firing Rate
laststop = laststop + 8;
fseek(h,laststop,'bof');
oc.filt = fread(h,numdat,'double', REC_BYTES - 8)';

% Error
laststop = laststop + 8;
fseek(h,laststop,'bof');
oc.erro = fread(h,numdat,'double', REC_BYTES - 8)';

% Error Integral
laststop = laststop + 8;
fseek(h,laststop,'bof');
oc.erin = fread(h,numdat,'double', REC_BYTES - 8)';

% Control On?
laststop = laststop + 8;
fseek(h,laststop,'bof');
oc.clon = logical(fread(h,numdat,'uint8', REC_BYTES - 1))';

% Stimulation Mode
laststop = laststop + 1;
fseek(h,laststop,'bof');
oc.mode = fread(h,numdat,'uint8', REC_BYTES - 1)';

% Out 1
laststop = laststop + 1;
fseek(h,laststop,'bof');
oc.out1 = fread(h,numdat,'double', REC_BYTES - 8)';

% Out 2
laststop = laststop + 8;
fseek(h,laststop,'bof');
oc.out2 = fread(h,numdat,'double', REC_BYTES - 8)';

% Voltage 1
laststop = laststop + 8;
fseek(h,laststop,'bof');
oc.vlt1 = fread(h,numdat,'double', REC_BYTES - 8)';

% Offset 1
laststop = laststop + 8;
fseek(h,laststop,'bof');
oc.off1 = fread(h,numdat,'double', REC_BYTES - 8)';

% Period 1
laststop = laststop + 8;
fseek(h,laststop,'bof');
oc.per1 = fread(h,numdat,'double', REC_BYTES - 8)';

% Width 1
laststop = laststop + 8;
fseek(h,laststop,'bof');
oc.wdt1 = fread(h,numdat,'double', REC_BYTES - 8)';

% Slope 1
laststop = laststop + 8;
fseek(h,laststop,'bof');
oc.slp1 = fread(h,numdat,'double', REC_BYTES - 8)';

% Voltage 2
laststop = laststop + 8;
fseek(h,laststop,'bof');
oc.vlt2 = fread(h,numdat,'double', REC_BYTES - 8)';

% Offset 2
laststop = laststop + 8;
fseek(h,laststop,'bof');
oc.off2 = fread(h,numdat,'double', REC_BYTES - 8)';

% close file
fclose(h);

delete(ftemp{1});

end



