function isEqualArray(a, b) { if(a.length == b.length) { for(var i = a.length - 1; i >= 0; --i) if(a[i] != b[i]) return false; return true; } else return false; } export function lab_parse(data) { data = data.join('\n'); if(data == '\nNo Data Found') return []; return data.split('\n===============================================================================\n \n').map(lab_parse1).filter(x => x); } export function lab_reparse_results(reports) { var res = [], report, result; for(var i = 0; i < reports.length; ++i) { if((report = reports[i]).hasOwnProperty('results')) { report = Object.assign({}, report); var results = report.results; delete report.results; if(report.hasOwnProperty('comment')) delete report.comment; for(var j = 0; j < results.length; ++j) res.push(result = Object.assign({}, report, results[j])); } } return res; } function lab_parse1(data) { if(data.startsWith('\n')) return lab_parse1default(data); if(data.startsWith(' ---- MICROBIOLOGY ----\n')) return lab_parse1microbiology(data); if(data.startsWith('Performing Lab Sites\n')) return null; } function lab_parse1default(data) { var res = {}, m, x, line; if(m = data.match(/^Report Released Date\/Time: (.*)/m)) res.time_released = new Date(m[1]); // 'Aug 24, 2022@07:15' if(m = data.match(/^Provider: (.*)/m)) res.practitioner = m[1]; // 'BARGNES,VINCENT HARRY III' if(m = data.match(/^ Specimen: (.*?)\.\s*(.*)/m)) { res.specimen = m[1]; // 'SERUM' res.accession = m[2]; // 'CH 0800 6706' } if(m = data.match(/^ Specimen Collection Date: (.*)/m)) res.time_collected = new Date(m[1]); // 'Aug 24, 2022' data = data.split('\n Test name Result units Ref. range Site Code\n')[1].split('\n'); var results = res.results = []; for(var i = 0; i < data.length; ++i) { if((line = data[i]).startsWith('Comment: ')) { res.comment = data.slice(i).join('\n').substring(9); break; } else if(line.startsWith(' Eval: ')) { if(results.length > 0) { x = results[results.length - 1]; if(x.comment) x.comment.push(line.substring(12)); else x.comment = [line.substring(12)]; } else console.log('DANGLING:', line); } else if(m = line.match(/^\b(?.*?)\s{2,}(?.*?)(?: (?L\*|L|H\*|H))?\s+(?:(?.{10}) (?.*?)(?: \[(?\d+)\])?)?$/)) { if((m.groups.range) && (m.groups.range.startsWith('Ref: '))) m.groups.range = m.groups.range.substring(5); results.push(x = m.groups); if((x.value === '') && (m = x.name.match(/^(?.*?)(?(?:[\d\.]+|positive|negative|reactive|not detected|collected - specimen in lab|test not performed))\s*$/i))) { x.name = m.groups.name; x.value = m.groups.value; } for(var k in x) if(x[k]) x[k] = x[k] ? x[k].replace(/^\s+|\s+$/g, '') : undefined; } else if(m = line.match(/^\b(?.*?) (?(?:[\d\.]+|positive|negative|reactive|not detected|collected - specimen in lab|test not performed))\s*$/i)) { results.push(x = m.groups); for(var k in x) if(x[k]) x[k] = x[k] ? x[k].replace(/^\s+|\s+$/g, '') : undefined; } else if(line.startsWith(' [')) { if(results.length > 0) results[results.length - 1].site = line.split('[')[1].split(']')[0] else console.log('DANGLING:', line); } else if(line.startsWith(' ')) { if(results.length > 0) { x = results[results.length - 1]; if(line.endsWith(']')) { x.range = line.split('[')[0].replace(/^\s+|\s+$/g, ''); x.site = line.split('[')[1].split(']')[0]; } else x.range = line.replace(/^\s+|\s+$/g, ''); } else console.log('DANGLING:', line); } else if(m = line.match(/^\s{40}\b(?:(?.{10}) (?.*?)(?: \[(?\d+)\])?)?$/)) { if(results.length > 0) { x = results[results.length - 1]; if(m.groups.unit) x.unit = m.groups.unit.replace(/^\s+|\s+$/g, ''); if(m.groups.range) x.range = m.groups.range.replace(/^\s+|\s+$/g, ''); if(m.groups.site) x.site = m.groups.site.replace(/^\s+|\s+$/g, ''); } else console.log('DANGLING:', line, m.groups); } else console.log('INVALID:', line); } for(var i = results.length - 1; i >= 0; --i) { results[(x = results[i]).name] = x; if(x.comment) x.comment = x.comment.join('\n'); } if(res.accession.startsWith('HE ')) { if((results.hasOwnProperty('SEGS')) || (results.hasOwnProperty('BANDS'))) { results.push(results['NEUTROPHIL%'] = { name: 'NEUTROPHIL%', unit: '%', range: '42.2 - 75.2', value: x = (results.hasOwnProperty('SEGS') ? +results.SEGS.value : 0) + (results.hasOwnProperty('BANDS') ? +results.BANDS.value : 0), flag: (x < 42.2 ? 'L' : x > 75.2 ? 'H' : undefined) }); results.push(results['NEUTROPHIL#'] = { name: 'NEUTROPHIL#', unit: 'K/cmm', range: '1.4 - 6.5', value: +(x = 0.01*x*results.WBC.value).toFixed(3), flag: (x < 1.4 ? 'L' : x > 6.5 ? 'H' : undefined) }); } if((results.hasOwnProperty('LYMPHS')) || (results.hasOwnProperty('ATYPICAL LYMPHOCYTES'))) { results.push(results['LYMPHOCYTE%'] = { name: 'LYMPHOCYTE%', unit: '%', range: '15.0 - 41.0', value: x = (results.hasOwnProperty('LYMPHS') ? +results.LYMPHS.value : 0) + (results.hasOwnProperty('ATYPICAL LYMPHOCYTES') ? +results['ATYPICAL LYMPHOCYTES'].value : 0), flag: (x < 15 ? 'L' : x > 41 ? 'H' : undefined) }); results.push(results['LYMPHOCYTE#'] = { name: 'LYMPHOCYTE#', unit: 'K/cmm', range: '1.2 - 3.4', value: +(x = 0.01*x*results.WBC.value).toFixed(3), flag: (x < 1.2 ? 'L' : x > 3.4 ? 'H' : undefined) }); } } return res; } function lab_parse1microbiology(data) { var res = {}, lines = data.split('\n'), line, m; var idx_body = lines.indexOf(' '); for(var i = 0; i < lines.length; ++i) { line = lines[i]; if(line.startsWith('Accession [UID]: ')) { if(m = line.match(/^Accession \[UID\]: (?.*?) \[(?\d+)\]/)) { // 'BCUL 22 819 [3922000819]' res.accession = m.groups.accession; res.accession_uid = m.groups.accession_uid; } if(m = line.match(/Received: (.*)$/)) res.time_received = new Date(m[1]); // 'Aug 01, 2022@11:57' } else if(line.startsWith('Collection sample: ')) { res.sample = line.substring(0, 39).substring(19).replace(/^\s+|\s+$/g, ''); res.time_collected = new Date(line.substring(39).split('Collection date: ')[1].replace(/^\s+|\s+$/g, '')); } else if(line.startsWith('Site/Specimen: ')) { res.specimen = line.substring(15).replace(/^\s+|\s+$/g, ''); } else if(line.startsWith('Provider: ')) { res.practitioner = line.substring(10).replace(/^\s+|\s+$/g, ''); } else if(line.startsWith('Comment on specimen:')) { res.comment = lines.slice(i, idx_body).join('\n').substring(20).replace(/^\s+|\s+$/g, ''); break } } var idx_footer = lines.indexOf('=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--') if(idx_footer > idx_body) { res.body = lines.slice(idx_body, idx_footer).join('\n').replace(/^\s+|\s+$/g, ''); res.footer = lines.slice(idx_footer + 1).join('\n').replace(/^\s+|\s+$/g, ''); } else res.body = lines.slice(idx_body).join('\n').replace(/^\s+|\s+$/g, ''); return res; } export function measurement_parse(data) { var extras = []; var res = data.map(function(row) { if(row.charAt(0) != ' ') { var res = {}, idx = 0, value, m; res.measurement_ien = row.substring(0, idx = row.indexOf('^')); if(res.measurement_ien == '0') return; // '0^NO VITALS/MEASUREMENTS ENTERED WITHIN THIS PERIOD' res.datetime = new Date(row.substring(idx + 1, idx = row.indexOf(' ', idx))); res.name = row.substring(idx + 3, idx = row.indexOf(': ', idx)); value = row.substring(idx + 4, idx = row.indexOf(' _', idx)); res.user = row.substring(idx + 2); m = value.match(/^(?:(.*?)(?: (\S+))?)(\*)?(?: \((?:(.*?)(?: (\S+))?)\))?\s*$/); res.value = m[4] ? m[4] : m[1]; res.unit = m[4] ? m[5] : m[2]; res.flag = m[3]; res.value_american = m[4] ? m[1] : m[4]; res.unit_american = m[4] ? m[2] : m[5]; if(res.value.charAt(res.value.length - 1) == '%') { res.unit = '%'; res.value = res.value.substring(0, res.value.length - 1); } if(res.name == 'B/P') { var bpsplit = res.value.split('/'); extras.push({...res, name: 'SBP', range: '90 - 120', unit: 'mmHg', value: bpsplit[0] }); extras.push({...res, name: 'DBP', range: '60 - 80', unit: 'mmHg', value: bpsplit[1] }); } return res; } }).filter(x => x); res.push(...extras); return res; }