tasci_merger 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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
+