コード例 #1
0
ファイル: gmNetworkTools.py プロジェクト: rockdriven/gnumed
def compare_versions(left_version, right_version):
    """
	 0: left == right
	-1: left < right
	 1: left > right
	"""
    _log.debug('comparing [%s] with [%s]', left_version, right_version)
    if left_version == right_version:
        _log.debug('same version')
        return 0

    if right_version in ['head', 'dev', 'devel']:
        _log.debug('development code')
        return -1

    if left_version in ['head', 'dev', 'devel']:
        _log.debug('development code')
        return 1

    left_parts = left_version.split('.')
    right_parts = right_version.split('.')

    tmp, left_major = gmTools.input2decimal('%s.%s' %
                                            (left_parts[0], left_parts[1]))
    tmp, right_major = gmTools.input2decimal('%s.%s' %
                                             (right_parts[0], right_parts[1]))

    if left_major < right_major:
        _log.debug('left version [%s] < right version [%s]: major part',
                   left_version, right_version)
        return -1

    if left_major > right_major:
        _log.debug('left version [%s] > right version [%s]: major part',
                   left_version, right_version)
        return 1

    tmp, left_part3 = gmTools.input2decimal(left_parts[2].replace('rc', '0.'))
    tmp, right_part3 = gmTools.input2decimal(right_parts[2].replace(
        'rc', '0.'))

    if left_part3 < right_part3:
        _log.debug('left version [%s] < right version [%s]: minor part',
                   left_version, right_version)
        return -1

    if left_part3 > right_part3:
        _log.debug('left version [%s] > right version [%s]: minor part',
                   left_version, right_version)
        return 1

    return 0
コード例 #2
0
ファイル: gmNetworkTools.py プロジェクト: jeromecc/gnumed
def compare_versions(left_version, right_version):
    """
	 0: left == right
	-1: left < right
	 1: left > right
	"""
    if left_version == right_version:
        _log.debug('same version: [%s] = [%s]', left_version, right_version)
        return 0

    left_parts = left_version.split('.')
    right_parts = right_version.split('.')

    tmp, left_major = gmTools.input2decimal(u'%s.%s' %
                                            (left_parts[0], left_parts[1]))
    tmp, right_major = gmTools.input2decimal(u'%s.%s' %
                                             (right_parts[0], right_parts[1]))

    if left_major < right_major:
        _log.debug('left version [%s] < right version [%s]: major part',
                   left_version, right_version)
        return -1

    if left_major > right_major:
        _log.debug('left version [%s] > right version [%s]: major part',
                   left_version, right_version)
        return 1

    tmp, left_part3 = gmTools.input2decimal(left_parts[2].replace('rc', '0.'))
    tmp, right_part3 = gmTools.input2decimal(right_parts[2].replace(
        'rc', '0.'))

    if left_part3 < right_part3:
        _log.debug('left version [%s] < right version [%s]: minor part',
                   left_version, right_version)
        return -1

    if left_part3 > right_part3:
        _log.debug('left version [%s] > right version [%s]: minor part',
                   left_version, right_version)
        return 1

    return 0
コード例 #3
0
ファイル: gmNetworkTools.py プロジェクト: sk/gnumed
def compare_versions(left_version, right_version):
	"""
	 0: left == right
	-1: left < right
	 1: left > right
	"""
	if left_version == right_version:
		_log.debug('same version: [%s] = [%s]', left_version, right_version)
		return 0

	left_parts = left_version.split('.')
	right_parts = right_version.split('.')

	tmp, left_major = gmTools.input2decimal(u'%s.%s' % (left_parts[0], left_parts[1]))
	tmp, right_major = gmTools.input2decimal(u'%s.%s' % (right_parts[0], right_parts[1]))

	if left_major < right_major:
		_log.debug('left version [%s] < right version [%s]: major part', left_version, right_version)
		return -1

	if left_major > right_major:
		_log.debug('left version [%s] > right version [%s]: major part', left_version, right_version)
		return 1

	tmp, left_part3 = gmTools.input2decimal(left_parts[2].replace('rc', '0.'))
	tmp, right_part3 = gmTools.input2decimal(right_parts[2].replace('rc', '0.'))

	if left_part3 < right_part3:
		_log.debug('left version [%s] < right version [%s]: minor part', left_version, right_version)
		return -1

	if left_part3 > right_part3:
		_log.debug('left version [%s] > right version [%s]: minor part', left_version, right_version)
		return 1

	return 0
コード例 #4
0
ファイル: gmHL7.py プロジェクト: sk/gnumed
def __import_single_PID_hl7_file(filename, emr=None):
	"""Assumes single-PID/single-MSH HL7 file."""

	_log.debug('importing single-PID single-MSH HL7 data from [%s]', filename)

	# read the file
	MSH_file = io.open(filename, mode = 'rt', encoding = 'utf8')
	HL7 = pyhl7.parse(MSH_file.read(1024 * 1024 * 5))	# 5 MB max
	MSH_file.close()

	# sanity checks
	if len(HL7.segments('MSH')) != 1:
		_log.error('more than one MSH segment')
		return False
	if len(HL7.segments('PID')) != 1:
		_log.error('more than one PID segment')
		return False

	# ensure lab is in database
	hl7_lab = HL7.extract_field('MSH', field_num = MSH_field__sending_lab)
	gm_lab = __find_or_create_lab(hl7_lab)

	# ensure test types exist
	conn = gmPG2.get_connection(readonly = False)
	__ensure_hl7_test_types_exist_in_gnumed(link_obj = conn, hl7_data = HL7, pk_test_org = gm_lab['pk_test_org'])

	# find patient
	if emr is None:
		#PID = HL7.segment('PID')
		pats = __PID2dto(HL7 = HL7)
		if len(pats) == 0:
			conn.rollback()
			return False
		if len(pats) > 1:
			conn.rollback()
			return False
		emr = pats[0].emr

	# import values: loop over segments
	when_list = {}
	current_result = None
	previous_segment = None
	had_errors = False
	msh_seen = False
	pid_seen = False
	last_obr = None
	obr = {}
	for seg_idx in range(len(HL7)):
		seg = HL7[seg_idx]
		seg_type = seg[0][0]

		_log.debug('processing line #%s = segment of type <%s>', seg_idx, seg_type)

		if seg_type == u'MSH':
			msh_seen = True

		if seg_type == u'PID':
			if not msh_seen:
				conn.rollback()
				_log.error('PID segment before MSH segment')
				return False
			pid_seen = True

		if seg_type in [u'MSH', u'PID']:
			_log.info('segment already handled')
			previous_segment = seg_type
			obr = {}
			current_result = None
			continue

		if seg_type in [u'ORC']:
			_log.info('currently ignoring %s segments', seg_type)
			previous_segment = seg_type
			obr = {}
			current_result = None
			continue

		if seg_type == u'OBR':
			previous_segment = seg_type
			last_obr = seg
			current_result = None
			obr['abbrev'] = (u'%s' % seg[OBR_field__service_name][0]).strip()
			try:
				obr['name'] = (u'%s' % seg[OBR_field__service_name][1]).strip()
			except IndexError:
				obr['name'] = obr['abbrev']
			for field_name in [OBR_field__ts_ended, OBR_field__ts_started, OBR_field__ts_specimen_received, OBR_field__ts_requested]:
				obr['clin_when'] = seg[field_name][0].strip()
				if obr['clin_when'] != u'':
					break
			continue

		if seg_type == u'OBX':
			current_result = None
			# determine value
			val_alpha = seg[OBX_field__value][0].strip()
			is_num, val_num = gmTools.input2decimal(initial = val_alpha)
			if is_num:
				val_alpha = None
			else:
				val_num = None
				val_alpha = val_alpha.replace('\.br\\', u'\n')
			# determine test type
			unit = seg[OBX_field__unit][0].strip()
			if unit == u'':
				if is_num:
					unit = u'1/1'
				else:
					unit = None
			test_type = __find_or_create_test_type (
				loinc = u'%s' % seg[OBX_field__type][0][OBX_component__loinc-1],
				name = u'%s' % seg[OBX_field__type][0][OBX_component__name-1],
				pk_lab = gm_lab['pk_test_org'],
				unit = unit
			)
			# eventually, episode should be read from lab_request
			epi = emr.add_episode (
				link_obj = conn,
				episode_name = u'administrative',
				is_open = False,
				allow_dupes = False
			)
			current_result = emr.add_test_result (
				link_obj = conn,
				episode = epi['pk_episode'],
				type = test_type['pk_test_type'],
				intended_reviewer = gmStaff.gmCurrentProvider()['pk_staff'],
				val_num = val_num,
				val_alpha = val_alpha,
				unit = unit
			)
			# handle range information et al
			ref_range = seg[OBX_field__range][0].strip()
			if ref_range != u'':
				current_result.reference_range = ref_range
			flag = seg[OBX_field__abnormal_flag][0].strip()
			if flag != u'':
				current_result['abnormality_indicator'] = flag
			current_result['status'] = seg[OBX_field__status][0].strip()
			current_result['val_grouping'] = seg[OBX_field__subid][0].strip()
			current_result['source_data'] = u''
			if last_obr is not None:
				current_result['source_data'] += unicode(last_obr)
				current_result['source_data'] += u'\n'
			current_result['source_data'] += unicode(seg)
			clin_when = seg[OBX_field__timestamp][0].strip()
			if clin_when == u'':
				_log.warning('no <Observation timestamp> in OBX, trying OBR timestamp')
				clin_when = obr['clin_when']
			try:
				clin_when = __hl7dt2pydt(clin_when)
			except ValueError:
				_log.exception('clin_when from OBX or OBR not useable, assuming <today>')
			if clin_when is not None:
				current_result['clin_when'] = clin_when
			current_result.save(conn = conn)
			when_list[gmDateTime.pydt_strftime(current_result['clin_when'], '%Y %b %d')] = 1
			previous_segment = seg_type
			continue

		if seg_type == u'NTE':
			note = seg[NET_field__note][0].strip().replace('\.br\\', u'\n')
			if note == u'':
				_log.debug('empty NTE segment')
				previous_segment = seg_type			# maybe not ? (HL7 providers happen to use empty NTE segments to "structure" raw HL7 |-)
				continue

			# if this is an NTE following an OBR (IOW an order-related
			# comment): make this a test result all of its own :-)
			if previous_segment == u'OBR':
				_log.debug('NTE following OBR: general note, using OBR timestamp [%s]', obr['clin_when'])
				current_result = None
				name = obr['name']
				if name == u'':
					name = _('Comment')
				# FIXME: please suggest a LOINC for "order comment"
				test_type = __find_or_create_test_type(name = name, pk_lab = gm_lab['pk_test_org'], abbrev = obr['abbrev'])
				# eventually, episode should be read from lab_request
				epi = emr.add_episode (
					link_obj = conn,
					episode_name = u'administrative',
					is_open = False,
					allow_dupes = False
				)
				nte_result = emr.add_test_result (
					link_obj = conn,
					episode = epi['pk_episode'],
					type = test_type['pk_test_type'],
					intended_reviewer = gmStaff.gmCurrentProvider()['pk_staff'],
					val_alpha = note
				)
				#nte_result['val_grouping'] = seg[OBX_field__subid][0].strip()
				nte_result['source_data'] = unicode(seg)
				try:
					nte_result['clin_when'] = __hl7dt2pydt(obr['clin_when'])
				except ValueError:
					_log.exception('no .clin_when from OBR for NTE pseudo-OBX available')
				nte_result.save(conn = conn)
				continue

			if (previous_segment == u'OBX') and (current_result is not None):
				current_result['source_data'] += u'\n'
				current_result['source_data'] += unicode(seg)
				current_result['note_test_org'] = gmTools.coalesce (
					current_result['note_test_org'],
					note,
					u'%%s\n%s' % note
				)
				current_result.save(conn = conn)
				previous_segment = seg_type
				continue

			_log.error(u'unexpected NTE segment')
			had_errors = True
			break

		_log.error('unknown segment, aborting')
		_log.debug('line: %s', seg)
		had_errors = True
		break

	if had_errors:
		conn.rollback()
		return False

	conn.commit()

	# record import in chart
	try:
		no_results = len(HL7.segments('OBX'))
	except KeyError:
		no_results = u'?'
	soap = _(
		'Imported HL7 file [%s]:\n'
		' lab "%s" (%s@%s), %s results (%s)'
	) % (
		filename,
		hl7_lab,
		gm_lab['unit'],
		gm_lab['organization'],
		no_results,
		u' / '.join(when_list.keys())
	)
	epi = emr.add_episode (
		episode_name = u'administrative',
		is_open = False,
		allow_dupes = False
	)
	emr.add_clin_narrative (
		note = soap,
		soap_cat = None,
		episode = epi
	)

	# keep copy of HL7 data in document archive
	folder = gmPerson.cPatient(emr.pk_patient).document_folder
	hl7_docs = folder.get_documents (
		doc_type = u'HL7 data',
		episodes = [epi['pk_episode']],
		order_by = u'ORDER BY clin_when DESC'
	)
	if len(hl7_docs) > 0:
		# there should only ever be one unless the user manually creates more,
		# also, it should always be the latest since "ORDER BY clin_when DESC"
		hl7_doc = hl7_docs[0]
	else:
		hl7_doc = folder.add_document (
			document_type = u'HL7 data',
			encounter = emr.active_encounter['pk_encounter'],
			episode = epi['pk_episode']
		)
		hl7_doc['comment'] = _('list of imported HL7 data files')
	hl7_doc['clin_when'] = gmDateTime.pydt_now_here()
	hl7_doc.save()
	part = hl7_doc.add_part(file = filename)
	part['obj_comment'] = _('Result dates: %s') % u' / '.join(when_list.keys())
	part.save()
	hl7_doc.set_reviewed(technically_abnormal = False, clinically_relevant = False)

	return True
コード例 #5
0
def __import_single_PID_hl7_file(filename, emr=None):
	"""Assumes single-PID/single-MSH HL7 file."""

	_log.debug('importing single-PID single-MSH HL7 data from [%s]', filename)

	# read the file
	MSH_file = io.open(filename, mode = 'rt', encoding = 'utf8', newline = '')
	HL7 = pyhl7.parse(MSH_file.read(1024 * 1024 * 5))	# 5 MB max
	MSH_file.close()

	# sanity checks
	if len(HL7.segments('MSH')) != 1:
		_log.error('more than one MSH segment')
		return False
	if len(HL7.segments('PID')) != 1:
		_log.error('more than one PID segment')
		return False

	# ensure lab is in database
	hl7_lab = HL7.extract_field('MSH', field_num = MSH_field__sending_lab)
	gm_lab = __find_or_create_lab(hl7_lab)

	# ensure test types exist
	conn = gmPG2.get_connection(readonly = False)
	__ensure_hl7_test_types_exist_in_gnumed(link_obj = conn, hl7_data = HL7, pk_test_org = gm_lab['pk_test_org'])

	# find patient
	if emr is None:
		#PID = HL7.segment('PID')
		pats = __PID2dto(HL7 = HL7)
		if len(pats) == 0:
			conn.rollback()
			return False
		if len(pats) > 1:
			conn.rollback()
			return False
		emr = pats[0].emr

	# import values: loop over segments
	when_list = {}
	current_result = None
	previous_segment = None
	had_errors = False
	msh_seen = False
	pid_seen = False
	last_obr = None
	obr = {}
	for seg_idx in range(len(HL7)):
		seg = HL7[seg_idx]
		seg_type = seg[0][0]

		_log.debug('processing line #%s = segment of type <%s>', seg_idx, seg_type)

		if seg_type == 'MSH':
			msh_seen = True

		if seg_type == 'PID':
			if not msh_seen:
				conn.rollback()
				_log.error('PID segment before MSH segment')
				return False
			pid_seen = True

		if seg_type in ['MSH', 'PID']:
			_log.info('segment already handled')
			previous_segment = seg_type
			obr = {}
			current_result = None
			continue

		if seg_type in ['ORC']:
			_log.info('currently ignoring %s segments', seg_type)
			previous_segment = seg_type
			obr = {}
			current_result = None
			continue

		if seg_type == 'OBR':
			previous_segment = seg_type
			last_obr = seg
			current_result = None
			obr['abbrev'] = ('%s' % seg[OBR_field__service_name][0]).strip()
			try:
				obr['name'] = ('%s' % seg[OBR_field__service_name][1]).strip()
			except IndexError:
				obr['name'] = obr['abbrev']
			for field_name in [OBR_field__ts_ended, OBR_field__ts_started, OBR_field__ts_specimen_received, OBR_field__ts_requested]:
				obr['clin_when'] = seg[field_name][0].strip()
				if obr['clin_when'] != '':
					break
			continue

		if seg_type == 'OBX':
			current_result = None
			# determine value
			val_alpha = seg[OBX_field__value][0].strip()
			is_num, val_num = gmTools.input2decimal(initial = val_alpha)
			if is_num:
				val_alpha = None
			else:
				val_num = None
				val_alpha = val_alpha.replace('\.br\\', '\n')
			# determine test type
			unit = seg[OBX_field__unit][0].strip()
			if unit == '':
				if is_num:
					unit = '1/1'
				else:
					unit = None
			test_type = __find_or_create_test_type (
				loinc = '%s' % seg[OBX_field__type][0][OBX_component__loinc-1],
				name = '%s' % seg[OBX_field__type][0][OBX_component__name-1],
				pk_lab = gm_lab['pk_test_org'],
				unit = unit,
				link_obj = conn
			)
			# eventually, episode should be read from lab_request
			epi = emr.add_episode (
				link_obj = conn,
				episode_name = 'administrative',
				is_open = False,
				allow_dupes = False
			)
			current_result = emr.add_test_result (
				link_obj = conn,
				episode = epi['pk_episode'],
				type = test_type['pk_test_type'],
				intended_reviewer = gmStaff.gmCurrentProvider()['pk_staff'],
				val_num = val_num,
				val_alpha = val_alpha,
				unit = unit
			)
			# handle range information et al
			ref_range = seg[OBX_field__range][0].strip()
			if ref_range != '':
				current_result.reference_range = ref_range
			flag = seg[OBX_field__abnormal_flag][0].strip()
			if flag != '':
				current_result['abnormality_indicator'] = flag
			current_result['status'] = seg[OBX_field__status][0].strip()
			current_result['val_grouping'] = seg[OBX_field__subid][0].strip()
			current_result['source_data'] = ''
			if last_obr is not None:
				current_result['source_data'] += str(last_obr)
				current_result['source_data'] += '\n'
			current_result['source_data'] += str(seg)
			clin_when = seg[OBX_field__timestamp][0].strip()
			if clin_when == '':
				_log.warning('no <Observation timestamp> in OBX, trying OBR timestamp')
				clin_when = obr['clin_when']
			try:
				clin_when = __hl7dt2pydt(clin_when)
			except ValueError:
				_log.exception('clin_when from OBX or OBR not useable, assuming <today>')
			if clin_when is not None:
				current_result['clin_when'] = clin_when
			current_result.save(conn = conn)
			when_list[gmDateTime.pydt_strftime(current_result['clin_when'], '%Y %b %d')] = 1
			previous_segment = seg_type
			continue

		if seg_type == 'NTE':
			note = seg[NET_field__note][0].strip().replace('\.br\\', '\n')
			if note == '':
				_log.debug('empty NTE segment')
				previous_segment = seg_type			# maybe not ? (HL7 providers happen to use empty NTE segments to "structure" raw HL7 |-)
				continue

			# if this is an NTE following an OBR (IOW an order-related
			# comment): make this a test result all of its own :-)
			if previous_segment == 'OBR':
				_log.debug('NTE following OBR: general note, using OBR timestamp [%s]', obr['clin_when'])
				current_result = None
				name = obr['name']
				if name == '':
					name = _('Comment')
				# FIXME: please suggest a LOINC for "order comment"
				test_type = __find_or_create_test_type(name = name, pk_lab = gm_lab['pk_test_org'], abbrev = obr['abbrev'], link_obj = conn)
				# eventually, episode should be read from lab_request
				epi = emr.add_episode (
					link_obj = conn,
					episode_name = 'administrative',
					is_open = False,
					allow_dupes = False
				)
				nte_result = emr.add_test_result (
					link_obj = conn,
					episode = epi['pk_episode'],
					type = test_type['pk_test_type'],
					intended_reviewer = gmStaff.gmCurrentProvider()['pk_staff'],
					val_alpha = note
				)
				#nte_result['val_grouping'] = seg[OBX_field__subid][0].strip()
				nte_result['source_data'] = str(seg)
				try:
					nte_result['clin_when'] = __hl7dt2pydt(obr['clin_when'])
				except ValueError:
					_log.exception('no .clin_when from OBR for NTE pseudo-OBX available')
				nte_result.save(conn = conn)
				continue

			if (previous_segment == 'OBX') and (current_result is not None):
				current_result['source_data'] += '\n'
				current_result['source_data'] += str(seg)
				current_result['note_test_org'] = gmTools.coalesce (
					current_result['note_test_org'],
					note,
					'%%s\n%s' % note
				)
				current_result.save(conn = conn)
				previous_segment = seg_type
				continue

			_log.error('unexpected NTE segment')
			had_errors = True
			break

		_log.error('unknown segment, aborting')
		_log.debug('line: %s', seg)
		had_errors = True
		break

	if had_errors:
		conn.rollback()
		return False

	conn.commit()

	# record import in chart
	try:
		no_results = len(HL7.segments('OBX'))
	except KeyError:
		no_results = '?'
	soap = _(
		'Imported HL7 file [%s]:\n'
		' lab "%s" (%s@%s), %s results (%s)'
	) % (
		filename,
		hl7_lab,
		gm_lab['unit'],
		gm_lab['organization'],
		no_results,
		' / '.join(list(when_list))
	)
	epi = emr.add_episode (
		episode_name = 'administrative',
		is_open = False,
		allow_dupes = False
	)
	emr.add_clin_narrative (
		note = soap,
		soap_cat = None,
		episode = epi
	)

	# keep copy of HL7 data in document archive
	folder = gmPerson.cPatient(emr.pk_patient).document_folder
	hl7_docs = folder.get_documents (
		doc_type = 'HL7 data',
		pk_episodes = [epi['pk_episode']],
		order_by = 'ORDER BY clin_when DESC'
	)
	if len(hl7_docs) > 0:
		# there should only ever be one unless the user manually creates more,
		# also, it should always be the latest since "ORDER BY clin_when DESC"
		hl7_doc = hl7_docs[0]
	else:
		hl7_doc = folder.add_document (
			document_type = 'HL7 data',
			encounter = emr.active_encounter['pk_encounter'],
			episode = epi['pk_episode']
		)
		hl7_doc['comment'] = _('list of imported HL7 data files')
		hl7_doc['pk_org_unit'] = gmPraxis.gmCurrentPraxisBranch()['pk_org_unit']
	hl7_doc['clin_when'] = gmDateTime.pydt_now_here()
	hl7_doc.save()
	part = hl7_doc.add_part(file = filename)
	part['obj_comment'] = _('Result dates: %s') % ' / '.join(list(when_list))
	part.save()
	hl7_doc.set_reviewed(technically_abnormal = False, clinically_relevant = False)

	return True
コード例 #6
0
def create_sql(filename):

    csv_file = open(filename, mode='rt', encoding='utf-8-sig')

    csv_lines = gmTools.unicode_csv_reader(csv_file,
                                           fieldnames=field_names,
                                           delimiter=';',
                                           quotechar='"',
                                           dict=True)

    print SQL_start

    line_idx = 0
    skip_line = False
    for line in csv_lines:
        line_idx += 1
        print "-- line #%s" % line_idx
        # normalize field content
        for field in field_names:
            try:
                line[field] = line[field].strip().strip(';,').strip().replace(
                    "'", "''")
            except AttributeError:  # trailing fields are a list
                pass
        # verify required fields
        for field in non_empty_fields:
            if line[field] == '':
                print "-- ignoring line: empty field [%s]" % field
                print "--", line
                print ""
                skip_line = True
                break
        if skip_line:
            skip_line = False
            continue
        # verify numeric fields
        for field in numeric_fields:
            if line[field] == '':
                continue
            success, num_val = gmTools.input2decimal(initial=line[field])
            if not success:
                print "-- ignoring line: field [%s] not numeric: >>>%s<<<" % (
                    field, line[field])
                print "--", line
                print ""
                skip_line = True
                break
            line[field] = num_val
        if skip_line:
            skip_line = False
            continue

        # actually create SQL
        # loop over strengths
        for field in numeric_fields:
            if line[field] == '':
                continue
            line['brand_name'] = ('%%(product)s %%(%s)s (%%(company)s)' %
                                  field) % line
            line['strength'] = line[field]
            print SQL_stage_drug % line

    print SQL_end
コード例 #7
0
ファイル: gmDrugsFromCSV.py プロジェクト: sk/gnumed
def create_sql(filename):

	csv_file = io.open(filename, mode = 'rt', encoding = u'utf8')

	csv_lines = gmTools.unicode_csv_reader (
		csv_file,
		fieldnames = field_names,
		delimiter = ';',
		quotechar = '"',
		dict = True
	)

	print SQL_start

	line_idx = 0
	skip_line = False
	for line in csv_lines:
		line_idx += 1
		print "-- line #%s" % line_idx
		# normalize field content
		for field in field_names:
			try:
				line[field] = line[field].strip().strip(u';,').strip().replace(u"'", u"''")
			except AttributeError:		# trailing fields are a list
				pass
		# verify required fields
		for field in non_empty_fields:
			if line[field] == u'':
				print "-- ignoring line: empty field [%s]" % field
				print "--", line
				print ""
				skip_line = True
				break
		if skip_line:
			skip_line = False
			continue
		# verify numeric fields
		for field in numeric_fields:
			if line[field] == u'':
				continue
			success, num_val = gmTools.input2decimal(initial = line[field])
			if not success:
				print "-- ignoring line: field [%s] not numeric: >>>%s<<<" % (field, line[field])
				print "--", line
				print ""
				skip_line = True
				break
			line[field] = num_val
		if skip_line:
			skip_line = False
			continue

		# actually create SQL
		# loop over strengths
		for field in numeric_fields:
			if line[field] == u'':
				continue
			line['brand_name'] = (u'%%(brand)s %%(%s)s (%%(company)s)' % field) % line
			line['strength'] = line[field]
			print SQL_stage_drug % line

	print SQL_end