tasci_merger 0.2.1 → 0.2.2

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,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
+