NPMK/NSx Utilities/saveNSx.m
function saveNSx(NSx,varargin)

%% 
% Save an .NSx file from an NSx structure (gained by using openNSx)
% Works with file spec 2.3 and 3.0
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Use: saveNSx(NSx,optionalinputarguments)
%   NSx:        The NSx data structure.
%   All arguments below are optional:
%   Filename:   A complete filepath for the output file.
%               Default: CurrentFilename-Modified.NSx
%   Filespec:   Save the file using the filespec specified e.g. 2.3 or 3.0
%               Default: same as the filespec loaded

%saveNSx version = '1.0.0.1';

% Version History
%
% 1.0.0.1:
%   - Added ability to save to a specific filespec
%

%% 
% Verify FilePath and establish overwrite paramaters
FilePath = [fullfile(NSx.MetaTags.FilePath,NSx.MetaTags.Filename) '-modified' NSx.MetaTags.FileExt];
if length(varargin) >= 1
    if not(isempty(varargin{1}))
        FilePath = varargin{1};
    end
end

% save to a specific filespec
if length(varargin) >= 2
    if (varargin{2} == 2.3)
        NSx.MetaTags.FileTypeID(1:8) = 'NEURALCD';
        NSx.MetaTags.FileSpec(1:3) = '2.3';
    end
    if (varargin{2} == 3.0)
        NSx.MetaTags.FileTypeID(1:8) = 'BRSMPGRP';
        NSx.MetaTags.FileSpec(1:3) = '3.0';
    end
end


disp('This script will save a new file with the proper .NSx extensions');
disp('but you should retain the previous file. Do you acknowledge the');
Accept = input('risk inherent in saving modified versions of data files? (Y/N)','s');
if strcmpi(Accept,'y')
else
    disp('Ending Script...');
    return
end

%%
% Write the basic header into the file
%FullFile
Debug = 0;

if exist(FilePath)
        if exist(FilePath)
        disp('File already exists!');
        OverwritePrompt = input('Would you like to overwrite? (Y/N)','s');
        if strcmpi(OverwritePrompt,'y')
            Overwrite = 1;
            delete(FilePath);
        else
            return
        end
        end
end

clear Overwrite
clear OverwritePrompt
clear varargin

%PausedFile?
if iscell(NSx.Data)
    Paused = 1;
    NumberOfSegments = length(NSx.Data);
else
    Paused = 0;
  
end

FileID = fopen(FilePath, 'w', 'ieee-le');

%Basic header stuff
BytesInBasicHeader = 8+2+4+16+256+4+4+16+4;
BytesInExtendedHeader = 2+2+16+1+1+2+2+2+2+16+4+4+2+4+4+2;
if Paused == 1
    for SegmentCount = 1:NumberOfSegments
    [NumberOfChannels,LengthOfData{SegmentCount}] = size(NSx.Data{SegmentCount});
    end
elseif Paused == 0
    [NumberOfChannels,LengthOfData] = size(NSx.Data);
end

%Identify filespec
fspec = NSx.MetaTags.FileTypeID(1:8);
if strcmp(fspec,'BRSMPGRP')
    tspres = 'uint64';
else
    tspres = 'uint32';
end

%File Type ID
    Before = 0;
    fwrite(FileID,fspec);
    After = ftell(FileID);
    if After-Before ~= 8 && Debug == 1
        disp('error FildID')
    end
%File spec
    Before = ftell(FileID);
    fwrite(FileID, [str2double(NSx.MetaTags.FileSpec(1)) str2double(NSx.MetaTags.FileSpec(3))], 'uint8');
    After = ftell(FileID);
    if After-Before ~= 2 && Debug == 1
        disp('error File Spec')
    end
%Bytes in Headers
    Before = ftell(FileID);
    fwrite(FileID, BytesInBasicHeader+NumberOfChannels*BytesInExtendedHeader,'uint32');
    After = ftell(FileID);
    if After-Before ~= 4 && Debug == 1
        disp('error BytesInHeaders')
    end
%Label
    Before = ftell(FileID);
    fwrite(FileID, NSx.MetaTags.SamplingLabel);
    After = ftell(FileID);
    if After-Before ~= 16 && Debug == 1
        disp('error label')
    end
%Comment
    Before = ftell(FileID);
    if ~isempty(NSx.MetaTags.Comment)
        fwrite(FileID, NSx.MetaTags.Comment);
    else
        fwrite(FileID, repmat(' ', 1, 256));
    end
    After = ftell(FileID);
    if After-Before ~= 256 && Debug == 1
        disp('error comment')
    end
%Period
    Before = ftell(FileID);
    fwrite(FileID, (1/NSx.MetaTags.SamplingFreq)*30000, 'uint32');
    After = ftell(FileID);
    if After-Before ~= 4 && Debug == 1
        disp('error period')
    end
%Time Resolution of time stamps
    Before = ftell(FileID);
    fwrite(FileID, NSx.MetaTags.TimeRes,'uint32');
    After = ftell(FileID);
    if After-Before ~= 4 && Debug == 1
        disp('error time resolution')
    end
%Time Origin
    Before = ftell(FileID);
    if ~isempty(NSx.MetaTags.DateTimeRaw)
        fwrite(FileID, NSx.MetaTags.DateTimeRaw,'uint16');
    else
        fwrite(FileID, [1900 1 1 0 0 0 0 0],'uint16');
    end
    After = ftell(FileID);
    if After-Before ~= 16 && Debug == 1
        disp('error Time Origin')
    end
%Channel Count
    Before = ftell(FileID);
    fwrite(FileID, NumberOfChannels,'uint32');
    After = ftell(FileID);
    if After-Before ~= 4 && Debug == 1
        disp('error Channel Count')
    end



%Extended header stuff
%Number of these equal to number of channels
for i = 1:NumberOfChannels
    % Type
    Before = ftell(FileID);
    fwrite(FileID, 'CC');
    After = ftell(FileID);
    if After-Before ~= 2 && Debug == 1
        disp('error Type')
    end
    % ElectrodeID
    Before = ftell(FileID);
    try 
        fwrite(FileID, NSx.ElectrodesInfo(i).ElectrodeID,'uint16');
    catch
        fwrite(FileID, i,'uint16');
    end
    After = ftell(FileID);
    if After-Before ~= 2 && Debug == 1
        disp('error ElectrodeID')
    end
    % Electrode label
    Before = ftell(FileID);
    try
        fwrite(FileID, NSx.ElectrodesInfo(i).Label);
    catch
        templabel = ['chan' num2str(i) '                '];
        templabel(17:end) = [];
        fwrite(FileID, templabel);
    end
    After = ftell(FileID);
    if After-Before ~= 16 && Debug == 1
        disp('error Electrode Label')
    end
    % Physical connector
    Before = ftell(FileID);
    try
        fwrite(FileID, NSx.ElectrodesInfo(i).ConnectorBank, 'uint8');
    catch
        if i > 0 && i <= 32
            fwrite(FileID, 1, 'uint8');
        elseif i > 32 && i <= 64
            fwrite(FileID, 2, 'uint8');
        elseif i > 64 && i <= 96
            fwrite(FileID, 3, 'uint8');
        elseif i > 96 && i <= 128
            fwrite(FileID, 4, 'uint8');
        end
    end
    After = ftell(FileID);
    if After-Before ~= 1 && Debug == 1
        disp('error Physical Connector')
    end
%Physical pin
    Before = ftell(FileID);
    try 
        fwrite(FileID, NSx.ElectrodesInfo(i).ConnectorPin, 'uint8');
    catch
        fwrite(FileID, int2str((i-floor(i/32)*32)), 'uint8');
    end
    After = ftell(FileID);
    if After-Before ~= 1 && Debug == 1
        disp('error Physical Pin')
    end
%Min Digital Value
    Before = ftell(FileID);
    try
        fwrite(FileID, NSx.ElectrodesInfo(i).MinDigiValue,'int16');
    catch
        fwrite(FileID, -32764,'int16');
    end
    After = ftell(FileID);
    if After-Before ~= 2 && Debug == 1
        disp('error min Digital Value')
    end
%Max Digital Value
    Before = ftell(FileID);
    try 
        fwrite(FileID, NSx.ElectrodesInfo(i).MaxDigiValue,'int16');
    catch
        fwrite(FileID, 32764,'int16');
    end
    After = ftell(FileID);
    if After-Before ~= 2 && Debug == 1
        disp('error Max Digital value')
    end
%Min Analog Value
    Before = ftell(FileID);
    try
        fwrite(FileID, NSx.ElectrodesInfo(i).MinAnalogValue,'int16');
    catch
        fwrite(FileID, -8191,'int16');
    end
    After = ftell(FileID);
    if After-Before ~= 2 && Debug == 1
        disp('error Min Analog Value')
    end
%Max Analog Value
    Before = ftell(FileID);
    try
        fwrite(FileID, NSx.ElectrodesInfo(i).MaxAnalogValue,'int16');
    catch
        fwrite(FileID, 8191,'int16');
    end
    After = ftell(FileID);
    if After-Before ~= 2 && Debug == 1
        disp('error Max Aanalog value')
    end
%Units
    Before = ftell(FileID);
    try
        fwrite(FileID, NSx.ElectrodesInfo(i).AnalogUnits,'char');
    catch
        fwrite(FileID, 'uv              ');
    end
    After = ftell(FileID);
    if After-Before ~= 16 && Debug == 1
        disp('error Units')
    end
%High Freq Corner (High frequency cutoff in mHz)
    Before = ftell(FileID);
    try
        fwrite(FileID, NSx.ElectrodesInfo(i).HighFreqCorner,'uint32');
    catch
        fwrite(FileID, 0,'uint32');
    end
    After = ftell(FileID);
    if After-Before ~= 4 && Debug == 1
        disp('error High Corner')
    end
%High Freq Order (Order of the filter used)
    Before = ftell(FileID);
    try
        fwrite(FileID, NSx.ElectrodesInfo(i).HighFreqOrder,'uint32');
    catch
        fwrite(FileID, 0,'uint32');
    end
    After = ftell(FileID);
    if After-Before ~= 4 && Debug == 1
        disp('error high Order')
    end
%High Filter Type (0 = none, 1 = butterworth)
    Before = ftell(FileID);
    try
        fwrite(FileID, NSx.ElectrodesInfo(i).HighFilterType,'uint16');
    catch
        fwrite(FileID, 0,'uint16');
    end
    After = ftell(FileID);
    if After-Before ~= 2 && Debug == 1
        disp('error High Type')
    end
%Low Freq Corner (Low frequency cutoff in mHz)
    Before = ftell(FileID);
    try
        fwrite(FileID, NSx.ElectrodesInfo(i).LowFreqCorner,'uint32');
    catch
        fwrite(FileID, 0,'uint32');
    end
    After = ftell(FileID);
    if After-Before ~= 4 && Debug == 1
        disp('error Low Corner')
    end
%Low Freq Order (0 = none)
    Before = ftell(FileID);
    try
        fwrite(FileID, NSx.ElectrodesInfo(i).LowFreqOrder,'uint32');
    catch
        fwrite(FileID, 0,'uint32');
    end
    After = ftell(FileID);
    if After-Before ~= 4 && Debug == 1
        disp('error Low Order')
    end
%Low Filter Type (0 = none, 1 = butterworth)
    Before = ftell(FileID);
    try
        fwrite(FileID, NSx.ElectrodesInfo(i).LowFilterType,'uint16');
    catch
        fwrite(FileID, 0,'uint16');
    end
    After = ftell(FileID);
    if After-Before ~= 2 && Debug == 1
        disp('error Low Type')
    end

end


    %DataPackets
if Paused == 0
    %Header
    fwrite(FileID, NSx.RawData.DataHeader(1));
    %Timestamp
    fwrite(FileID, NSx.MetaTags.Timestamp,tspres);
    %Number of data points
    fwrite(FileID, LengthOfData, 'uint32');

    %for i = 1:TotalDataPoints
    %Data points
    %fwrite(FileID, NSx.Data(i),'int16');
    fwrite(FileID, NSx.Data,'int16');
    %end
elseif Paused == 1
    for SegmentNumber = 1:NumberOfSegments
        %Header
        fwrite(FileID, 1, 'uint8');
        %Timestamp
        fwrite(FileID, NSx.MetaTags.Timestamp(SegmentNumber),tspres);
        %Number of data points
        fwrite(FileID, LengthOfData{SegmentNumber}, 'uint32');

        %for i = 1:TotalDataPoints
        %Data points
        %fwrite(FileID, NSx.Data(i),'int16');
        fwrite(FileID, NSx.Data{SegmentNumber},'int16');
        %end
    end
end

fclose(FileID);













