tasci_merger 0.2.1 → 0.2.2

Sign up to get free protection for your applications and to get access to all the features.
data/lib/tasci_merger.rb CHANGED
@@ -1,333 +1,336 @@
1
- require 'csv'
2
- require_relative 'man_merger'
3
- require_relative 'labtime'
4
-
5
- Time.zone = 'Eastern Time (US & Canada)'
6
-
7
- class TasciMerger
8
-
9
- def initialize(subject_code, tasci_directory, output_directory)
10
- @subject_code = subject_code.chomp
11
- @tasci_directory = tasci_directory.chomp
12
- @output_directory = output_directory.chomp
13
- @master_file_path
14
- end
15
-
16
- def version
17
- '0.0.1'
18
- end
19
-
20
-
21
- def create_master_list
22
- puts "New Version"
23
-
24
- master_file_name = File.join(@output_directory, "tasci_master_#{Time.zone.now.strftime("%Y%m%d")}.csv")
25
- master_file = CSV.open(master_file_name, "wb")
26
-
27
- master_file << %w(file_name file_labtime file_full_time total_epochs start_labtime end_labtime)
28
- master_file_contents = []
29
-
30
- puts @tasci_directory
31
- puts File.exists?(@tasci_directory)
32
-
33
- Dir.foreach(@tasci_directory) do |file|
34
- next if file == '.' or file == '..' or File.extname(file).upcase != ".TASCI"
35
-
36
- puts file
37
-
38
- tasci_file = File.open(File.join(@tasci_directory, file))
39
- file_info = {}
40
-
41
- ## HEADER INFO
42
- # Header Line
43
- tasci_file.readline
44
-
45
- # File Name
46
- read_line = tasci_file.readline
47
- matched_name = /\W*File name \|\W*(.*\.vpd)/i.match(read_line)
48
- puts "ERROR: #{read_line}" unless matched_name
49
- file_info[:source_file_name] = matched_name[1]
50
-
51
- # Record Date
52
- read_line = tasci_file.readline
53
- matched_date = /RecordDate\W*\|\W*(..)\/(..)\/(....)\W*\|.*/.match(read_line)
54
- puts "ERROR: #{read_line}" unless matched_date
55
- #MY_LOG.info "matched_date: #{matched_date[3]} #{matched_date[1]} #{matched_date[2]}"
56
- file_info[:record_date] = (matched_date ? Time.zone.local(matched_date[3].to_i, matched_date[2].to_i, matched_date[1].to_i) : nil)
57
-
58
- # Record Time
59
- read_line = tasci_file.readline
60
- matched_time = /RecordTime\W*\|\W*(..):(..):(..)\W*\|\W*Patient ID\W*\|\W*.*\W*\|/.match(read_line)
61
- puts "ERROR: #{read_line}" unless matched_time
62
- file_info[:record_full_time] = ((matched_time and matched_date) ? Time.zone.local(matched_date[3].to_i, matched_date[2].to_i, matched_date[1].to_i, matched_time[1].to_i, matched_time[2].to_i, matched_time[3].to_i) : nil)
63
- file_info[:record_labtime] = Labtime.parse(file_info[:record_full_time])
64
-
65
- 6.times do
66
- tasci_file.readline
67
- end
68
-
69
- # Epochs and duration
70
- read_line = tasci_file.readline
71
- matched_line = /\W*# Epochs\W*\|\W*(\d+)\W*\|\W*Duration\(S\)\W*\|\W*(\d+)\|/.match(read_line)
72
- puts "ERROR: #{read_line}" unless matched_line
73
- file_info[:epochs] = matched_line[1].to_i - 1
74
- file_info[:epoch_duration] = matched_line[2].to_i
75
-
76
- 5.times do
77
- tasci_file.readline
78
- end
79
-
80
-
81
- first_labtime = nil
82
- last_labtime = nil
83
-
84
- until tasci_file.eof?
85
- line = tasci_file.readline
86
-
87
- matched_line = /(\d+)\|\W*(\d+)\|\W*(\d+)\|\W*(\d+)\|\W*(\d\d):(\d\d):(\d\d)\|\W*(.+)\|\W*(.+)\|/.match(line)
88
- fields = matched_line.to_a
89
- fields.delete_at(0)
90
-
91
- raise StandardError, "fields should have 9 fields: #{fields.length} #{fields} #{line}" unless fields.length == 9
92
-
93
- # Calculating labtime is tricky - file may span two days
94
- calculated_line_time = file_info[:record_full_time] + fields[1].to_i.hours + fields[2].to_i.minutes + fields[3].to_i.seconds
95
- if calculated_line_time.hour == fields[4].to_i and calculated_line_time.min == fields[5].to_i and calculated_line_time.sec == fields[6].to_i
96
- line_time = calculated_line_time
97
- line_labtime = Labtime.parse(line_time)
98
- elsif file_info[:record_full_time].dst? != calculated_line_time.dst?
99
- if (calculated_line_time.hour - fields[4].to_i).abs == 1 and calculated_line_time.min == fields[5].to_i and calculated_line_time.sec == fields[6].to_i
100
- line_time = calculated_line_time
101
- line_labtime = Labtime.parse(line_time)
102
- else
103
- raise StandardError, "Times DO NOT MATCH IN TASCI FILE #{File.basename(tasci_file_path)}!!! #{calculated_line_time.to_s} #{fields[4]} #{fields[5]} #{fields[6]}"
104
- end
105
- else
106
- raise StandardError, "Times DO NOT MATCH IN TASCI FILE #{File.basename(tasci_file_path)}!!! #{calculated_line_time.to_s} #{fields[4]} #{fields[5]} #{fields[6]}"
107
- end
108
-
109
- first_labtime = line_labtime if first_labtime.nil?
110
- last_labtime = line_labtime
111
-
112
- #MY_LOG.info fields
113
- #puts fields
114
- end
115
-
116
- master_file_contents << [file, file_info[:record_labtime].to_short_s, file_info[:record_full_time], file_info[:epochs], first_labtime.to_decimal, last_labtime.to_decimal]
117
- end
118
-
119
- master_file_contents.sort! {|x, y| x[4] <=> y[4] }
120
- master_file_contents.each { |row| master_file << row }
121
-
122
- puts "1. Created master file: #{master_file.path}"
123
- @master_file_path = master_file.path
124
- master_file_name
125
- master_file.close
126
- end
127
-
128
- def merge_files
129
- raise StandardError, "No master file path set! You must run create_master_list before running this function." unless @master_file_path
130
-
131
- merged_file = CSV.open(File.join(@output_directory, "#{@subject_code}_merged_#{Time.zone.now.strftime("%Y%m%d")}.csv"), "wb")
132
- merged_file << %w(SUBJECT_CODE FILE_NAME_SLEEP_WAKE_EPISODE LABTIME SLEEP_STAGE LIGHTS_OFF_ON_FLAG SEM_FLAG)
133
-
134
- simple_merged_file = CSV.open(File.join(@output_directory, "#{@subject_code}_merged_simple_#{Time.zone.now.strftime("%Y%m%d")}.csv"), "wb")
135
- simple_merged_file << %w(SLEEP_STAGE LABTIME)
136
-
137
- previous_first_labtime = nil
138
- previous_last_labtime = nil
139
-
140
- CSV.foreach(@master_file_path, headers: true) do |row|
141
- puts row
142
- tasci_file_path = File.join(@tasci_directory, row[0])
143
-
144
- tasci_file = File.open(tasci_file_path)
145
- file_info = {}
146
-
147
- ## HEADER INFO
148
- # Header Line
149
- tasci_file.readline
150
-
151
- # File Name
152
- read_line = tasci_file.readline
153
- matched_name = /\W*File name \|\W*(.*\.vpd)/i.match(read_line)
154
- puts "ERROR: #{read_line}" unless matched_name
155
- file_info[:source_file_name] = matched_name[1]
156
-
157
- # Record Date
158
- read_line = tasci_file.readline
159
- matched_date = /RecordDate\W*\|\W*(..)\/(..)\/(....)\W*\|.*/.match(read_line)
160
- puts "ERROR: #{read_line}" unless matched_date
161
- #MY_LOG.info "matched_date: #{matched_date[3]} #{matched_date[1]} #{matched_date[2]}"
162
- file_info[:record_date] = (matched_date ? Time.zone.local(matched_date[3].to_i, matched_date[2].to_i, matched_date[1].to_i) : nil)
163
-
164
- # Record Time
165
- read_line = tasci_file.readline
166
- matched_time = /RecordTime\W*\|\W*(..):(..):(..)\W*\|\W*Patient ID\W*\|\W*.*_.*_(\w*)\W*\|/.match(read_line)
167
- puts "ERROR: #{read_line}" unless matched_time
168
- file_info[:record_full_time] = ((matched_time and matched_date) ? Time.zone.local(matched_date[3].to_i, matched_date[2].to_i, matched_date[1].to_i, matched_time[1].to_i, matched_time[2].to_i, matched_time[3].to_i) : nil)
169
- file_info[:record_labtime] = Labtime.parse(file_info[:record_full_time])
170
- file_info[:sleep_wake_episode] = matched_time[4]
171
-
172
- 6.times do
173
- tasci_file.readline
174
- end
175
-
176
- # Epochs and duration
177
- read_line = tasci_file.readline
178
- matched_line = /\W*# Epochs\W*\|\W*(\d+)\W*\|\W*Duration\(S\)\W*\|\W*(\d+)\|/.match(read_line)
179
- puts "ERROR: #{read_line}" unless matched_line
180
- file_info[:epochs] = matched_line[1].to_i
181
- file_info[:epoch_duration] = matched_line[2].to_i
182
-
183
- 5.times do
184
- tasci_file.readline
185
- end
186
-
187
- first_labtime = nil
188
- last_labtime = nil
189
-
190
- until tasci_file.eof?
191
- line = tasci_file.readline
192
-
193
- matched_line = /(\d+)\|\W*(\d+)\|\W*(\d+)\|\W*(\d+)\|\W*(\d\d):(\d\d):(\d\d)\|\W*(.+)\|\W*(.+)\|/.match(line)
194
- fields = matched_line.to_a
195
- fields.delete_at(0)
196
-
197
- raise StandardError, "fields should have 9 fields: #{fields.length} #{fields} #{line}" unless fields.length == 9
198
-
199
- # Calculating labtime is tricky - file may span two days
200
- calculated_line_time = file_info[:record_full_time] + fields[1].to_i.hours + fields[2].to_i.minutes + fields[3].to_i.seconds
201
- if calculated_line_time.hour == fields[4].to_i and calculated_line_time.min == fields[5].to_i and calculated_line_time.sec == fields[6].to_i
202
- line_time = calculated_line_time
203
- line_labtime = Labtime.parse(line_time)
204
- elsif file_info[:record_full_time].dst? != calculated_line_time.dst?
205
- if (calculated_line_time.hour - fields[4].to_i).abs == 1 and calculated_line_time.min == fields[5].to_i and calculated_line_time.sec == fields[6].to_i
206
- line_time = calculated_line_time
207
- line_labtime = Labtime.parse(line_time)
208
- else
209
- raise StandardError, "Times DO NOT MATCH IN TASCI FILE #{File.basename(tasci_file_path)}!!! #{calculated_line_time.to_s} #{fields[4]} #{fields[5]} #{fields[6]}"
210
- end
211
- else
212
- raise StandardError, "Times DO NOT MATCH IN TASCI FILE #{File.basename(tasci_file_path)}!!! #{calculated_line_time.to_s} #{fields[4]} #{fields[5]} #{fields[6]}"
213
- end
214
-
215
- # Sleep Period Coding:
216
- # 1 Sleep Onset (Lights Off)
217
- # 2 Sleep Offset (Lights On)
218
- if /Lights Off|LOff|LightsOn/i.match(fields[7]) # Sleep Onset
219
- sleep_period = 1
220
- elsif /Lights On|LOn|LightsOn/i.match(fields[7]) # Sleep Offset
221
- sleep_period = 2
222
- else
223
- sleep_period = nil
224
- end
225
-
226
- # Sleep Stage Coding:
227
- # 1 stage 1
228
- # 2 stage 2
229
- # 3 stage 3
230
- # 4 stage 4
231
- # 6 MT
232
- # 7 Undef
233
- # 5 REM
234
- # 9 Wake
235
- line_event = nil
236
- if fields[8] == "Wake" || fields[8] == 'Awake'
237
- line_event = 9
238
- elsif fields[8] == "Undefined"
239
- line_event = 7
240
- elsif fields[8] == "N1" || fields[8] == '1'
241
- line_event = 1
242
- elsif fields[8] == "N2" || fields[8] == '2'
243
- line_event = 2
244
- elsif fields[8] == "N3" || fields[8] == '3'
245
- line_event = 3
246
- elsif fields[8] == "N4" || fields[8] == '4'
247
- line_event = 4
248
- elsif fields[8] == "REM"
249
- line_event = 5
250
- elsif fields[8] == "MVT"
251
- line_event = 6
252
- else
253
- raise StandardError, "Cannot map the following event: #{fields[8]}"
254
- end
255
-
256
- # SEM Event Coding:
257
- # 1 Slow Eye Movement
258
- # 0 No Slow Eye Movement
259
- sem_event = (fields[7] =~ /SEM/ ? 1 : 0)
260
-
261
-
262
-
263
-
264
- # Alternate Coding:
265
- # 0 - UNDEF
266
- # 1 - N1
267
- # 2 - N2
268
- # 3 - N3
269
- # 4 - 4
270
- # 5 - Wake
271
- # 6 - REM
272
- # 7 - MT
273
- # 8 - Sleep Onset (LIGHTS OFF)
274
- # 9 - Lights On
275
-
276
- ### SLEEP STAGE, LABTIME
277
- simple_line_event = nil
278
- if fields[8] == "Wake" || fields[8] == 'Awake'
279
- simple_line_event = 5
280
- elsif fields[8] == "Undefined"
281
- simple_line_event = 0
282
- elsif fields[8] == "N1" || fields[8] == '1'
283
- simple_line_event = 1
284
- elsif fields[8] == "N2" || fields[8] == '2'
285
- simple_line_event = 2
286
- elsif fields[8] == "N3" || fields[8] == '3'
287
- simple_line_event = 3
288
- elsif fields[8] == "N4" || fields[8] == '4'
289
- simple_line_event = 4
290
- elsif fields[8] == "REM"
291
- simple_line_event = 6
292
- elsif fields[8] == "MVT"
293
- simple_line_event = 7
294
- else
295
- raise StandardError, "Cannot map the following event: #{fields[8]}"
296
- end
297
-
298
- if sleep_period == 1
299
- simple_line_event = 8
300
- elsif sleep_period == 2
301
- simple_line_event = 9
302
- end
303
-
304
-
305
-
306
-
307
-
308
- first_labtime = line_labtime if first_labtime.nil?
309
- last_labtime = line_labtime
310
-
311
- output_line = [@subject_code.upcase, file_info[:sleep_wake_episode], line_labtime.to_decimal, line_event, sleep_period, sem_event]
312
- simple_output_line = [simple_line_event, line_labtime.to_decimal]
313
- merged_file << output_line
314
- simple_merged_file << simple_output_line
315
-
316
- #MY_LOG.info fields
317
- end
318
-
319
-
320
- unless previous_first_labtime.nil? or previous_last_labtime.nil?
321
- puts "Start time is before previous end labtime: #{previous_last_labtime.to_short_s} #{first_labtime.to_short_s}" if first_labtime < previous_last_labtime
322
- end
323
-
324
-
325
- previous_first_labtime = first_labtime
326
- previous_last_labtime = last_labtime
327
- end
328
- merged_file.close
329
- simple_merged_file.close
330
- end
331
-
332
- end
333
-
1
+ require 'csv'
2
+ require_relative 'man_merger'
3
+ require_relative 'labtime'
4
+
5
+ Time.zone = 'Eastern Time (US & Canada)'
6
+
7
+ class TasciMerger
8
+
9
+ def initialize(subject_code, tasci_directory, output_directory)
10
+ @subject_code = subject_code.chomp
11
+ @tasci_directory = tasci_directory.chomp
12
+ @output_directory = output_directory.chomp
13
+ @master_file_path
14
+ end
15
+
16
+ def version
17
+ '0.0.1'
18
+ end
19
+
20
+
21
+ def create_master_list
22
+ puts "New Version"
23
+
24
+ master_file_name = File.join(@output_directory, "tasci_master_#{Time.zone.now.strftime("%Y%m%d")}.csv")
25
+ master_file = CSV.open(master_file_name, "wb")
26
+
27
+ master_file << %w(file_name file_labtime file_full_time total_epochs start_labtime end_labtime)
28
+ master_file_contents = []
29
+
30
+ puts @tasci_directory
31
+ puts File.exists?(@tasci_directory)
32
+
33
+ Dir.foreach(@tasci_directory) do |file|
34
+ next if file == '.' or file == '..' or File.extname(file).upcase != ".TASCI"
35
+
36
+ puts file
37
+
38
+ tasci_file = File.open(File.join(@tasci_directory, file))
39
+ file_info = {}
40
+
41
+ ## HEADER INFO
42
+ # Header Line
43
+ tasci_file.readline
44
+
45
+ # File Name
46
+ read_line = tasci_file.readline
47
+ matched_name = /\W*File name \|\W*(.*\.vpd)/i.match(read_line)
48
+ puts "ERROR: #{read_line}" unless matched_name
49
+ file_info[:source_file_name] = matched_name[1]
50
+
51
+ # Record Date
52
+ read_line = tasci_file.readline
53
+ matched_date = /RecordDate\W*\|\W*(..)\/(..)\/(....)\W*\|.*/.match(read_line)
54
+ puts "ERROR: #{read_line}" unless matched_date
55
+ #MY_LOG.info "matched_date: #{matched_date[3]} #{matched_date[1]} #{matched_date[2]}"
56
+ file_info[:record_date] = (matched_date ? Time.zone.local(matched_date[3].to_i, matched_date[2].to_i, matched_date[1].to_i) : nil)
57
+
58
+ # Record Time
59
+ read_line = tasci_file.readline
60
+ matched_time = /RecordTime\W*\|\W*(..):(..):(..)\W*\|\W*Patient ID\W*\|\W*.*\W*\|/.match(read_line)
61
+ puts "ERROR: #{read_line}" unless matched_time
62
+ file_info[:record_full_time] = ((matched_time and matched_date) ? Time.zone.local(matched_date[3].to_i, matched_date[2].to_i, matched_date[1].to_i, matched_time[1].to_i, matched_time[2].to_i, matched_time[3].to_i) : nil)
63
+ file_info[:record_labtime] = Labtime.parse(file_info[:record_full_time])
64
+
65
+ 6.times do
66
+ tasci_file.readline
67
+ end
68
+
69
+ # Epochs and duration
70
+ read_line = tasci_file.readline
71
+ matched_line = /\W*# Epochs\W*\|\W*(\d+)\W*\|\W*Duration\(S\)\W*\|\W*(\d+)\|/.match(read_line)
72
+ puts "ERROR: #{read_line}" unless matched_line
73
+ file_info[:epochs] = matched_line[1].to_i - 1
74
+ file_info[:epoch_duration] = matched_line[2].to_i
75
+
76
+ 5.times do
77
+ tasci_file.readline
78
+ end
79
+
80
+
81
+ first_labtime = nil
82
+ last_labtime = nil
83
+
84
+ until tasci_file.eof?
85
+ line = tasci_file.readline
86
+
87
+ matched_line = /(\d+)\|\W*(\d+)\|\W*(\d+)\|\W*(\d+)\|\W*(\d\d):(\d\d):(\d\d)\|\W*(.+)\|\W*(.+)\|/.match(line)
88
+ fields = matched_line.to_a
89
+ fields.delete_at(0)
90
+
91
+ raise StandardError, "fields should have 9 fields: #{fields.length} #{fields} #{line}" unless fields.length == 9
92
+
93
+ # Calculating labtime is tricky - file may span two days
94
+ calculated_line_time = file_info[:record_full_time] + fields[1].to_i.hours + fields[2].to_i.minutes + fields[3].to_i.seconds
95
+ if calculated_line_time.hour == fields[4].to_i and calculated_line_time.min == fields[5].to_i and calculated_line_time.sec == fields[6].to_i
96
+ line_time = calculated_line_time
97
+ line_labtime = Labtime.parse(line_time)
98
+ elsif file_info[:record_full_time].dst? != calculated_line_time.dst?
99
+ if (calculated_line_time.hour - fields[4].to_i).abs == 1 and calculated_line_time.min == fields[5].to_i and calculated_line_time.sec == fields[6].to_i
100
+ line_time = calculated_line_time
101
+ line_labtime = Labtime.parse(line_time)
102
+ else
103
+ raise StandardError, "Times DO NOT MATCH IN TASCI FILE #{File.basename(tasci_file_path)}!!! #{calculated_line_time.to_s} #{fields[4]} #{fields[5]} #{fields[6]}"
104
+ end
105
+ else
106
+ raise StandardError, "Times DO NOT MATCH IN TASCI FILE #{File.basename(tasci_file_path)}!!! #{calculated_line_time.to_s} #{fields[4]} #{fields[5]} #{fields[6]}"
107
+ end
108
+
109
+ first_labtime = line_labtime if first_labtime.nil?
110
+ last_labtime = line_labtime
111
+
112
+ #MY_LOG.info fields
113
+ #puts fields
114
+ end
115
+
116
+ master_file_contents << [file, file_info[:record_labtime].to_short_s, file_info[:record_full_time], file_info[:epochs], first_labtime.to_decimal, last_labtime.to_decimal]
117
+ end
118
+
119
+ master_file_contents.sort! {|x, y| x[4] <=> y[4] }
120
+ master_file_contents.each { |row| master_file << row }
121
+
122
+ puts "1. Created master file: #{master_file.path}"
123
+ @master_file_path = master_file.path
124
+ master_file_name
125
+ master_file.close
126
+ end
127
+
128
+ def merge_files
129
+ raise StandardError, "No master file path set! You must run create_master_list before running this function." unless @master_file_path
130
+
131
+ merged_file = CSV.open(File.join(@output_directory, "#{@subject_code}_merged_#{Time.zone.now.strftime("%Y%m%d")}.csv"), "wb")
132
+ merged_file << %w(SUBJECT_CODE FILE_NAME_SLEEP_WAKE_EPISODE LABTIME SLEEP_STAGE LIGHTS_OFF_ON_FLAG SEM_FLAG)
133
+
134
+ simple_merged_file = CSV.open(File.join(@output_directory, "#{@subject_code}_merged_simple_#{Time.zone.now.strftime("%Y%m%d")}.csv"), "wb")
135
+ simple_merged_file << %w(SLEEP_STAGE LABTIME)
136
+
137
+ sem_merged_file = CSV.open(File.join(@output_directory, "#{@subject_code}_merged_sem_#{Time.zone.now.strftime("%Y%m%d")}.csv"), "wb")
138
+ simple_merged_file << %w(SUBJECT_CODE LABTIME)
139
+
140
+ previous_first_labtime = nil
141
+ previous_last_labtime = nil
142
+
143
+ CSV.foreach(@master_file_path, headers: true) do |row|
144
+ puts row
145
+ tasci_file_path = File.join(@tasci_directory, row[0])
146
+
147
+ tasci_file = File.open(tasci_file_path)
148
+ file_info = {}
149
+
150
+ ## HEADER INFO
151
+ # Header Line
152
+ tasci_file.readline
153
+
154
+ # File Name
155
+ read_line = tasci_file.readline
156
+ matched_name = /\W*File name \|\W*(.*\.vpd)/i.match(read_line)
157
+ puts "ERROR: #{read_line}" unless matched_name
158
+ file_info[:source_file_name] = matched_name[1]
159
+
160
+ # Record Date
161
+ read_line = tasci_file.readline
162
+ matched_date = /RecordDate\W*\|\W*(..)\/(..)\/(....)\W*\|.*/.match(read_line)
163
+ puts "ERROR: #{read_line}" unless matched_date
164
+ #MY_LOG.info "matched_date: #{matched_date[3]} #{matched_date[1]} #{matched_date[2]}"
165
+ file_info[:record_date] = (matched_date ? Time.zone.local(matched_date[3].to_i, matched_date[2].to_i, matched_date[1].to_i) : nil)
166
+
167
+ # Record Time
168
+ read_line = tasci_file.readline
169
+ matched_time = /RecordTime\W*\|\W*(..):(..):(..)\W*\|\W*Patient ID\W*\|\W*.*_.*_(\w*)\W*\|/.match(read_line)
170
+ puts "ERROR: #{read_line}" unless matched_time
171
+ file_info[:record_full_time] = ((matched_time and matched_date) ? Time.zone.local(matched_date[3].to_i, matched_date[2].to_i, matched_date[1].to_i, matched_time[1].to_i, matched_time[2].to_i, matched_time[3].to_i) : nil)
172
+ file_info[:record_labtime] = Labtime.parse(file_info[:record_full_time])
173
+ file_info[:sleep_wake_episode] = matched_time[4]
174
+
175
+ 6.times do
176
+ tasci_file.readline
177
+ end
178
+
179
+ # Epochs and duration
180
+ read_line = tasci_file.readline
181
+ matched_line = /\W*# Epochs\W*\|\W*(\d+)\W*\|\W*Duration\(S\)\W*\|\W*(\d+)\|/.match(read_line)
182
+ puts "ERROR: #{read_line}" unless matched_line
183
+ file_info[:epochs] = matched_line[1].to_i
184
+ file_info[:epoch_duration] = matched_line[2].to_i
185
+
186
+ 5.times do
187
+ tasci_file.readline
188
+ end
189
+
190
+ first_labtime = nil
191
+ last_labtime = nil
192
+
193
+ until tasci_file.eof?
194
+ line = tasci_file.readline
195
+
196
+ matched_line = /(\d+)\|\W*(\d+)\|\W*(\d+)\|\W*(\d+)\|\W*(\d\d):(\d\d):(\d\d)\|\W*(.+)\|\W*(.+)\|/.match(line)
197
+ fields = matched_line.to_a
198
+ fields.delete_at(0)
199
+
200
+ raise StandardError, "fields should have 9 fields: #{fields.length} #{fields} #{line}" unless fields.length == 9
201
+
202
+ # Calculating labtime is tricky - file may span two days
203
+ calculated_line_time = file_info[:record_full_time] + fields[1].to_i.hours + fields[2].to_i.minutes + fields[3].to_i.seconds
204
+ if calculated_line_time.hour == fields[4].to_i and calculated_line_time.min == fields[5].to_i and calculated_line_time.sec == fields[6].to_i
205
+ line_time = calculated_line_time
206
+ line_labtime = Labtime.parse(line_time)
207
+ elsif file_info[:record_full_time].dst? != calculated_line_time.dst?
208
+ if (calculated_line_time.hour - fields[4].to_i).abs == 1 and calculated_line_time.min == fields[5].to_i and calculated_line_time.sec == fields[6].to_i
209
+ line_time = calculated_line_time
210
+ line_labtime = Labtime.parse(line_time)
211
+ else
212
+ raise StandardError, "Times DO NOT MATCH IN TASCI FILE #{File.basename(tasci_file_path)}!!! #{calculated_line_time.to_s} #{fields[4]} #{fields[5]} #{fields[6]}"
213
+ end
214
+ else
215
+ raise StandardError, "Times DO NOT MATCH IN TASCI FILE #{File.basename(tasci_file_path)}!!! #{calculated_line_time.to_s} #{fields[4]} #{fields[5]} #{fields[6]}"
216
+ end
217
+
218
+ # Sleep Period Coding:
219
+ # 1 Sleep Onset (Lights Off)
220
+ # 2 Sleep Offset (Lights On)
221
+ if /Lights Off|LOff|LightsOn/i.match(fields[7]) # Sleep Onset
222
+ sleep_period = 1
223
+ elsif /Lights On|LOn|LightsOn/i.match(fields[7]) # Sleep Offset
224
+ sleep_period = 2
225
+ else
226
+ sleep_period = nil
227
+ end
228
+
229
+ # Sleep Stage Coding:
230
+ # 1 stage 1
231
+ # 2 stage 2
232
+ # 3 stage 3
233
+ # 4 stage 4
234
+ # 6 MT
235
+ # 7 Undef
236
+ # 5 REM
237
+ # 9 Wake
238
+ line_event = nil
239
+ if fields[8] == "Wake" || fields[8] == 'Awake'
240
+ line_event = 9
241
+ elsif fields[8] == "Undefined"
242
+ line_event = 7
243
+ elsif fields[8] == "N1" || fields[8] == '1'
244
+ line_event = 1
245
+ elsif fields[8] == "N2" || fields[8] == '2'
246
+ line_event = 2
247
+ elsif fields[8] == "N3" || fields[8] == '3'
248
+ line_event = 3
249
+ elsif fields[8] == "N4" || fields[8] == '4'
250
+ line_event = 4
251
+ elsif fields[8] == "REM"
252
+ line_event = 5
253
+ elsif fields[8] == "MVT"
254
+ line_event = 6
255
+ else
256
+ raise StandardError, "Cannot map the following event: #{fields[8]}"
257
+ end
258
+
259
+ # SEM Event Coding:
260
+ # 1 Slow Eye Movement
261
+ # 0 No Slow Eye Movement
262
+ sem_event = (fields[7] =~ /SEM/ ? 1 : 0)
263
+
264
+
265
+
266
+
267
+ # Alternate Coding:
268
+ # 0 - UNDEF
269
+ # 1 - N1
270
+ # 2 - N2
271
+ # 3 - N3
272
+ # 4 - 4
273
+ # 5 - Wake
274
+ # 6 - REM
275
+ # 7 - MT
276
+ # 8 - Sleep Onset (LIGHTS OFF)
277
+ # 9 - Lights On
278
+
279
+ ### SLEEP STAGE, LABTIME
280
+ simple_line_event = nil
281
+ if fields[8] == "Wake" || fields[8] == 'Awake'
282
+ simple_line_event = 5
283
+ elsif fields[8] == "Undefined"
284
+ simple_line_event = 0
285
+ elsif fields[8] == "N1" || fields[8] == '1'
286
+ simple_line_event = 1
287
+ elsif fields[8] == "N2" || fields[8] == '2'
288
+ simple_line_event = 2
289
+ elsif fields[8] == "N3" || fields[8] == '3'
290
+ simple_line_event = 3
291
+ elsif fields[8] == "N4" || fields[8] == '4'
292
+ simple_line_event = 4
293
+ elsif fields[8] == "REM"
294
+ simple_line_event = 6
295
+ elsif fields[8] == "MVT"
296
+ simple_line_event = 7
297
+ else
298
+ raise StandardError, "Cannot map the following event: #{fields[8]}"
299
+ end
300
+
301
+ if sleep_period == 1
302
+ simple_line_event = 8
303
+ elsif sleep_period == 2
304
+ simple_line_event = 9
305
+ end
306
+
307
+ first_labtime = line_labtime if first_labtime.nil?
308
+ last_labtime = line_labtime
309
+
310
+ output_line = [@subject_code.upcase, file_info[:sleep_wake_episode], line_labtime.to_decimal, line_event, sleep_period, sem_event]
311
+ simple_output_line = [simple_line_event, line_labtime.to_decimal]
312
+ sem_output_line = [@subject_code.upcase, line_labtime.to_decimal] if sem_event == 1
313
+
314
+ merged_file << output_line
315
+ simple_merged_file << simple_output_line
316
+ sem_merged_file << sem_output_line if sem_event == 1
317
+
318
+ #MY_LOG.info fields
319
+ end
320
+
321
+
322
+ unless previous_first_labtime.nil? or previous_last_labtime.nil?
323
+ puts "Start time is before previous end labtime: #{previous_last_labtime.to_short_s} #{first_labtime.to_short_s}" if first_labtime < previous_last_labtime
324
+ end
325
+
326
+
327
+ previous_first_labtime = first_labtime
328
+ previous_last_labtime = last_labtime
329
+ end
330
+ merged_file.close
331
+ simple_merged_file.close
332
+ sem_merged_file.close
333
+ end
334
+
335
+ end
336
+