function [EntriesGreaterThan1, ...
          EntriesLessThan0] =   ...
		  i1i02txtFileToColorMunkiCSVFormat(i1txtFile);
% Purpose		The i1i0 AST, equipped with an i1Pro 2 spectrophotometer, 
%				can save its reflectance measurements (for every 10
%				nm) in a .txt file.  The ColorMunki, on the other hand, can save the reflectances
%				in a .csv file.  This routine converts an i1i02 .txt file into a .csv file.  This routine
%				creates a .csv file in ColorMunki format, with the same name as the input file,
%				but a different extension.
%
% Description	Use the following settings when saving from i1Profiler with the i1i02 option
%				selected: check SampleName, ReflectanceSpectrum, L*a*b*
%				Use Decimal separator---Period, Output scale---0.0-1.0, Spectral range---380 to 730 nm.
%
%				The conversion is complicated because the i1i0 format stores reflectance
%				spectra by columns, even though the AST reads the spectra rows (the AST
%				assumes that  there is a grid of colours to be measured).  Therefore, the
%				colours in the i1i0 file must be rearranged, to be consistent with a
%				ColorMunki .csv file.  The ColorMunki assumes that colours are measured
%				sequentially, but does not assume that they form a grid.
%
% Author		Paul Centore (December 7, 2013)
% Revision		Paul Centore (July 6, 2015)
%				---Added comment that this routine can only handle i1iO AST files with 26 or fewer columns
%
% Copyright 2013-2015 Paul Centore
%
%    This file is part of MunsellAndKubelkaMunkToolbox.
%
%    MunsellAndKubelkaMunkToolbox is free software: you can redistribute it and/or modify
%    it under the terms of the GNU General Public License as published by
%    the Free Software Foundation, either version 3 of the License, or
%    (at your option) any later version.
%
%    MunsellAndKubelkaMunkToolbox is distributed in the hope that it will be useful,
%    but WITHOUT ANY WARRANTY; without even the implied warranty of
%    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
%    GNU General Public License for more details.
%
%    You should have received a copy of the GNU General Public License
%    along with MunsellAndKubelkaMunkToolbox.  If not, see <http://www.gnu.org/licenses/>.

% Open the .txt file generated by the i1 spectrophotometer
input_fid  = fopen(i1txtFile, 'r')		;

% Create the .csv file into which the .txt file will be converted
OutputFileName = [i1txtFile(1:(end-4)),'.csv']	;
output_fid     = fopen(OutputFileName, 'w')		;

% Eliminate the header data at the top of the i1i02 .txt file
DataStart = false					;
while ~DataStart
	FileLine = fgetl(input_fid)		;
	FileLine = deblank(FileLine)	;
	if strcmp(FileLine, 'BEGIN_DATA')
	    DataStart = true			;
	end
end

% The i1i0 measures a grid of colour samples.  The rows in the grid are indexed by
% numbers, while the columns in the grid are indexed by letters.  Each cell in the grid is 
% denoted by, for example, T20, or B7.  The file output first lists the cell designator,
% and then gives the reflectances in the reflectance spectra, from 380 to 730 nm, in
% increments of 10.  Although the i1i0
% measures the grid row by row, the output file lists the measured reflectance spectra
% column by column.  (The cells are listed as A1, A2, A3, ..., then B1, B2, B3, etc.)
% The next section of code rearranges the order so that the cells are listed as A1, B1,
% C1,..., then A2, B2, C2, etc.  The rearranged measurements then give reflectance data
% for samples across the first row of the grid, in order of occurence, then across the
% second row of the grid, and so on.  Currently, this routine can only handle i1iO files
% with 26 or fewer columns of data (additional columns are denoted 2A, 2B, 2C, etc.).  
% Each line of reflectance data is read into a list called AllFileLines.  The letter
% in the cell indicator is extracted from each lne, as is the number of the cell
% indicator.  Those are then rearranged so that all the cells with number 1 are listed
% alphabetically by letter indicator, then all the cells with number 2, and so on.
DoubleIndices = []	;
DataEnded = false	;
LineCtr = 0			;
AllFileLines = {}	;
i1i0ChartPosition = {}	;
while ~DataEnded
	FileLine = fgetl(input_fid)		;
	if ~strcmp(FileLine,'END_DATA') % Not end of file
	    LineCtr = LineCtr + 1	;
		AllFileLines{LineCtr} = FileLine				;
	    LetterKey = FileLine(find(isletter(FileLine)))	;
    	LetterAscii = toascii(LetterKey) - 64			;
        ColNum = 0		;
	    ForwardCtr = 1	;
	    for ctr = length(LetterAscii):(-1):1
		    ColNum = ColNum + 26 ^ (ForwardCtr-1) *	LetterAscii(ctr)	;
		    ForwardCtr = ForwardCtr + 1	;
	    end
	
	    EndOfLetters = max(find(isletter(FileLine)))	;
	    Indices = []	;
	    IndexCtr = EndOfLetters + 1		;
	    while isdigit(FileLine(IndexCtr))
	        Indices = [Indices, IndexCtr]	;
		    IndexCtr = IndexCtr + 1			;
	    end
	    RowNum = str2num(FileLine(Indices))	;
		
		DoubleIndices = [DoubleIndices; ColNum RowNum LineCtr]	;
		i1i0ChartPosition{LineCtr} = [LetterKey,num2str(RowNum)];
	else % End of input file of reflectances has been reached
	    DataEnded = true	;
    end
end
SortedDoubleIndices = sortrows(DoubleIndices,[2,1])	;
SortedLineIndices = SortedDoubleIndices(:,3)		;

% The first line of a ColorMunki .csv file is fixed, so it is written directly to the file
FirstOutputLine = ['Name,L*,a*,b*,380 nm,390 nm,400 nm,410 nm,420 nm,430 nm,440 nm,',...
                   '450 nm,460 nm,470 nm,480 nm,490 nm,500 nm,510 nm,520 nm,530 nm,',...
				   '540 nm,550 nm,560 nm,570 nm,580 nm,590 nm,600 nm,610 nm,620 nm,',...
				   '630 nm,640 nm,650 nm,660 nm,670 nm,680 nm,690 nm,700 nm,710 nm,720 nm,730 nm']	;
fprintf(output_fid, '%s\n', FirstOutputLine)	;			

% The previous section rearranged the lines of reflectance spectra for each cell, to read 
% across the rows, rather than down the columns. Using that order, write each line to a 
% .csv file, in the ColorMunki format.  The first four fields in the ColorMunki line are a colour
% description, and L*a*b* coordinates.  Fill these with space-fillers.
% Also keep track of how many reflectance entries are not between 0 and 1
EntriesGreaterThan1 = 0				;
EntriesLessThan0    = 0				;
for ctr = 1:length(SortedLineIndices)
    FileLine = AllFileLines{SortedLineIndices(ctr)}	;
    if ctr ~= 1 	% No carriage return is needed for the first line 
        fprintf(output_fid, '\n')		;
    end
    cstr = strsplit (FileLine, ' ', true)	;
	OutputLine = [i1i0ChartPosition{SortedLineIndices(ctr)},', ', deblank(cstr{1,2}), ...
	                                                        ', ', deblank(cstr{1,3}), ...
															', ', deblank(cstr{1,4}),', ']		;
	for ind = 5:39
	    TempString = deblank(cstr{1,ind})	;
	    % Make sure the reflectance at each wavelength is between 0 and 1.  If it is not,
		% then replace it with either a 0 or a 1 (whichever is closer to the original entry)
		TempNum    = str2num(TempString)	;
		if TempNum > 1
		    TempString = '1.0000'			;
			EntriesGreaterThan1 = EntriesGreaterThan1 + 1	;
		elseif TempNum < 0
		    TempString = '0.0000'			;
			EntriesLessThan0 = EntriesLessThan0 + 1			;
		end
	       OutputLine = [OutputLine, TempString(1), TempString(2), TempString(3), ...
		                             TempString(4), TempString(5), TempString(6),',']	;
	end
	TempString = deblank(cstr{1,40})	;
	% The last line is treated a bit differently, because there is no comma after it.
	% Make sure the reflectance at the last wavelength is between 0 and 1.  If it is not,
	% then replace it with either a 0 or a 1 (whichever is closer to the original entry)
	TempNum    = str2num(TempString)	;
	if TempNum > 1
	    TempString = '1.0000'			;
		EntriesGreaterThan1 = EntriesGreaterThan1 + 1	;
	elseif TempNum < 0
	    TempString = '0.0000'			;
		EntriesLessThan0 = EntriesLessThan0 + 1			;
	end
	OutputLine = [OutputLine, TempString(1), TempString(2), TempString(3), ...
		                      TempString(4), TempString(5), TempString(6)]			;
	OutputLine = deblank(OutputLine)	;
	fprintf(output_fid, '%s', OutputLine)	;			
end
	
fclose(input_fid)	;
fclose(output_fid)	;