Adding lines to my graph

hello guys,

I’ve been running the script below in R to plot the frequency vs RMS acceleration diagrams. How can I combine the dataX, Y & Z curves into one diagram, and plot each line without colour into various form of dotted line since my publication can only be in black?

So far I can only ran the script to analyze the X, Y, and Z separately. Modify the line "data<-dataZ" as needed for each axis.

#Gulf Coast Data Concepts
#June 22, 2016
#file name: "car_vibration.r"
#R script for processing X2 accelerometer data into
#a frequency spectrum plot
#----------------------------------------------------
#This script takes a segment of data (a block) and converts
#the time series into a frequency series (Fast Fourier Transform)
#The FFT output represents the energy level for each frequency bin
#The analysis repeats by pulling successive blocks of data 
#throughout the data set.  Each block is plotted during the analysis.
#The results of each FFT are summed and averaged.  The output data is
#saved to a text file
#-----------------------------------------------------

######################################################################
#Functions must be declared first before the script can utilize them #
######################################################################

#fileList is a simple function to build an array of text strings containing
#the files to analyze.  This particular script will only use one data file
#as outlined in the Helmholtz test procedure.  The fileList is kept here to
#maintain continuity with other scripts.  The list will contain only one file
######################################################################
#these lines will build a list using the path, directory, and file numbers defined
#at the beginning of the script
fileList<-function(start, finish, dr, dir){
  dataFiles<-array()
  #prefix name of the data files
  filename<-"DATA-"
  g<-as.numeric(start)
  n<-1
  while(g<(as.numeric(finish)+1)){
    #add leading zeros if need to make valid file name
    if(g<10)
      temp<-paste("00",as.character(g),sep="")
    else if(g<100)
      temp<-paste("0",as.character(g),sep="")
    else
      temp<-as.character(g)  
    name<-paste(filename, temp, ".csv", sep="")
    path<-paste(dr,":", "\\", dir, "\\", name, sep="")
    dataFiles[n]<-path
    g<-g+1
    n<-n+1
  }
  return(dataFiles)
}

#the next few lines of code build a Hann Window filter
#for processing successive FFTs. It's good to filter the
#input data such that there are no discontinuities in the
#transitions between blocks of data.  Hann Window is a common 
#way to do this.
hannWindow<-function(block){  
  #first, initialize the array with a zero
  hann.window<-0
  #the first element of the hann.window array has a 0 so the 
  #index will be initialized to '2' to address the next array element
  z<-2
  #start a loop that will build an element array of factors
  #representing a Hann filter
  while(z<(block+1)){
    #this is the formula for a Hann filter
    temp<-0.5*(1-cos((2*pi*z)/(block-1)))
    #take the new factor and append it to the hann.window array
    hann.window<-append(hann.window, temp)
    #increment the index by 1
    z<-z+1
  }
  return(hann.window)
}

#################################################################
#Function definitions are complete.  Before starting the main 	#
#script, we need to collect information from the user regarding #
#files and analysis parameters.							#
#################################################################

#First, print a note to the user that this script is intended
#for Windows PCs and the file directory path is not compatible
#with Mac or Linux.
print("##############################################")
print("Note, this script is intended for Windows based PCs.")
print("The file path locations are not compatible with Mac/Linux")
print("##############################################")

#ask for the drive location of the data files
#this is the drive or path that contains the GCDC directory
drive<-(-1)
while(drive<0){
  drive<-readline("Enter drive location letter: ")
  drive<-ifelse(grepl("[a-z,A-Z]", drive), as.character(drive), -1)
}
  
#the directory containing the data files
#ask for the drive location of the data files
#this is the drive or path that contains the GCDC directory
directory<-(-1)
while(directory<0){
  directory<-readline("Enter drive location letter(GCDC): ")
  if(directory==""){
    directory="GCDC"
    break
  }
  directory<-as.character(directory)
}
  
#prefix name of the data files
filename<-"DATA-"
#the data logger creates files sequentially numbered
#the following parameters define the file numbers to analyze
#for example, files 377 through 380
#ask for the sequential files to analyze
fileNumStart<-(-1)
while(fileNumStart<0){
  fileNumStart<-readline("Enter the file to analyze: ")
  fileNumStart<-ifelse(grepl("[0-9]", fileNumStart), as.numeric(fileNumStart),-1)
}
#the script uses only one file so the fileList will include only 
#one entry
fileNumFinish<-fileNumStart

#build a vector list of files to analyze
#the first file is used to determine the start_time
dataFiles<-fileList(fileNumStart, fileNumFinish, drive, directory)
  
#open the first file and read the first five lines
#the third line contains the start_time
lines<-readLines(dataFiles[1],6)
#parse the lines
date<-unlist(strsplit(lines[3],","))
#combine the 2 and 3 entries into a date/time
d<-paste(date[2],date[3])
#convert the date/time text into a R type date
startDate<-as.POSIXlt(d)

#read the sample rate setting from the first data file
#the X2 logger records sample rate on line 6 of the file header
temp<-unlist(strsplit(lines[6],","))
SR<-as.numeric(temp[2])

#is user ready to start analysis
test<-(-1)
while(test<0){
  test<-readline("Press Enter to start analysis! ")
  if(test==""){
    break
  }else{
    test<-(-1)
  }
}

############################################################  
#the following parameters affect the analysis algorithm	#
############################################################  

#block is a segment of data processed through the FFT algorithm
#The script will process 4 seconds of data thru the FFT
block<-4*SR
#the FFT function can't handle blocks of data larger than 4096
if(block<0 | block>4096){
  print("Invalid block size")
  block<-4096
}
  
#the script progresses through data set pulling
#blocks of data.  Each block of data can overlap the
#previous block of data.  Overlapping the data improves
#the signal-to-noise of the results but increases
#computations and time
#define the FFT overlap, 1=0%, 2=50%, 4=75%, etc
overlap<-4	#75% of data will overlap previous block of data
		#and 25% will be new data from the file

######################################################################
# Analysis parameters finished.  Now, set up variables before		#
# starting the main part of script							#
######################################################################

#check system clock for start of analysis
startTime<-Sys.time()

#cfactor is used to convert the raw data into "g".  The factor
#is different depending on the logger type and sensor range.
#X16 series 	-> 2048
#X2, low gain	-> 6554
#X2, high gain	-> 13108
#X200			-> 163.8
cfactor<-6554

#initialize three arrays to store the xyz data
dataX<-array(0)
dataY<-array(0)
dataZ<-array(0)

#a time value is calculated for each FFT, time increases with
#each new block of data as the script proceeds through a file.
#The time values are stored to timearray. When a new file is opened,
#timeF is used to carry the last time value into the new file data
time<-0
timeF<-time

#timearray stores all the FFT time values and is used later for
#plotting purposes
timearray<-array(0)

#build a history of FFTs
fftHistory<-array(0)

#build a Hann Window filter
#when processing successive FFTs it's good to filter the
#input data such that there are no discontinuities in the
#transitions.  Hann Window is a common way to do this.
hann.window<-hannWindow(block)

#build an array of frequency values based on fft size
#this is used for plotting the spectral output
x.axis<-0:(block/2-1)	
x.axis<-x.axis*((SR/2)/(block/2))


#####################################################################
# START OF MAIN SECTION                                             #
#####################################################################

#this loop will read the input file into three arrays
#there is only one data file so this loop will complete once
f<-1
while(f<(length(dataFiles)+1)){
  print(paste("Opening data file:  ", dataFiles[f]))
  colNames<-c("time", "Ax", "Ay","Az")
  dataIn<-read.table(dataFiles[f], sep=",", comment=";", col.names=colNames, fill=TRUE)
  
  #initialize three arrays to store the xyz data
  dataX<-array(0)
  dataY<-array(0)
  dataZ<-array(0)
  
  #use spline to resample the data into evenly spaced samples.  The accelerometer
  #sensor streams data at the set sample rate but this may vary depending on
  #the accuracy of the sensor's clock.  For example, configuring to sample at 400Hz
  #may actually result in data recorded at 410Hz.  We need the resulting data to be
  #very accurate and consistent.  Therefore, as data arrives to the logger CPU, it is time
  #stamped using an independent and accurate real time clock.  These time stamps 
  #are assumed to be accurate.  We will resample the data based on 
  #the time stamps to ensure the time series data is consistent and accurate.
  ################################################################################

  #determine the total time recorded in the file by finding the 
  #largest time stamp and subtracting the smallest time stamp
  timeFile=max(dataIn[,1])-min(dataIn[,1])
  #total number of samples that should be in the file assuming
  #the sample rate used.  In reality, the sensor may produce data 
  #slower or faster than the set rate, that's why we are resampling
  numberSamples=timeFile*SR
  #The time stamps are based on the real time clock so these values are 
  #accurate.  However, the arrival of the data could be different than the 
  #set sample rate due to the sensor's clock error.  Therefore, we will
  #use a cubic spline algorithm to resample each axis such that the 
  #sample timing is consistent.  This will improve the accuracy of the FFT
  #by correcting the sample rate error from the sensor.
  resample<-spline(dataIn[,1],dataIn[,2],n=numberSamples,xmin=min(dataIn[,1]),xmax=max(dataIn[,1]))
  dataTime<-unlist(resample[1])
  dataX<-unlist(resample[2])
  resample<-spline(dataIn[,1],dataIn[,3],n=numberSamples,xmin=min(dataIn[,1]),xmax=max(dataIn[,1]))
  dataTime<-unlist(resample[1])
  dataY<-unlist(resample[2])	
  resample<-spline(dataIn[,1],dataIn[,4],n=numberSamples,xmin=min(dataIn[,1]),xmax=max(dataIn[,1]))
  dataTime<-unlist(resample[1])
  dataZ<-unlist(resample[2])
  
  #Convert the raw data into g's
  dataX<-(dataX)/cfactor
  dataY<-(dataY)/cfactor
  dataZ<-(dataZ)/cfactor
  
  #Evaluate the z-axis data which is vertical to the road surface
  data<-dataZ
  #Another way to look at the data is to use the RMS magnitude all three axis
  #data<-sqrt(dataX^2+dataY^2+dataZ^2)
  
	#this is the main loop to calculate each FFT.  First, a block data points
	#is pulled from the input data and the Hann filter applied to it.  An FFT is
	#performed on the filtered data.  The "Mod" function extracts the real portion 
 	#of the FFT.  The results of the FFT are summed and then averaged.
	i<-1
	while((i+block)<length(data)) {
		datablock<-data[i:((block-1)+i)]	#get the data
		data.hann<-hann.window*datablock	#apply the filter
		data.fft<-fft(data.hann)			#perform FFT
		#data.fft<-fft(datablock)			#no filter
		data.mod<-Mod(data.fft)			#Mod separates the real and imaginary values
		data.mod.half<-data.mod[1:((length(data.mod))/2)]	#use the real half of FFT
	
		#correct output so values are in acceleration units (g)
		fftOutput<-data.mod.half/(block/2)

		#calculate the time stamp for this particular block of data
		time<-timeF+(i+block)/SR/60

		#combine the FFT and x.axis into one array for plotting purposes
		output<-array(c(x.axis, fftOutput), dim=c(length(x.axis),2)) #combine arrays
		#plot the output in log scale on the y-axis
		#this plot shows the spectral response of the resonating bottle
		plot(output, type="l", xlim=c(0,SR/2), ylim=c(1e-6,1e6), log="y", tck=1, xlab="Frequency", ylab="Total RMS Acceleration (g)")
		text(round(time, 1), x=70, y=50)
		text("elapsed minutes", x=70, y=10)
		#Sys.sleep(0.1)	#pause so the plots don't flash by too quickly
		    
    		#add the fft result to the history
    		fftHistory<-fftHistory+fftOutput

		#save the time stamp associated with this block of data
		timearray<-append(timearray, time)
	
		#increment the index by a percentage of the block
		#defined by the overlap variable.
		i<-i+(block/overlap)
		    
		#back to the top of loop and repeat everything for
		#the next block of data
	}
  
	#update timeF to track time into the next data file
	timeF<-time

	#move to the next file
	f<-f+1	#increment f
  
	#back to top of main loop to repeat everything
  	#for next data file
}
#end of main loop

#convert time into date
timeDate<-startDate+timearray*60

#average out the FFT history
fftHistory<-fftHistory/(length(timearray))

#plot averaged spectral response for the entire data set
output<-array(c(x.axis, fftHistory), dim=c(length(x.axis),2)) 
plot(output, type="l", tck=1, xlab="Frequency (Hz)", ylab="RMS Acceleration", xlim=c(0,SR/2), ylim=c(0,max(fftHistory[5:length(fftHistory)])), main=dataFiles[1])
text(paste("Data File:",dataFiles[1]), x=SR/4, y=0.005, col="red")

#finished analysis
finishTime<-Sys.time()
#print(paste("total time for analysis: ",(finishTime-startTime)/60," minutes"))

#write the results to the output file
#uncomment the next two lines to have the results stored to a file
outputDataFile<-paste(drive,":\\","analysis_output_of_File_", as.character(fileNumStart),".txt", sep="")
columnOutput=c("freq","accel (g)")
write.table(output, outputDataFile, sep="\t",row.names=FALSE, col.names=columnOutput)