tasci_merger 0.1.0 → 0.2.0

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