Skip to content

Instantly share code, notes, and snippets.

@vsoch
Last active January 2, 2016 04:39
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save vsoch/8251564 to your computer and use it in GitHub Desktop.
Save vsoch/8251564 to your computer and use it in GitHub Desktop.
Confirmation and reminder emails for experimental research in Matlab, as well as a script to send brain images to participants.
function confirmation_email(contactemail)
% CONFIRMATION_EMAIL
% Vanessa Sochat
%
% This script sends confirmation emails for imaging and battery appointments
% added to the calendar the previous day.
%
% -------------------------------------------------------------------------
% VARIABLES:
%
% contactemail: An email address that you want to be notified in
% the case of error
%
% -------------------------------------------------------------------------
% DEPENDENCY:
% For the script to work, it must have access to each of the appointment
% private calendars (URL's hard coded), and the data in the calendar must
% have the user email as the first thing in the Description field, like so
%
% Name: Jane Doe
% Phone: (999) 999-9999
% E-mail: jane.doe@duke.edu
%
% poozie.mat must be in the same folder it is running from
%
% schedule.csv: Downloaded by the batch script just before running
% the matlab script - this file contains all subject specific info that is
% used to look up an individual based on name.
%--------------------------------------------------------------------------
% OUTPUT:
% A log of confirmation email info is saved, and all files are located
% under:
%
% Y:/Scripts/Appointments
% -------------------------------------------------------------------------
%--------------------------------------------------------------------------
% Set up mail credentials
%--------------------------------------------------------------------------
load poozie.mat
email_count=0;
% Path to the reminder and directions sheet
reminder_directions = 'Y:/Scripts/Appointments/Reminder_and_Directions.pdf';
% Then this code will set up the preferences properly:
setpref('Internet','E_mail',poozie);
setpref('Internet','SMTP_Server','smtp.gmail.com');
setpref('Internet','SMTP_Username',poozie);
setpref('Internet','SMTP_Password',pooziepa);
props = java.lang.System.getProperties;
props.setProperty('mail.smtp.auth','true');
props.setProperty('mail.smtp.socketFactory.class', 'javax.net.ssl.SSLSocketFactory');
props.setProperty('mail.smtp.socketFactory.port','465');
%--------------------------------------------------------------------------
% Read in appointment file (schedule.csv) downloaded from server
%--------------------------------------------------------------------------
% If the file exists, read it in. If it doesn't, exit with an error,
% record error to the log, and email Vanessa about error.
if exist('schedule.csv','file')
fid = fopen('schedule.csv');
else
% Initialize and print to file
fid = fopen('ERROR_LOG.txt', 'a');
fprintf(fid, 'Date: ');
fprintf(fid,'%s\n', date');
fprintf(fid, 'Schedule file does not exist! Check download.');
fclose(fid);
% If the user has provided an email, alert that email of the failure:
if exist('contactemail','var')
sendmail(contactemail,'Message from Rem_Email.m',[ 'The script exited with error on ' date ' while sending out ' days ' day reminders for the ' calendar ' calendar. '],'');
end
error('Schedule file does not exist');
end
% READ APPOINTMENT INFORMATION FROM FILE
% First read in the header fields
H = textscan(fid, '%s %s %s %s %s %s %s %s %s %s %s \n', 'delimiter', ',');
% StartTime {H1}
% EndTime (H2)
% First Name (H3)
% Last Name (H4)
% Phone (H5)
% Email (H6)
% Type (H7)
% Calendar (H8)
% Duke Unique ID (H9)
% Text Message? (H10)
% Phone Carrier (H11)
% Then read the data from the rest of the file
C = textscan(fid, '%s %s %s %s %s %s %s %s %s %s %s %s %s', 'delimiter', ',');
% StartDate {C1}
% StartTime (C2)
% EndDate (C3)
% EndTime (C4)
% First Name (C5)
% Last Name (C6)
% Phone (C7)
% Email (C8)
% Appointment Type (C9)
% Clinician (C10)
% Unique ID (C11)
% Text Message? (C12)
% Phone Carrier (C13)
% Now we convert a cell array into an array of strings so we can read each
% one, only for the fields that we are interested in.
FirstNames = C{5};
LastNames = C{6};
Phones = C{7};
Emails = C{8};
Txt = C{12};
Carriers = C{13};
fclose(fid);
clear C H fid;
%--------------------------------------------------------------------------
% Download latest appointments from imaging and computer calendar to file
%--------------------------------------------------------------------------
% CD to directory for saving current appointment files
cd('Y:/Scripts/Appointments/');
% Download and save the calendar data, if it doesn't already exist in the
% folder (since the reminder emails are sent just before and haven't been
% deleted by the batch script, these files should already exist!)
if exist('imaging.txt','file')==0
calie{1} = urlwrite(schmoogie,'imaging.txt','get',{});
else
calie{1} = 'imaging.txt';
end
meetingloc{1} = 'Soc-Psych 07';
cal{1} = 'Imaging';
if exist('computer.txt','file')==0
calie{2} = urlwrite(yebya,'computer.txt','get',{});
else
calie{2} = 'computer.txt';
end
meetingloc{2} = 'LSRC B Lobby';
cal{2} = 'Computer';
%--------------------------------------------------------------------------
% Read appointments from the file and save to variable
%--------------------------------------------------------------------------
% Open the subject appointment file, which was an .ical file that we open as
% a text file
for v=1:2
fln = fopen(calie{v});
% Create a subject count variable
appt_count=0;
% Set the current appointment date to today, so we can stop reading the
% file when the appointments go into the past.
Appointment=date;
% Set today's date in a number format for easy comparison
today = datenum(date);
while ~feof(fln)
% We need to make sure that we only read in appointments for today and
% in the future, so we do a comparison between the current appointment
% that is being read. We use a do-->while loop so that the comparison
% until after a subject has been
% Read in line
currentline = fgetl(fln);
% Look to see if we have a date line, which starts with 'DSTART'
if regexp(currentline, 'DTSTART', 'once');
%if yes, pull the date and time from this line, and format
year = currentline(9:12);
month = currentline(13:14);
day = currentline(15:16);
appointment = datestr([ year ' ' month ' ' day ]);
time = currentline(18:21);
time = str2double(time);
% The time is 4 hours in the future, so we subtract 4:
time = time - 400;
% Convert military time to standard time
if (time > 1259)
time = time-1200;
period = 'pm';
else
if (time >= 1200) && (time <= 1259)
period = 'pm';
else
period = 'am';
end
end
% Format time with a ":" by separating the last two characters
% from the first, and sticking them together with a ":"
time = num2str(time);
time_end = time(length(time)-1:length(time));
time_beg = regexprep(time, time_end, '','once');
% Put it all together into a user friendly format for printing
time = [ time_beg ':' time_end ' ' period ];
% If the appointment is from before today, we don't want to do
% anything.
if(today > datenum(appointment))
else
%Add another subject to the array if they aren't from the past
appt_count = appt_count +1;
APPTS(appt_count)= struct('First','','Last','','Email', '','Phone','','Appointment', appointment, 'Time', time,'Text','','Carrier','','Created','');
end
end
% Look to see if we have a date created line, which starts with 'CREATED'
if regexp(currentline, 'CREATED', 'once');
%if yes, pull the date and time from this line, and format
create_year = currentline(9:12);
create_month = currentline(13:14);
create_day = currentline(15:16);
created = datestr([ create_year ' ' create_month ' ' create_day ]);
% If the appointment is from before today, we don't want to do
% anything.
if(today > datenum(appointment))
else
APPTS(appt_count).Created = created;
end
end
% Look to see if we have a participant info line:
if regexp(currentline, 'DESCRIPTION', 'once');
% Only read the line if there is data there, meaning the length
% is greater than 12 (the length of DESCRIPTION:)
if length(currentline) > 12
% If the appointment is from the past, skip it, as we did
% above
if (today > datenum(appointment))
else
%if yes, first get rid of the 'DESCRIPTION:Name: ' section
currentline = regexprep(currentline, currentline(1:18), '','once');
% Put the first name into a variable by finding the end of it,
% marked by a space
marker = regexp(currentline, ' ', 'once');
name = currentline(1:marker-1);
currentline = regexprep(currentline, currentline(1:marker), '','once');
% Put the last name into a variable by finding the end,
% marked by a space
marker = regexp(currentline, ' ', 'once');
lastname = currentline(1:marker-1);
% Add name to the data structure
APPTS(appt_count).First = deblank(name);
APPTS(appt_count).Last = deblank(lastname);
end
end
end
% Take in the name from the summary field, in case we need it
if regexp(currentline, 'SUMMARY', 'once');
currentline = regexprep(currentline, currentline(1:8), '','once');
% Put the first name into a variable by finding the end of it,
% marked by a space
marker = regexp(currentline, ' ', 'once');
name = currentline(1:marker-1);
currentline = regexprep(currentline, currentline(1:marker), '','once');
% Put the last name into a variable by finding the end,
% marked by a space
marker = regexp(currentline, ' ', 'once');
if isempty(marker)
lastname = currentline;
else
lastname = currentline(1:marker-1);
end
% In the case that the name was not present in the
% DESCRIPTION, we can get it from the Summary!
if isempty(APPTS(appt_count).First)
APPTS(appt_count).First = deblank(name);
end
if isempty(APPTS(appt_count).Last)
APPTS(appt_count).Last = deblank(lastname);
end
end
end
%--------------------------------------------------------------------------
% Find rest of subject info by reading from Appointment file
%--------------------------------------------------------------------------
% Need to find a way to decrease search through appointment file! Right now
% we look at everyone and compare First and Last Name. Since the
% information on the calendar is equivalent to the online system,
% these fields should match for each subject. If we have duplicates, then
% Vanessa can add phone number matching to the script. We place the
% current first and last name in a deblanked variable instead of
% referencing them from the array each time so we can easily calculate the
% length without blank spaces.
for i=1:length(FirstNames)
for k=1:length(APPTS)
currentfirst = deblank(FirstNames{i});
currentlast = deblank(LastNames{i});
if length(APPTS(k).First) >= length(currentfirst)
if strcmp(currentfirst,deblank(APPTS(k).First(1:length(currentfirst))))
if length(APPTS(k).Last) >= length(currentlast)
if strcmp(currentlast,deblank(APPTS(k).Last(1:length(currentlast))))
APPTS(k).Phone = deblank(Phones{i});
APPTS(k).Text = Txt{i};
APPTS(k).Carrier = Carriers{i};
APPTS(k).Email = deblank(Emails{i});
end
end
end
end
end
end
clear currentfirst currentlast
%--------------------------------------------------------------------------
% Send confirmation emails
%--------------------------------------------------------------------------
% Cycle through the participants in the array, and if the appointment was
% made the previous day (since this script runs in the wee hours of the
% morning) we want to send a confirmation email with directions attached.
yesterday = today -1;
for i=1:size(APPTS,2)
if (datenum(APPTS(i).Created) == yesterday)
% -------------------------------------------------------------
% FIRST SEND EMAIL
%--------------------------------------------------------------
% If the subject has an email, we send a confirmation email
if isempty(APPTS(i).Email)==0
sendmail(APPTS(i).Email,[ 'Laboratory of Neurogenetics - ' cal{v} ' Appointment Confirmation' ],[ APPTS(i).First ', this is a confirmation of your ' cal{v} ' session appointment on ' datestr(APPTS(i).Appointment,'mmm dd, yyyy') ' at ' APPTS(i).Time '. For your appointment, please meet the experimenter at ' meetingloc{v} '. Appointment details and directions are attached.' ],reminder_directions);
else
% We will want to know about this error, so we save the
% subject information to an array, to be emailed later.
APPT_ERRORS(email_count+1) = APPTS(i);
end
end
end
%--------------------------------------------------------------------------
% Update sending log
%--------------------------------------------------------------------------
% Initialize and print to file
lid = fopen('CONFIRMATION_LOG.txt', 'a');
% List the headings if the file is just being created
if exist('CONFIRMATION_LOG.txt','file')==0
fprintf(lid, 'Date,Calendar,Appt_Days_Away,First,Last,Email,Phone,Appointment,Time,Text,Carrier,');
end
for i=1:numel(APPTS)
fprintf(lid,'\n%s', [ date ',' ]');
fprintf(lid,'%s', [ cal{v} ',' ]');
fprintf(lid,'%s', [ APPTS(i).First ',' ]');
fprintf(lid,'%s', [ APPTS(i).Last ',' ]');
fprintf(lid,'%s', [ APPTS(i).Email ',' ]');
fprintf(lid,'%s', [ APPTS(i).Phone ',' ]');
fprintf(lid,'%s', [ APPTS(i).Appointment ',' ]');
fprintf(lid,'%s', [ APPTS(i).Time ',' ]');
fprintf(lid,'%s', [ APPTS(i).Text ',' ]');
fprintf(lid,'%s', APPTS(i).Carrier);
end
fclose(lid);
end
clear i Phones Txt Carriers Emails FirstNames LastNames
%--------------------------------------------------------------------------
% Email to send if there are errors in reading the calendar or sending
% brains
%--------------------------------------------------------------------------
if exist('APPT_ERRORS','var')
save('APPT_ERRORS','APPTS.mat');
if exist('contactemail','var')
sendmail(contactemail,'Message from Rem_Email.m',[ 'The script had subjects with missing emails on ' date ' while sending out confirmation emails for the ' cal{v} ' calendar. The attached mat file contains these subjects!'],'APPTS.mat');
end
end
% Exit from matlab to run the next script
exit
end
function rem_email(days,cal,sendtxt,sendemail,contactemail)
% REM_EMAIL
% Vanessa Sochat
%
% This series of scripts can be run to download appointment data from the
% lab calendar and send reminder emails at the time specified. Emails
% sent are recorded
%
% -------------------------------------------------------------------------
% VARIABLES:
% days: This is the number of days in advance that the reminder emails
% will be sent. (1 = 24 hrs, 2 = 48 hrs, etc)
%
% calendars: This is the calendar name that the reminders will be
% sent to, for each of the times indicated. This can currently be
% "Computer" or "Imaging."
%
% sendtxt: 'yes' indicates we want to send a text message, no means no!
%
% sendemail: 'yes' indicates we want to send an email, no means no!
%
% contactemail:(optional) An email address that you want to be notified in
% the case of error
%
% -------------------------------------------------------------------------
% DEPENDENCY:
% For the script to work, it must have access to each of the appointment
% private calendars (URL's hard coded), and the data in the calendar must
% have the user email as the first thing in the Description field, like so
%
% Name: Jane Doe
% Phone: (999) 999-9999
% E-mail: jane.doe@duke.edu
%
% poozie.mat must be in the same folder it is running from
%
% schedule.csv: Downloaded by the batch script just before running
% the matlab script - this file contains all subject specific info that is
% used to look up an individual based on name.
%--------------------------------------------------------------------------
% OUTPUT:
% A temporary file of appointment info for each calendar is saved, but
% deleted when the script finishes running. A log is updated with emails
% that were successfully sent. All files are located under
% Y:/Scripts/Appointments
% -------------------------------------------------------------------------
%--------------------------------------------------------------------------
% Set up mail credentials
%--------------------------------------------------------------------------
load poozie.mat
email_count=0;
% Path to the reminder and directions sheet
reminder_directions = 'Y:/Scripts/Appointments/Reminder_and_Directions.pdf';
% Then this code will set up the preferences properly:
setpref('Internet','E_mail',poozie);
setpref('Internet','SMTP_Server','smtp.gmail.com');
setpref('Internet','SMTP_Username',poozie);
setpref('Internet','SMTP_Password',pooziepa);
props = java.lang.System.getProperties;
props.setProperty('mail.smtp.auth','true');
props.setProperty('mail.smtp.socketFactory.class', 'javax.net.ssl.SSLSocketFactory');
props.setProperty('mail.smtp.socketFactory.port','465');
%--------------------------------------------------------------------------
% Read in appointment file (schedule.csv) downloaded from server
%--------------------------------------------------------------------------
% If the file exists, read it in. If it doesn't, exit with an error,
% record error to the log, and email Vanessa about error.
if exist('schedule.csv','file')
fid = fopen('schedule.csv');
else
% Initialize and print to file
fid = fopen('ERROR_LOG.txt', 'a');
fprintf(fid, 'Date: ');
fprintf(fid,'%s\n', date');
fprintf(fid, 'Schedule file does not exist! Check download.');
fclose(fid);
% If the user has provided an email, alert that email of the failure:
if exist('contactemail','var')
sendmail(contactemail,'Message from Rem_Email.m',[ 'The script exited with error on ' date ' while sending out ' days ' day reminders for the ' calendar ' calendar. '],'');
end
error('Schedule file does not exist');
end
% READ APPOINTMENT INFORMATION FROM FILE
% First read in the header fields
H = textscan(fid, '%s %s %s %s %s %s %s %s %s %s %s \n', 'delimiter', ',');
% StartTime {H1}
% EndTime (H2)
% First Name (H3)
% Last Name (H4)
% Phone (H5)
% Email (H6)
% Type (H7)
% Calendar (H8)
% Duke Unique ID (H9)
% Text Message? (H10)
% Phone Carrier (H11)
% Then read the data from the rest of the file
C = textscan(fid, '%s %s %s %s %s %s %s %s %s %s %s %s %s', 'delimiter', ',');
% StartDate {C1}
% StartTime (C2)
% EndDate (C3)
% EndTime (C4)
% First Name (C5)
% Last Name (C6)
% Phone (C7)
% Email (C8)
% Appointment Type (C9)
% Clinician (C10)
% Unique ID (C11)
% Text Message? (C12)
% Phone Carrier (C13)
% Now we convert a cell array into an array of strings so we can read each
% one, only for the fields that we are interested in.
FirstNames = C{5};
LastNames = C{6};
Phones = C{7};
Emails = C{8};
Txt = C{12};
Carriers = C{13};
fclose(fid);
clear C H fid;
%--------------------------------------------------------------------------
% Download latest appointments from calendar to file
%--------------------------------------------------------------------------
% FOR CALENDAR IN calendars (NEED TO ADD THIS LOOP HERE)
% CD to directory for saving current appointment files
cd('Y:/Scripts/Appointments/');
% Download and save the calendar data
if strcmp(cal,'Imaging')
calie = urlwrite(schmoogie,'imaging.txt','get',{});
meetingloc = 'Soc-Psych 07';
elseif strcmp(cal,'Computer')
meetingloc = 'LSRC B Lobby';
calie = urlwrite(yebya,'computer.txt','get',{});
else
error('Incorrect specification of calendar: only accepts "Computer" and "Imaging"');
end
%--------------------------------------------------------------------------
% Read appointments from the file and save to variable
%--------------------------------------------------------------------------
% Open the subject appointment file, which was an .ical file that we open as
% a text file
fln = fopen(calie);
% Create a subject count variable
appt_count=0;
% Set the current appointment date to today, so we can stop reading the
% file when the appointments go into the past.
Appointment=date;
% Set today's date in a number format for easy comparison
today = datenum(date);
while ~feof(fln)
% We need to make sure that we only read in appointments for today and
% in the future, so we do a comparison between the current appointment
% that is being read. We use a do-->while loop so that the comparison
% until after a subject has been
% Read in line
currentline = fgetl(fln);
% Look to see if we have a date line, which starts with 'DSTART'
if regexp(currentline, 'DTSTART', 'once');
%if yes, pull the date and time from this line, and format
year = currentline(9:12);
month = currentline(13:14);
day = currentline(15:16);
appointment = datestr([ year ' ' month ' ' day ]);
time = currentline(18:21);
time = str2double(time);
% The time is 4 hours in the future, so we subtract 4:
time = time - 400;
% Convert military time to standard time
if (time > 1259)
time = time-1200;
period = 'pm';
else
if (time >= 1200) && (time <= 1259)
period = 'pm';
else
period = 'am';
end
end
% Format time with a ":" by separating the last two characters
% from the first, and sticking them together with a ":"
time = num2str(time);
time_end = time(length(time)-1:length(time));
time_beg = regexprep(time, time_end, '','once');
% Put it all together into a user friendly format for printing
time = [ time_beg ':' time_end ' ' period ];
% If the appointment is from before today, we don't want to do
% anything.
if(today > datenum(appointment))
else
%Add another subject to the array if they aren't from the past
appt_count = appt_count +1;
APPTS(appt_count)= struct('First','','Last','','Email', '','Phone','','Appointment', appointment, 'Time', time,'Text','','Carrier','');
end
end
% Look to see if we have a participant info line:
if regexp(currentline, 'DESCRIPTION', 'once');
% Only read the line if there is data there, meaning the length
% is greater than 12 (the length of DESCRIPTION:)
if length(currentline) > 12
% If the appointment is from the past, skip it, as we did
% above
if (today > datenum(appointment))
else
%if yes, first get rid of the 'DESCRIPTION:Name: ' section
currentline = regexprep(currentline, currentline(1:18), '','once');
% Put the first name into a variable by finding the end of it,
% marked by a space
marker = regexp(currentline, ' ', 'once');
name = currentline(1:marker-1);
currentline = regexprep(currentline, currentline(1:marker), '','once');
% Put the last name into a variable by finding the end,
% marked by a space
marker = regexp(currentline, ' ', 'once');
lastname = currentline(1:marker-1);
% Add name to the data structure
APPTS(appt_count).First = deblank(name);
APPTS(appt_count).Last = deblank(lastname);
end
end
end
% Take in the name from the summary field, in case we need it
if regexp(currentline, 'SUMMARY', 'once');
currentline = regexprep(currentline, currentline(1:8), '','once');
% Put the first name into a variable by finding the end of it,
% marked by a space
marker = regexp(currentline, ' ', 'once');
name = currentline(1:marker-1);
currentline = regexprep(currentline, currentline(1:marker), '','once');
% Put the last name into a variable by finding the end,
% marked by a space
marker = regexp(currentline, ' ', 'once');
if isempty(marker)
lastname = currentline;
else
lastname = currentline(1:marker-1);
end
% In the case that the name was not present in the
% DESCRIPTION, we can get it from the Summary!
if isempty(APPTS(appt_count).First)
APPTS(appt_count).First = deblank(name);
end
if isempty(APPTS(appt_count).Last)
APPTS(appt_count).Last = deblank(lastname);
end
end
end
%--------------------------------------------------------------------------
% Find rest of subject info by reading from Appointment file
%--------------------------------------------------------------------------
% Need to find a way to decrease search through appointment file! Right now
% we look at everyone and compare First and Last Name. Since the
% information on the calendar is equivalent to the online system,
% these fields should match for each subject. If we have duplicates, then
% Vanessa can add phone number matching to the script. We place the
% current first and last name in a deblanked variable instead of
% referencing them from the array each time so we can easily calculate the
% length without blank spaces.
for i=1:length(FirstNames)
for k=1:length(APPTS)
currentfirst = deblank(FirstNames{i});
currentlast = deblank(LastNames{i});
if length(APPTS(k).First) >= length(currentfirst)
if strcmp(currentfirst,deblank(APPTS(k).First(1:length(currentfirst))))
if length(APPTS(k).Last) >= length(currentlast)
if strcmp(currentlast,deblank(APPTS(k).Last(1:length(currentlast))))
APPTS(k).Phone = deblank(Phones{i});
APPTS(k).Text = Txt{i};
APPTS(k).Carrier = Carriers{i};
APPTS(k).Email = deblank(Emails{i});
end
end
end
end
end
end
clear currentfirst currentlast i Phones Txt Carriers Emails FirstNames LastNames
%--------------------------------------------------------------------------
% Send reminder emails
%--------------------------------------------------------------------------
% Cycle through the participants in the array, and if the appointment is
% within the user specified number of days, send a reminder email with
% directions attached.
% Create date (x days away from today) to compare to. If the participant
% has an appointment on this day, he/she should receive a reminder about it
% today!
comparedate = today + days;
for i=1:size(APPTS,2)
if (datenum(APPTS(i).Appointment) == comparedate)
% -------------------------------------------------------------
% FIRST SEND EMAIL
%--------------------------------------------------------------
if strcmp(sendemail,'yes')
% we look at the email field to make sure that it isn't
% blank. If it is, this means that there was no match for
% the subject found in the database
if isempty(APPTS(i).Email)==0
sendmail(APPTS(i).Email,[ 'Laboratory of Neurogenetics - ' cal ' Appointment Reminder' ],[ APPTS(i).First ', this is a reminder about your ' cal ' session appointment on ' datestr(APPTS(i).Appointment,'mmm dd, yyyy') ' at ' APPTS(i).Time '. Please come to ' meetingloc ' and see the attached reminder and directions sheet for location details about your appointment.' ],reminder_directions);
else
% We will want to know about this error, so we save the
% subject information to an array, to be emailed later.
APPT_ERRORS(email_count+1) = APPTS(i);
end
end
% -------------------------------------------------------------
% SECOND SEND TEXT
%--------------------------------------------------------------
if strcmp(sendtxt,'yes')
if strcmp(APPTS(i).Text,'yes')
send_text_message(APPTS(i).Phone,APPTS(i).Carrier, [ cal 'Appointment Reminder' ],[ cal ' appointment reminder: ' datestr(APPTS(i).Appointment,'mmm dd, yyyy') ' at ' APPTS(i).Time ' at ' meetingloc ]);
end
end
end
end
%--------------------------------------------------------------------------
% Update sending log
%--------------------------------------------------------------------------
% Initialize and print to file
lid = fopen('LOG.txt', 'a');
% List the headings if the file is just being created
if exist('LOG.txt','file')==0
fprintf(lid, 'Date,Calendar,Appt_Days_Away,First,Last,Email,Phone,Appointment,Time,Text,Carrier,');
end
for i=1:numel(APPTS)
fprintf(lid,'\n%s', [ date ',' ]');
fprintf(lid,'%s', [ cal ',' ]');
fprintf(lid,'%s', [ days ',' ]');
fprintf(lid,'%s', [ APPTS(i).First ',' ]');
fprintf(lid,'%s', [ APPTS(i).Last ',' ]');
fprintf(lid,'%s', [ APPTS(i).Email ',' ]');
fprintf(lid,'%s', [ APPTS(i).Phone ',' ]');
fprintf(lid,'%s', [ APPTS(i).Appointment ',' ]');
fprintf(lid,'%s', [ APPTS(i).Time ',' ]');
fprintf(lid,'%s', [ APPTS(i).Text ',' ]');
fprintf(lid,'%s', APPTS(i).Carrier);
end
fclose(lid);
%--------------------------------------------------------------------------
% Email to send if there are errors in reading the calendar or sending
% brains
%--------------------------------------------------------------------------
if exist('APPT_ERRORS','var')
save('APPT_ERRORS','APPTS.mat');
if exist('contactemail','var')
sendmail(contactemail,'Message from Rem_Email.m',[ 'The script had subjects with missing emails on ' date ' while sending out ' days ' day reminders for the ' calendar ' calendar. The attached mat file contains these subjects!'],'APPTS.mat');
end
end
% Exit from matlab to run the next script
exit
end
function send_brains()
% SEND BRAIN IMAGES (send_brains.m)
% Vanessa Sochat
%
% This script takes in a list of subjects processed in SPM, creates a brain
% images zip with two .JPG images to send to the subject, and sends it.
%__________________________________________________________________________
%
% DEPENDENCIES: You need to have the crop.m script in the same folder for
% this to work: http://vsoch.com/LONG/Vanessa/MATLAB/Send%20Brains/crop.m
%
% SUBJECT ID: This script is set up to work with DNS data - it is expecting
% IDs to have the format (DATE)_(SUBJECT ID). As the subject output images
% are named with the five numbers after the "_" (representing the subject
% ID) - this is the format that the script is expecting. If your subject
% IDs do not fit this format, you can nix the section that goes through the
% processed subject names and creates a string of modified IDs and just use
% the processed subject list raw without any changes to compare the files
% variable list to.
%
%__________________________________________________________________________
%
% USAGE: send_brains()
% no input variables are required as the program takes them into a GUI.
%__________________________________________________________________________
%
% ORGANIZATION: You should maintain the following file structure:
% Output images under DNS.01\Graphics\Brain Images
% Input Data: We will be using the processed highres under "anat"
% sdns01-005-00001-000001-01.img, to create the image from.
%__________________________________________________________________________
%
% This script works by....
% 1. Creating the list of potential sendees - whoever has been newly
% processed that week and does not have a brain image created yet.
% 2. The script then presents this list to the user, and asks if he/she
% would like to delete any participants. This is important because we
% could have a test folder under Processed, or potentially a participant
% that we don't want to send to. To delete a participant, the user simply
% enters the ID into the GUI, and then the script presents the user with
% the new list. There is no negative consequence of making a typo and
% entering an incorrect ID - the script will not find the ID in the list,
% and will present the identical list to the user, and he/she can enter
% the ID again.
% 3. Next, the script looks for the processed anatomical in the subject's
% anat directory under Processed. This image will normally always have
% the same name - however in rare cases when the name is different,
% for whatever reason, the script will not find the highres, and will
% present the user with a GUI to select the image that he/she would like
% to use for that participant. It then prepares two slice views of the
% highres, crops them, puts them together as a zip, moves the zip to the
% Graphics/Brain Images folder, and cleans up the old files.
% 4. Once all brain image zips have been created, the script prompts the
% user if he/she wants to send a brain image for each subject, and asks
% the user to enter the email. This process is fairly rapid and easy.
% In the case that the user mistypes an email, the easiest thing to do
% is delete the output image, and quickly run the script again.
% 5. As each address in entered, the script sends the email directly from
% MATLAB.
%__________________________________________________________________________
%__________________________________________________________________________
%-Global Variables
%-----------------------------------------------------------------------
fprintf('SEND_BRAIN.M Alpha\n Vanessa Sochat\n August, 2010\n');
% Here the user specifies the experiment directory
homedir = spm_select(1,'dir','Select top of experiment directory','','N:');
% Here the user specifies the output directory
output = spm_select(1,'dir','Select output directory','',[ homedir 'Graphics\' ] );
% Here we set the Processed directory
processed_dir = horzcat(homedir,'Analysis\SPM\Processed\');
% Add the path to the crop script
addpath(genpath('N:\DNS.01\Scripts\MATLAB\Vanessa\Send Brains'));
%-Identify subject list to make brain images for
%-----------------------------------------------------------------------
% Here the script compares the subjects in the "Processed" folder (meaning
% they have been processed and we can send a brain image) to the brain
% images in the output folder. The subject IDs that appear in the Processed
% folder but not the output folder are saved into a variable as they need
% to have brain images sent. Then, the user is allowed to delete subjects
% or text from the string, as it could be likely that there is a TEST
% folder or file in the processed directory that isn't a subject to send
% brain images to.
% First get the processed subjects
cd(processed_dir)
processed = [ ls ];
% And then we grab the subject IDs who have had brain images.
cd(output);
files = [ ls ];
% Initialize brain_list variables
brain_list = '';
% We start at the third element because the first two are "." and ".."
for c = 3:size(processed,1)
% The subject ID always starts at the 10th spot, and ends at te 15th, so we
% use those coordinates to pull the subject IDs fromn the processed variable.
% You will need to change this if you have a different format, or you could
% just get rid of it completely and use the entire subject ID for the image names.
current_processed = processed(c,:);
% By default, add_var starts out as 'yes' and only gets changed to
% no if we find a matched subject ID.
add_var = 'yes';
% VANESSA - MIGHT WANT TO ADD SOME SORT OF BREAK IF A MATCH IS
% FOUND, SO DON'T KEEP SEARCHING ONCE IS FOUND!
for i = 1:size(files,1)
% We take the first 5 characters of the file name, which is the
% subject's ID
subject = files(i,1:5);
if strcmp(current_processed(10:14),subject)
% If the processed subject can be found under the output files
% list, then the brain image has already been processed and we
% exit the loop without adding anything
add_var = 'no';
end
end
% After cycling through the list of brain images already made, we only
% flag the subject as needing an image if the add_var is set to "yes" -
% meaning that no match was ever found.
if strcmp(add_var,'yes')
brain_list = [ brain_list;current_processed ];
end
% and now we move on to the next processed subject at the start of the
% loop
end
% Clean up
clear current_processed subject
fprintf('%s\n','The list of subjects that need brain images is...');
selections = listdlg('PromptString','Select Subjects to send to:','SelectionMode','multiple','ListString',brain_list);
% Pull the user selections from the brain list, and put them in the
% temp_list
add_count = 0;
for j = 1:size(selections,2)
add_count = add_count +1;
temp_list{add_count} = deblank(brain_list(selections(j),:));
end
clear selections
%-Create brain images
%-----------------------------------------------------------------------
% This part of the script goes to the subject's anatomical directory,
% creates the brain image, and saves it to the output directory.
% Initialize graphic viewer
spm_figure('GetWin','Graphics');
clear global st
% Read in logo and prepare file array (to make zip) just once!
I = imread('http://www.haririlab.com/img/logo_small.jpg');
I = imresize(I, 2);
imagefiles{1}='slices.JPG';
imagefiles{2}='sagittal.JPG';
for i=1:size(temp_list,2)
subject = temp_list{i};
% CD to subject's anatomical folder
if exist(horzcat(processed_dir,subject,'/anat/'),'dir')
cd(horzcat(processed_dir,subject,'/anat/'));
% If the default anatomical/highres exists, we use that
if exist(horzcat(processed_dir,subject,'/anat/sdns01-0005-00001-000001-01.img'),'file');
anat = horzcat(processed_dir,subject,'/anat/sdns01-0005-00001-000001-01.img');
% Create slices view and save...
SO=slover();
SO.img(1).vol=spm_vol(anat);
SO.slices = [-36:2:70];
SO=paint(SO);
% Add logo to slices image and save
image(I)
axis off
print -dtiff -noui slices.JPG
crop('slices.JPG');
% Print sagittal view
SO=slover();
SO.img(1).vol=spm_vol(anat);
SO.slices = [-2:10:52];
SO.transform = 'sagittal';
SO=paint(SO);
axis off
print -dtiff -noui sagittal.JPG
crop('sagittal.JPG');
% Prepare zip of two files
zip('brain',imagefiles)
% Save final image to output directory
copyfile('brain.ZIP',[ output,subject(10:14),'.ZIP' ]);
delete brain.ZIP
delete slices.JPG
delete sagittal.JPG
clear SO
else
% If not, we give the user the option to select the file
h = msgbox([ 'Default highres does not exist for ' subject '!' ],'File Not Found','warn');
uiwait(h);
files = [ ls ];
[ selection use_anat ] = listdlg('PromptString','Select file, or CANCEL to skip','SelectionMode','single','ListString',files);
if use_anat == 1
anat = files(selection,:);
% Create slices view and save...
SO=slover();
SO.img(1).vol=spm_vol(anat);
SO.slices = [-36:2:70];
SO=paint(SO);
% Add logo to slices image and save
image(I)
axis off
print -dtiff -noui slices.JPG
crop('slices.JPG');
% Print sagittal view
SO=slover();
SO.img(1).vol=spm_vol(anat);
SO.slices = [-2:10:52];
SO.transform = 'sagittal';
SO=paint(SO);
axis off
print -dtiff -noui sagittal.JPG
crop('sagittal.JPG');
% Prepare zip of two files
zip('brain',imagefiles)
% Save final image to output directory
copyfile('brain.ZIP',[ output,subject(10:14),'.ZIP' ]);
delete brain.ZIP
delete slices.JPG
delete sagittal.JPG
clear SO
else
fprintf('%s%s%s\n','Please take not that subject ',subject,' has been skipped!');
end
end
else
fprintf('%s%s%s\n','Subject ',subject,' does not have an anat folder under Processed!')
end
end
%-Send Brain Images
%-----------------------------------------------------------------------
% This part of the script goes to the output directory and sends an email
% for each subject
cd(output);
% Must be in the same folder as the script
load poozie.mat
% Then this code will set up the preferences properly:
setpref('Internet','E_mail',poozie);
setpref('Internet','SMTP_Server','smtp.gmail.com');
setpref('Internet','SMTP_Username',poozie);
setpref('Internet','SMTP_Password',pooziepa);
props = java.lang.System.getProperties;
props.setProperty('mail.smtp.auth','true');
props.setProperty('mail.smtp.socketFactory.class', 'javax.net.ssl.SSLSocketFactory');
props.setProperty('mail.smtp.socketFactory.port','465');
for i=1:size(temp_list,2)
subject = temp_list{i};
send_var=spm_input([ 'Send image to:',subject(10:14),'?' ],1,'Yes|No');
if strcmp(send_var,'Yes')
email = spm_input([ subject(10:14),' email address:' ],2,'s','',1);
% Check to see if the brain image exists, just in case!
if exist([ subject(10:14),'.ZIP' ],'file')
brain_image=[ subject(10:14),'.ZIP' ];
% Send the email. Note that the first input is the address!
sendmail(email,'Laboratory of Neurogenetics - Brain Image','Attached, please find an image of your brain. This image is intended for personal use only. The image is NOT intended as and should NOT be used as a substitute for medical evaluation.',brain_image);
else
fprintf('%s%s/n',subject(10:14),'.ZIP cannot be found! Brain image not sent!');
end
end
end
fprintf('%s\n','Done sending brain images!');
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment