function data = Conductivity_Oven( mode, modeParam, sCurrent, dvmRange, ...
delay, fileName, varargin)
%function data = Conductivity_Oven( mode, modeParam, sCurrent, dvmRange, ...
% delay, fileName, <Parameters>)
%
%Collects and logs data for the conductivity experiment in the oven with a
%single platinum thermometer attached near the sample. Code is similar to
%Conductivity_Cold.m
%
%
%INPUTS
%
%mode Either 'f' or 'a'
% The program can be run in two modes. In the mode with
% mode set to 'f' (follow), the program collects data
% until the temperature "modeParam" is reached.
% In the mode with tempFollow set to 'a' (alone), the program
% collects "modeParam" number of data points and is not
% sensitive to any particular temperature.
%
%modeParam Positive scalar
% Represnts either the target Platinum reistance in ohms
% (follow mode) or number of data points (alone mode).
%
%sCurrent Positive Scalar
% Applied current to sample in Amperes
% Suggested Value: 0.01
%
%dvmRange Positive Scalar
% The digital voltmeter Range sets the measurement range of
% the digital voltmeter in volts. Care must be taken to
% keep all data points in range, otherwise the device will
% return an error and the data may not be logged.
% Suggested Value: 1
%
%delay Positive Scalar
% Time delay (in seconds) between consecutive data points. The
% time between successive points will always be slightly
% longer, as the time for receiving data from the device
% is not counted in this number.
% Suggested Value: 1
%
%fileName File name for output data file
% Data file is a comma delimited .csv file containing the data
% with the following order of columns
% Platinum Resistance
% sample current
% voltage
% Sample Resistance (voltage / current)
%
%
%OPTIONAL PARAMETERS
%
%saveFolder Folder to save output data .csv file.
% Default: [pwd]/Data_[YYYYmmDD]/
%
%
%OUTPUTS
%
%data N x 4 matrix
% Contains data in 4 columns:
% Platinum Resistance
% sample current
% voltage
% Sample Resistance (voltage / current)
%
%
%NOTES
%
%If the program exits with errors, call delete(instrfind) at the command
%prompt to reset the hardware connections.
%
%
%ACKNOWLEDGEMENTS
%
%Inspired by nickel.m written by David Tam (tam@phys.columbia.edu) and
%Benjamin Nachumi (peripatetic1@yahoo.com).
%
%
%XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
%X Author: Sky Cheung X
%X Date Created: 14 Feb 2015 X
%X Last Modified: 14 Feb 2015 X
%XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
%

%Input Parsing
p = inputParser;

%Defaults
defaultSaveFolder = sprintf('%s\\Data_%s', pwd, datestr(now,'YYYY-mm-DD') );

%Expected
expectedMode = {'a','f'};

%Parsing Conditions for Required Arguments
addRequired(p, 'mode', @(x) any( validatestring( x, ...
expectedMode) ) );
addRequired(p, 'modeParam', @(x) validateattributes( x, ...
{'numeric'}, {'nonempty','scalar','nonnegative'} ) );
addRequired(p, 'sCurrent', @(x) validateattributes( x, ...
{'numeric'}, {'nonempty','scalar','nonnegative'} ) );
addRequired(p, 'dvmRange', @(x) validateattributes( x, ...
{'numeric'}, {'nonempty','scalar','nonnegative'} ) );
addRequired(p, 'delay', @(x) validateattributes( x, ...
{'numeric'}, {'nonempty','scalar','nonnegative'} ) );
addRequired(p, 'fileName', @(x) validateattributes( x, ...
{'char'}, {'nonempty'} ) );

%Parsing Conditions for Optional Parameters
addParameter(p, 'SaveFolder', defaultSaveFolder, @(x) validateattributes( x, ...
{'char'}, {'nonempty'} ) );

%Parsing Inputs
parse(p, mode, modeParam, sCurrent, dvmRange, delay, fileName, varargin{:});

%Getting proper inputs
mode = p.Results.mode;
modeParam = p.Results.modeParam;
sCurrent = p.Results.sCurrent;
dvmRange = p.Results.dvmRange;
delay = p.Results.delay;
fileName = p.Results.fileName;
saveFolder = p.Results.SaveFolder;

%Delete Stucture
clear p;

%Constants
%NOTE: do not change these or some data might be lost in transit
%Number of individual delta mode measurements to be averaged for each data point
numDeltaPoints = 10;
%Sufficient Delay
deltaDelay = 0.1;

%Alone mode parameter must be an integer
if strcmp(mode,'a') && logical( abs( round(modeParam) - modeParam ) > eps )
error('modeParam must be an integer in alone mode.');
end

%initialize some things
pause on

%Create and open instrument objects, and echo their names
lakeshore = visa('ni','gpib0::12::INSTR');
fopen(lakeshore);
fprintf(lakeshore,'*IDN?');
lakeshoreName = fscanf(lakeshore);
%Removing trailing whitespace
lakeshoreName = strtrim(lakeshoreName);

keithley = visa('ni','gpib0::13::INSTR');
fopen(keithley);
fprintf(keithley,'*IDN?');
keithleyName = fscanf(keithley);
%Removing Trailing Whitespace
keithleyName = strtrim(keithleyName);

%Preparing Cleanup function to ensure proper disconnection
finishUp = onCleanup(@() Disconnect_Ports( lakeshore, keithley ) );

%Echoing names
fprintf('Successfully connected to:\n%s\n%s\n', ...
lakeshoreName , ...
keithleyName );

%Check keithley internal setup
fprintf(keithley,'SOUR:DELT:NVPR?');
is2182aConnected = fscanf(keithley);
if is2182aConnected == 1,
fprintf('WARNING: Voltmeter is not connected.\n');
end

%set up voltmeter
fprintf( keithley, 'SYST:COMM:SER:SEND "VOLT:RANGE %s"', num2str(dvmRange) );

%set up keithley for delta mode
%as in ref manual, p. 5-29
fprintf('Strike any key to arm the Keithley...\n');
pause;

fprintf(keithley,'*RST');
fprintf(keithley,'SOUR:DELT:HIGH %e', sCurrent);
fprintf(keithley,'SOUR:DELT:DEL %e', deltaDelay);
fprintf(keithley,'SOUR:DELT:COUN %s', num2str(numDeltaPoints));
fprintf(keithley,'TRAC:POIN %s', num2str(numDeltaPoints));
fprintf(keithley,'TRAC:CLE');
fprintf(keithley,'SOUR:DELT:ARM');
%it takes 8 seconds to arm the keithley with a 10,000 point buffer
pause( max( [0.01, numDeltaPoints*(8/10000)] ) + 2 );
fprintf('...Keithley is armed.\n');

%start heater and begin logging data points
fprintf('Strike any key to begin the heating cycle and start logging data...\n');
pause;
%preview of for loop;
%measure
%fprintf(keithley,'INIT:IMM')
%pause(numDeltaPoints*deltaDelay + 0.1);
%read out the buffer;
%fprintf(keithley,'TRAC:DATA?')
%pause(numDeltaPoints*deltaDelay + 0.1);
%fscanf(keithley);

if ishold==0;
hold
end

%Preparing output file
if ~isdir(saveFolder)
mkdir(saveFolder);
end
fName = sprintf('%s\\%s.txt', defaultSaveFolder, fileName);

%Switch for different modes
switch mode
%Follow Mode
case 'f'
%Preallocate Data with 1000 rows
preallocateNum = 1e3;
data = zeros(preallocateNum, 4);
dataCount = 1;

%Obtianing Pt resistance from reading B
fprintf(lakeshore,'SRDG?b');
oldResist = fscanf(lakeshore,'%f');
%Sign of the difference
oldResistSign = sign(oldResist - modeParam);

newResistSign = oldResistSign;

%While loop to continually collect data until the sign of the difference
%has changed (crossover of target temperature)
while isequal(newResistSign, oldResistSign)
%Check if extra rows need to be added
if mod(dataCount,preallocateNum) == 0
%Add 1000 extra rows
data = [data; zeros(preallocateNum, 4)];
end
%Acquiring Pt Resistance from B
fprintf(lakeshore,'SRDG?b');
newResist = fscanf(lakeshore,'%f');
%Sign of the difference
newResistSign = sign(newResist - modeParam);

%keithley data
fprintf(keithley,'INIT:IMM');
pause(numDeltaPoints*deltaDelay + 0.1);
%CHECK TO SEE IF THIS IS NECESSARY
fprintf(keithley,'TRAC:DATA?');
pause(numDeltaPoints*deltaDelay + 0.1);
fscanf(keithley);
fprintf(keithley,'CALC2:FORM MEAN');
fprintf(keithley,'CALC2:STAT ON');
fprintf(keithley,'CALC2:IMM');
fprintf(keithley,'CALC2:DATA?');
%Average Voltage
avgVoltage = fscanf(keithley,'%e');
avgOhms = avgVoltage/sCurrent;

%New Data
newData = ...
[newResist, sCurrent, avgVoltage, avgOhms];

%Write new data to file
dlmwrite( fName, newData, ...
'delimiter', ',', ...
'newline', 'pc', ...
'precision', '%.6e', ...
'-append');

%Update Plot
plot(newResist, avgOhms, 'r+' );

%Storing current measurements into data matrix
data(dataCount,:) = newData;

%Increment Data Count
dataCount = dataCount + 1;
%Delay
pause(delay);

end %End of while loop
%Stripping away extra preallocated rows
data = data(any(data,2),:);
%End of Follow Mode

%Alone Mode
case 'a'
%Preallocate Data
data = zeros(modeParam,4);

%For loop for alone mode
for j = 1:modeParam
%Acquiring Pt Resistance from B
fprintf(lakeshore,'SRDG?b');
newResist = fscanf(lakeshore,'%f');

%keithley data
fprintf(keithley,'INIT:IMM');
pause(numDeltaPoints*deltaDelay + 0.1);
%CHECK TO SEE IF THIS IS NECESSARY
fprintf(keithley,'TRAC:DATA?');
pause(numDeltaPoints*deltaDelay + 0.1);
fscanf(keithley);
fprintf(keithley,'CALC2:FORM MEAN');
fprintf(keithley,'CALC2:STAT ON');
fprintf(keithley,'CALC2:IMM');
fprintf(keithley,'CALC2:DATA?');
%Average Voltage
avgVoltage = fscanf(keithley,'%e');
avgOhms = avgVoltage/sCurrent;

%New Data
data(j,:) = ...
[newResist, sCurrent, avgVoltage, avgOhms];

%Write new data to file
dlmwrite( fName, data(j,:), ...
'delimiter', ',', ...
'newline', 'pc', ...
'precision', '%.6e', ...
'-append');

%Update Plot
plot(newResist, avgOhms, 'r+' );

%Delay
pause(delay);
end %End of alone mode for loop
%End of alone mode

end %End of switch for mode

%Overlay plot with blue diamonds
plot(data(:,1), data(:,4),'bd');

end %End of Conductivity_Oven.m

%Disconnect upon completion
function Disconnect_Ports(lakeshore, keithley)
%Lakeshore
fprintf('Removing Lakeshore connection.\n');
fclose(lakeshore);

%Keithley
fprintf('Removing Keithley connection.\n');
%Disarming Keithley
fprintf(keithley,'SOUR:SWE:ABOR');
fprintf(keithley,'TRAC:CLE');
fclose(keithley);

fprintf('Disconnecting ports.\n');
delete(instrfind);

fprintf('Successfully disconnected.\n');
end %End of Disconnect_Ports