def createTimingResource(self): from fhirclient.models import timing, fhirdate timing_resource = timing.Timing() # once(frequency) per week(period/periodUnit) repeat = timing.TimingRepeat() repeat.frequency = int(self.frequency.value) repeat.periodUnit = self.frequency.unit repeat.period = float(self.frequency.unit_period) # Start Date start_fhirdate = fhirdate.FHIRDate(self.period.start) end_fhirdate = fhirdate.FHIRDate(self.period.end) print(start_fhirdate) print(end_fhirdate) print(fhirdate.FHIRDate(self.period.start)) from fhirclient.models import period fhir_period = period.Period() fhir_period.start = start_fhirdate fhir_period.end = end_fhirdate repeat.boundsPeriod = fhir_period timing_resource.repeat = repeat return timing_resource
def get_responseperiod_x(start,end): responseperiod_x = Ext.Extension() responseperiod_x.url = 'http://fhir.org/guides/argonaut-questionnaire/StructureDefinition/extension-responsePeriod' responseperiod_x.valuePeriod = P.Period() responseperiod_x.valuePeriod.start = FD.FHIRDate(start) responseperiod_x.valuePeriod.end = FD.FHIRDate(end) return responseperiod_x
def to_fhir_obj(self): observation = o.Observation(base_observation) #observation.subject_reference = self.subject_reference observation.subject.reference = self.subject_reference observation.performer[0].reference = self.subject_reference observation.effectiveDateTime = fd.FHIRDate(str(datetime.utcnow().isoformat())) observation.issued = fd.FHIRDate(str(datetime.utcnow().isoformat())) observation.valueString = self.sexual_orientation return observation
def fhir_composition(obj): """ Converts Phenopacket to FHIR Composition. """ composition = comp.Composition() composition.id = obj['id'] composition.subject = fhirreference.FHIRReference() composition.subject.reference = str(obj['subject']['id']) composition.title = PHENOPACKETS_ON_FHIR_MAPPING['phenopacket']['title'] # elements in Composition required by FHIR spec composition.status = 'preliminary' composition.author = [] author = fhirreference.FHIRReference() author.reference = obj['meta_data']['created_by'] composition.author.append(author) composition.date = fhirdate.FHIRDate(obj['meta_data']['created']) composition.type = fhir_codeable_concept({ "id": PHENOPACKETS_ON_FHIR_MAPPING['phenopacket']['code']['code'], "label": PHENOPACKETS_ON_FHIR_MAPPING['phenopacket']['title'], "system": PHENOPACKETS_ON_FHIR_MAPPING['phenopacket']['code']['system'] }) composition.section = [] sections = ['biosamples', 'variants', 'diseases', 'hts_files'] for section in sections: if obj[section]: section_content = _get_section_object(obj.get(section, None), section) composition.section.append(section_content) return composition.as_json()
def patient_list(): start = request.args.get('start', 0) length = request.args.get('length', 100) start = int(start) length = int(length) count = db.engine.execute("select count(*) from T_Patients").scalar() result = db.engine.execute("select * from T_Patients limit %d, %d" % (start, length)) plist = [] total = count for row in result: patient = p.Patient({'id': row['pat_id']}) name = hn.HumanName() name.given = [row['pat_first']] name.family = row['pat_last'] patient.name = [name] address = addr.Address() address.city = row['pat_city'] address.state = row['pat_state'] address.postalCode = row['pat_zip'] address.district = row['pat_address'] patient.address = [address] patient.gender = row['pat_gender'] patient.birthDate = fd.FHIRDate( datetime.strftime(row['pat_birthdate'], "%Y-%m-%d")) # patient.maritalStatus = row['pat_marital'] plist.append(patient.as_json()) return jsonify(results=plist, total=total)
def hts_file_to_fhir(obj): """Converts HTS file to FHIR DocumentReference. :param obj: HTS file json :return: FHIR DocumentReference json """ schema_path = os.path.join(SCHEMA_PATH, 'hts_file_schema.json') try: validate_schema(schema_path, obj) except jsonschema.exceptions.ValidationError: raise Exception("The hts file object is not valid.") doc_ref = documentreference.DocumentReference() doc_ref.type = fhir_codeable_concept({ "label": obj['htsFormat'], "id": obj['htsFormat'] }) # GA4GH requires status with the fixed value doc_ref.status = PHENOPACKETS_ON_FHIR_MAPPING['htsFile']['status'] doc_ref.content = [] doc_content = documentreference.DocumentReferenceContent() doc_content.attachment = attachment.Attachment() doc_content.attachment.url = obj['uri'] if 'description' in obj: doc_content.attachment.title = obj['description'] doc_ref.content.append(doc_content) doc_ref.indexed = fhirdate.FHIRDate() doc_ref.indexed.date = datetime.now() doc_ref.extension = [] genome_assembly = extension.Extension() genome_assembly.url = PHENOPACKETS_ON_FHIR_MAPPING['htsFile'][ 'genomeAssembly'] genome_assembly.valueString = obj['genomeAssembly'] doc_ref.extension.append(genome_assembly) return doc_ref.as_json()
def create_sleep_observations(patient_ref): form_data = repo.generate_patient_sleep_data() for measurement in form_data.items(): # (date, val) date = measurement[0] value = measurement[1] observation = obs.Observation() observation.status = "registered" # <code> ref_patient = fhirref.FHIRReference() ref_patient.reference = "Patient/" + str(patient_ref) observation.subject = ref_patient observation.code = models.codeableconcept.CodeableConcept() code = models.coding.Coding() code.system = "SNOMED CT" code.code = "248263006" code.display = "Sleep Duration" observation.code.coding = [code] quantity = models.quantity.Quantity() quantity.value = value quantity.unit = "h" quantity.system = "http://unitsofmeasure.org" quantity.code = "h" observation.valueQuantity = quantity observation.effectiveDateTime = fhirdate.FHIRDate(date) result = observation.create(smart.server) print(result)
def createobservation(cls, valueString=str, code=None, codesystem=None, codedisplay=None, date=None): from . import fhirutils obs = observation.Observation() # Date fdate = fhirdate.FHIRDate() fdate.date = date or datetime.datetime.utcnow() obs.effectiveDateTime = fdate # Ontology if code is not None and codesystem is not None: obs.code = fhirutils.FHIRUtils.codeableconcept( code, codesystem, codedisplay) # status obs.status = 'final' # Value obs.valueString = valueString or None return obs
def patient(id): # https://{FHIR Base URL}/Patient/{id}? # name={name}& # family={family name}& # gender={gender}& # _format=json # TODO: query params name = request.args.get('name', None) family = request.args.get('family', None) gender = request.args.get('gender', None) # TODO: connect to database to search patient result = db.engine.execute("select * from T_Patients limit 1") names = [] for row in result: patient = p.Patient({'id': row['pat_id']}) name = hn.HumanName() name.given = [row['pat_first']] name.family = row['pat_last'] patient.name = [name] address = addr.Address() address.city = row['pat_city'] address.state = row['pat_state'] address.postalCode = row['pat_zip'] address.district = row['pat_address'] patient.address = [address] patient.gender = row['pat_gender'] patient.birthDate = fd.FHIRDate( datetime.strftime(row['pat_birthdate'], "%Y-%m-%d")) patient.maritalStatus = row['pat_marital'] return jsonify(result=patient.as_json())
def create_QR_for_single_patient(patient_ref, form_data, name): for measurement in form_data.items(): date = measurement[0] categories = measurement[1] qr = qresponse.QuestionnaireResponse() qr.status = "completed" qr.authored = fhirdate.FHIRDate(date) qr.questionnaire = models.fhirreference.FHIRReference() qr.questionnaire.reference = getQuestionnaire(name) ref_patient = fhirref.FHIRReference() ref_patient.reference = patient_ref qr.subject = ref_patient answer_set = [] for i, (key, val) in enumerate(categories.items()): qr_item = qresponse.QuestionnaireResponseItem() qr_item.text = key qr_item.answer = [qresponse.QuestionnaireResponseItemAnswer()] qr_item.answer[0].valueInteger = int(val) qr_item.linkId = str( i) # Should correspond to item from Questionnaire answer_set.append(qr_item) qr.item = answer_set result = qr.create(smart.server) print(result)
def fhir_document_reference(obj): """ Converts HTS file to FHIR DocumentReference. """ doc_ref = documentreference.DocumentReference() doc_ref.type = fhir_codeable_concept({ "label": obj['hts_format'], "id": obj['hts_format'] }) # GA4GH requires status with the fixed value doc_ref.status = PHENOPACKETS_ON_FHIR_MAPPING['hts_file']['status'] doc_ref.content = [] doc_content = documentreference.DocumentReferenceContent() doc_content.attachment = attachment.Attachment() doc_content.attachment.url = obj['uri'] if 'description' in obj.keys(): doc_content.attachment.title = obj.get('description', None) doc_ref.content.append(doc_content) doc_ref.indexed = fhirdate.FHIRDate() # check what date it should be - when it's retrieved or created doc_ref.indexed.date = datetime.now() doc_ref.extension = [] genome_assembly = extension.Extension() genome_assembly.url = PHENOPACKETS_ON_FHIR_MAPPING['hts_file'][ 'genome_assembly'] genome_assembly.valueString = obj['genome_assembly'] doc_ref.extension.append(genome_assembly) return doc_ref.as_json()
def createRequestResource(self, server=FHIRServer, patient=None, practitioner=None, schedule=None): from . import fhirutils if self.instrument is None: print("missin instrument to request") return None # Take instrument or from the argument instr = self.instrument # create new `ServiceRequest` serviceRequest = servicerequest.ServiceRequest() serviceRequest.status = 'active' serviceRequest.intent = 'plan' serviceRequest.category = self.category or [ PRORequest.EvaluationCodeableConcept() ] # Coding Request if instr.code is not None: serviceRequest.code = fhirutils.FHIRUtils.codeableconcept( instr.code, instr.codesystem, instr.title) # Tag Patient if patient is not None: patientreference = fhirreference.FHIRReference() patientreference.reference = f'Patient/{patient.id}' serviceRequest.subject = patientreference # Tag Practitioner if practitioner is not None: practitionerreference = fhirreference.FHIRReference() practitionerreference.reference = f'Practitioner/{practitioner.id}' practitionerreference.display = practitioner.name[0].text serviceRequest.requester = practitionerreference # Schedule if schedule is not None: timing_resource = schedule.createTimingResource() serviceRequest.occurrenceTiming = timing_resource else: now = datetime.datetime.utcnow() fhirDate = fhirdate.FHIRDate() fhirDate.date = now serviceRequest.occurrenceDateTime = fhirDate # Questionnaire Extension if Instrument is a `Questionnaire` if self.is_questionnaire(): extension = PRORequest.QuestionnaireExtension( questionnaire=self.instrument.resource) serviceRequest.extension = [extension] return serviceRequest
def individual_to_fhir(obj): """Converts Individual to FHIR Patient. :param obj: Individual json :return: FHIR Patient json """ # first validate if phenopackets object is well-formed schema_path = os.path.join(SCHEMA_PATH, 'individual_schema.json') try: validate_schema(schema_path, obj) except jsonschema.exceptions.ValidationError: raise Exception("The individual object is not valid.") patient = p.Patient() patient.id = obj['id'] patient.birthDate = fhirdate.FHIRDate(obj.get('dateOfBirth', None)) patient.gender = obj.get('sex', None) patient.active = obj.get('active', None) patient.deceasedBoolean = obj.get('deceased', None) patient.extension = list() # age if 'age' in obj: age_extension = age_to_fhir( obj, PHENOPACKETS_ON_FHIR_MAPPING['individual']['age'], 'age') patient.extension.append(age_extension) # karyotypic_sex if 'karyotypicSex' in obj: karyotypic_sex_extension = extension.Extension() karyotypic_sex_extension.url = PHENOPACKETS_ON_FHIR_MAPPING[ 'individual']['karyotypicSex']['url'] karyotypic_sex_extension.valueCodeableConcept = codeableconcept.CodeableConcept( ) karyotypic_sex_extension.valueCodeableConcept.coding = list() coding = c.Coding() coding.display = obj.get('karyotypicSex', None) coding.code = obj.get('karyotypicSex', None) coding.system = PHENOPACKETS_ON_FHIR_MAPPING['individual'][ 'karyotypicSex']['system'] karyotypic_sex_extension.valueCodeableConcept.coding.append(coding) patient.extension.append(karyotypic_sex_extension) # taxonomy if 'taxonomy' in obj: taxonomy_extension = extension.Extension() taxonomy_extension.url = PHENOPACKETS_ON_FHIR_MAPPING['individual'][ 'taxonomy'] taxonomy_extension.valueCodeableConcept = codeableconcept.CodeableConcept( ) taxonomy_extension.valueCodeableConcept.coding = list() coding = c.Coding() coding.display = obj.get('taxonomy', None).get('label', None) coding.code = obj.get('taxonomy', None).get('id', None) taxonomy_extension.valueCodeableConcept.coding.append(coding) patient.extension.append(taxonomy_extension) return patient.as_json()
def _create_FHIRDate(date): """ Creates a FHIRDate object :param date: datetime object used to set the date in the FHIRDate object :returns: FHIRDate object """ eastern = timezone('US/Eastern') FHIRDate = fd.FHIRDate() FHIRDate.date = date.astimezone(eastern) return FHIRDate
def fhir_gen_datetime(value=None, to_date=False, error_out=False): """ :return: fhirclient.models.fhirdate.FHIRDate class object if it can be constructed If invalid datetime string is passed, DatetimeParseError is raised if error_out=True """ dt = validate_datetime(value=value, to_date=to_date, error_out=error_out) fhir_date_obj = fhirdate.FHIRDate() if dt: fhir_date_obj.date = dt return fhir_date_obj fhir_date_obj.date = None return fhir_date_obj
def init_aqr(q): aqr = QR.QuestionnaireResponse(f.aqr_templ(q.url), strict=False) # resets aqr and contained q aqr.questionnaire = Ref.FHIRReference( {'reference': '#contained-adaptive-{}'.format(q.id)}) # update the questionnaire aqr.id = q.url.rsplit('/')[-1].replace( 'questionnaire', 'adaptive-questionnaireresponse') # update the QR id dt = '{}Z'.format(datetime.utcnow().isoformat()) # start time... aqr.authored = FD.FHIRDate(dt) # update datetime # application.logger.info(json.dumps(qr.as_json(), indent=4, sort_keys=True)) # ---create narrative only answered and static questions --- logging.info(aqr) # get_next_q(q, aqr) return (aqr)
def phenopacket_to_fhir(obj): """Converts Phenopacket to FHIR Composition. :param obj: Phenopacket json :return: FHIR Composition json """ schema_path = os.path.join(SCHEMA_PATH, 'phenopacket_schema.json') try: validate_schema(schema_path, obj) except jsonschema.exceptions.ValidationError: raise Exception("The phenopacket object is not valid.") composition = comp.Composition() if 'id' in obj: composition.id = obj['id'] composition.subject = fhirreference.FHIRReference() if 'subject' in obj: composition.subject.reference = str(obj['subject']['id']) composition.title = PHENOPACKETS_ON_FHIR_MAPPING['phenopacket']['title'] # elements in Composition required by FHIR spec composition.status = 'preliminary' composition.author = [] author = fhirreference.FHIRReference() author.reference = obj['metaData']['createdBy'] composition.author.append(author) composition.date = fhirdate.FHIRDate(obj['metaData']['created']) composition.type = fhir_codeable_concept({ "id": PHENOPACKETS_ON_FHIR_MAPPING['phenopacket']['code']['code'], "label": PHENOPACKETS_ON_FHIR_MAPPING['phenopacket']['title'], "system": PHENOPACKETS_ON_FHIR_MAPPING['phenopacket']['code']['system'] }) composition.section = [] # TODO add htsFiles to the list and fix inconsistency in mappings sections = ['biosamples', 'variants', 'diseases'] for section in sections: if obj[section]: section_content = _get_section_object(obj.get(section, None), section) composition.section.append(section_content) return composition.as_json()
def to_fhir_obj(self): patient = p.Patient() identifier = p.identifier.Identifier() identifier.value = self.id patient.identifier = [identifier] name = hn.HumanName() name.given = [self.first_name] name.family = self.last_name patient.name = [name] patient.gender = self.sex patient.birthDate = fd.FHIRDate(str(datetime.utcnow().date())) # prints patient's JSON representation, now with id and name address = a.Address() address.state = self.state address.district = self.district patient.address = [address] json = patient.as_json() return patient
def initalize_report(self): patient_reference = reference.FHIRReference( {"reference": "Patient/" + self.patientID}) self.report.id = "dr-" + uuid4().hex[:13] self.report.meta = meta.Meta({ "profile": [("http://hl7.org/fhir/uv/genomics-reporting" + "/StructureDefinition/genomics-report")] }) self.report.status = "final" self.report.code = concept.CodeableConcept({ "coding": [{ "system": "http://loinc.org", "code": "81247-9", "display": "Master HL7 genetic variant reporting panel" }] }) self.report.subject = patient_reference self.report.issued = date.FHIRDate(get_fhir_date()) self.report.contained = []
def fhir_patient(obj): """ Converts Individual to FHIR Patient. """ patient = p.Patient() patient.id = obj['id'] patient.birthDate = fhirdate.FHIRDate(obj.get('date_of_birth', None)) patient.gender = obj.get('sex', None) patient.active = obj.get('active', None) patient.deceasedBoolean = obj.get('deceased', None) patient.extension = list() # age if 'age' in obj.keys(): age_extension = fhir_age( obj, PHENOPACKETS_ON_FHIR_MAPPING['individual']['age'], 'age') patient.extension.append(age_extension) # karyotypic_sex karyotypic_sex_extension = extension.Extension() karyotypic_sex_extension.url = PHENOPACKETS_ON_FHIR_MAPPING['individual'][ 'karyotypic_sex']['url'] karyotypic_sex_extension.valueCodeableConcept = codeableconcept.CodeableConcept( ) karyotypic_sex_extension.valueCodeableConcept.coding = list() coding = c.Coding() coding.display = obj.get('karyotypic_sex', None) coding.code = obj.get('karyotypic_sex', None) coding.system = PHENOPACKETS_ON_FHIR_MAPPING['individual'][ 'karyotypic_sex']['system'] karyotypic_sex_extension.valueCodeableConcept.coding.append(coding) patient.extension.append(karyotypic_sex_extension) # taxonomy if 'taxonomy' in obj.keys(): taxonomy_extension = extension.Extension() taxonomy_extension.url = PHENOPACKETS_ON_FHIR_MAPPING['individual'][ 'taxonomy'] taxonomy_extension.valueCodeableConcept = codeableconcept.CodeableConcept( ) taxonomy_extension.valueCodeableConcept.coding = list() coding = c.Coding() coding.display = obj.get('taxonomy', None).get('label', None) coding.code = obj.get('taxonomy', None).get('id', None) taxonomy_extension.valueCodeableConcept.coding.append(coding) patient.extension.append(taxonomy_extension) return patient.as_json()
def qr_view(): working_q = '{}_wq'.format(session['form_url']) qr_working_q = cache.get(working_q) reset_q_cache() # results = request.form # this is multiDict structure - can only retreive the first element or use the get list method application.logger.info('results = {}'.format(request.form)) # bp() # ***************** this is a break****************** # split out linkId and text to create answers create a QR resource use a template for the meta for now qr = QR.QuestionnaireResponse(f.qr_templ, strict=False) qr.questionnaire = Ref.FHIRReference({'reference': qr_working_q.url}) # update the questionnaire qr.id = qr_working_q.url.rsplit('/')[-1].replace('questionnaire', 'questionnaireresponse') # update the QR id dt = '{}Z'.format(datetime.utcnow().isoformat()) # == stop time qr.extension = [get_responseperiod_x(session['q_starttime'],dt)] # add extension for FHIRDates start and stoptime qr.authored = FD.FHIRDate(dt) # update datetime # application.logger.info(json.dumps(qr.as_json(), indent=4, sort_keys=True)) qr.item = [] get_qr_items(request.form, qr_working_q.item, qr.item) #application.logger.info(json.dumps(qr.as_json(), indent=4, sort_keys=True)) # ---create narrative--- qr.text.div = '''<div xmlns=\"http://www.w3.org/1999/xhtml\"> <h3>Response Summary</h3> <strong>Questionnaire URL:</strong> {q}<br /> <strong>Date Completed:</strong> {d}<br /> <hr /> {r} <br /><br /> </div>'''.format(q=qr.questionnaire.reference, d=qr.authored.as_json(), r=''.join(session['narr_list'])) #scrub id for user POST and save as session qr qr.identifier.value = qr.id session['qr_id'] = qr.id # this is for saving my examples session['profile'] = qr.meta.profile[0] # this is for uploads if validate by profile # qr.id = None # TODO comment out for user posting to server set_cache(qr.identifier.value, json.dumps(qr.as_json(),indent = 3, sort_keys=True)) # bp() # ***************** this is a break****************** return render_template('qr_view.html', qr=qr, qr_string=cache.get(qr.identifier.value), adaptive=False )
def write(server_url, system, code, patient, value): observation = o.Observation() observation.status = "final" observation.subject = fr.FHIRReference() observation.subject.reference = ("Patient/%s" % patient) observation.code = cc.CodeableConcept() tmp = c.Coding() tmp.system = system tmp.code = code observation.code.coding = [tmp] observation.valueString = str(value) observation.effectiveDateTime = fd.FHIRDate("2017-11-28T00:00:00+00:00") #write json obj json_obj = observation.as_json() json_obj["resourceType"] = "Observation" print(json.dumps(json_obj)) requests.post(server_url + "Observation", json=json_obj)
def get_next_q(q, aqr, score=0): # assuming no nesting cq = aqr.contained[0] if cq.item is None: # create first response cq.item = [] # use first item get_hidden_score(cq.item) # add score as item 0 # add score as item 0 get_hidden_stddev(cq.item) # add stddev as item 1 q_item = get_q_items(q.item)[0] q_item.definition = '{}-{}'.format(q.url, q_item.linkId) # logging.info(q_item.prefix) cq.item.append(q_item) # use first question get_itemorder(cq.item[2], 3) cq.copyright = q.copyright dt = '{}Z'.format(datetime.utcnow().isoformat()) cq.date = FD.FHIRDate(dt) cq.id = 'contained-adaptive-{}'.format(q.id) cq.extension = q.extension #cq.title = 'Contained Adaptive {}'.format(q.title) #cq.url = q.url cq = aqr.contained[0] aqr.text.div = intro.format(t=cq.title, c=cq.copyright, q=cq.url, d=cq.date.as_json()) # render intro elif len(cq.item) < 5: # check number of q is < 5 add a new q logging.info('cq.item = {}'.format(cq.item)) check_list = [x.linkId for x in cq.item] logging.info('check_list = {}'.format(check_list)) next_cq_item = get_next_q_item(q.url, q.item, check_list) logging.info('next_cq_item = {}'.format(next_cq_item)) get_itemorder(next_cq_item, len(cq.item) + 1) cq.item.append(next_cq_item) else: # done change the status of the QR to complete and add score as a hidden # QUESTION: aqr.status = 'completed' return (aqr)
def addObservationToServer(self, patient_id, value_code, value_unit, value_quantity, coding_code, coding_display, coding_system, timestamp): observation = o.Observation() # Create Value Quantity quantity = q.Quantity() quantity.code = value_code quantity.unit = value_unit quantity.value = value_quantity observation.valueQuantity = quantity # Create Coding code = cc.CodeableConcept() coding_item = c.Coding() coding_item.code = coding_code coding_item.display = coding_display coding_item.system = coding_system coding_list = [coding_item] code.coding = coding_list observation.code = code # Create Subject reference = r.FHIRReference() reference.reference = self.getPatientById(patient_id).relativePath() observation.subject = reference # Create Status observation.status = 'final' # Create Issued/EffectiveDateTime observation.effectiveDateTime = d.FHIRDate(timestamp) # Write the observation result_json = observation.create(self.smart.server) observation.id = self.getCreatedId(result_json) return observation.id
def writeMedProfile(meds_medication, meds_frequencyPerYear, meds_fractionOfSubjects, meds_correlatedLabsCoefficients, meds_correlatedMedsCoefficients, meds_correlatedProceduresCoefficients, meds_correlatedDiagnosisCoefficients, meds_correlatedPhenotypesCoefficients, cohort='All', sex='All', race='All', age_low='All', age_high=None, topN=10, correlationCutoff=0.3): """Write out Medication Clinical Profile to JSON File and save locally Keywords: Structures from output of calculateAnyProfile(profileType='medications') cohort -- short name for cohort, special characters besides hyphens are prohibited (default 'All') sex -- specification of whether this is a 'All', 'Male', or 'Female' sex profile (default 'All') race -- specification of whether this is 'All', 'White or Caucasian', 'Black or African American', 'Other' race profile (default 'All') age_low -- low age range for this profile (default 'All') age_high -- high age range for this profile (default None) topN -- integer representing the maximum number of correlations to report in the profile, ranked descending (default 10) correlationCutoff -- minimum correlation coefficient value to report for whole profile (default 0.3) """ import os import sys import sqlalchemy import urllib.parse import pandas as pd import numpy as np import getpass from dataclasses import dataclass from SciServer import Authentication from fhirclient.models import clinicalprofile, fhirreference, identifier, codeableconcept, fhirdate, quantity from datetime import datetime import json from fhir_loader import fhir_loader import pymssql # Initialize profile clinicalProfile = clinicalprofile.ClinicalProfile() if sex == 'M': sex = 'Male' elif sex == 'F': sex = 'Female' # Header info if (age_low != 'All'): clinicalProfile.id = ('jh-medications-' + cohort + '-' + sex + '-' + race + '-' + str(int(age_low)) + '-' + str(int(age_high))) clinicalProfile.identifier = [ identifier.Identifier({ 'value': ('jh-medications-' + cohort + '-' + sex + '-' + race + '-' + str(int(age_low)) + '-' + str(int(age_high))) }) ] clinicalProfile.cohort = fhirreference.FHIRReference({ 'reference': ('Group/jh-medications-' + cohort + '-' + sex + '-' + race + '-' + str(int(age_low)) + '-' + str(int(age_high))) }) else: clinicalProfile.id = 'jh-medications-' + cohort + '-' + sex + '-' + race + '-' + str( age_low) clinicalProfile.identifier = [ identifier.Identifier({ 'value': 'jh-medications-' + cohort + '-' + sex + '-' + race + '-' + str(age_low) }) ] clinicalProfile.cohort = fhirreference.FHIRReference({ 'reference': ('Group/jh-medications-' + cohort + '-' + sex + '-' + race + '-' + str(age_low)) }) clinicalProfile.status = 'draft' clinicalProfile.population = fhirreference.FHIRReference( {'reference': 'Group/jh-medications-' + cohort}) clinicalProfile.date = fhirdate.FHIRDate( str(datetime.now()).replace(' ', 'T')) clinicalProfile.reporter = fhirreference.FHIRReference({ 'reference': 'Organization/JHM', 'type': 'Organization', 'display': 'Johns Hopkins School of Medicine' }) meds = list() meds_medication = [x for x in meds_medication if str(x) != 'nan'] for thisMed in meds_medication: thisCPMed = clinicalprofile.ClinicalProfileMedication() try: thisCPMed.medicationCodeableConcept = codeableconcept.CodeableConcept( dict(coding=[ dict(system='http://www.nlm.nih.gov/research/umls/rxnorm/', code=str(thisMed)) ])) # meds_dosageInfo # thisCPMed.dose = quantity.Quantity(dict(unit=str(meds_dosageInfo.loc[thisMed]))) thisCPMed.frequencyPerYear = round( float(meds_frequencyPerYear.loc[thisMed].mean()), 3) thisCPMed.fractionOfSubjects = round( float(meds_fractionOfSubjects.loc[thisMed].mean()), 3) try: topNcorrs = (pd.DataFrame( meds_correlatedLabsCoefficients.loc[thisMed].groupby([ 'LAB_LOINC' ]).Relative_Counts.mean()).Relative_Counts.nlargest( topN).round(3)) entries = list() for code, corr in topNcorrs.iteritems(): if corr <= correlationCutoff: continue otherLab = [(dict( coding=[dict(system='http://loinc.org', code=code)]))] entries.append(dict(labcode=otherLab, coefficient=corr)) if not entries: print('No correlated Labs for Med ', thisMed) else: thisCPMed.correlatedLabs = clinicalprofile.\ ClinicalProfileLabScalarDistributionCorrelatedLabs(dict(topn=topN, entry=entries)) except: print('No correlated Labs for Med ', thisMed) try: topNcorrs = (pd.DataFrame( meds_correlatedDiagnosisCoefficients.loc[thisMed].groupby([ 'DX' ]).Relative_Counts.mean()).Relative_Counts.nlargest( topN).round(3)) entries = list() for code, corr in topNcorrs.iteritems(): if corr <= correlationCutoff: continue otherDX = (dict(coding=[ dict(system='http://www.icd10data.com/', code=code) ])) entries.append(dict(code=otherDX, coefficient=corr)) if not entries: print('No correlated Diagnoses for Med ', thisMed) else: thisCPMed.correlatedDiagnoses = clinicalprofile.ClinicalProfileLabScalarDistributionCorrelatedDiagnoses( dict(topn=topN, entry=entries)) except: print('No correlated DX for Med ', thisMed) try: topNcorrs = (pd.DataFrame( meds_correlatedProceduresCoefficients.loc[thisMed].groupby( ['RAW_PX' ]).Relative_Counts.mean()).Relative_Counts.nlargest( topN).round(3)) entries = list() for code, corr in topNcorrs.iteritems(): if corr <= correlationCutoff: continue otherProc = [(dict(coding=[ dict(system= 'http://www.ama-assn.org/practice-management/cpt', code=code) ]))] entries.append(dict(code=otherProc, coefficient=corr)) if not entries: print('No correlated Procedures for Med ', thisMed) else: thisCPMed.correlatedProcedures = clinicalprofile.ClinicalProfileLabScalarDistributionCorrelatedProcedures( dict(topn=topN, entry=entries)) except: print('No correlated Procedures for Med ', thisMed) try: topNcorrs = (pd.DataFrame( meds_correlatedMedsCoefficients.loc[thisMed].groupby([ 'JH_INGREDIENT_RXNORM_CODE' ]).Relative_Counts.mean()).Relative_Counts.nlargest( topN).round(3)) entries = list() for code, corr in topNcorrs.iteritems(): if corr <= correlationCutoff: continue otherMed = [ dict(medicationCodeableConcept=dict(coding=[ dict( system= 'http://www.nlm.nih.gov/research/umls/rxnorm/', code=code) ])) ] entries.append(dict(meds=otherMed, coefficient=corr)) if not entries: print('No correlated Meds for Med ', thisMed) else: thisCPMed.correlatedMedications = clinicalprofile.ClinicalProfileLabScalarDistributionCorrelatedMedications( dict(topn=topN, entry=entries)) except: print('No correlated Meds for Med ', thisMed) try: topNcorrs = (pd.DataFrame( meds_correlatedPhenotypesCoefficients.loc[thisMed].groupby( ['HPO' ]).Relative_Counts.mean()).Relative_Counts.nlargest( topN).round(3)) entries = list() for code, corr in topNcorrs.iteritems(): if corr <= correlationCutoff: continue otherHPO = (dict(coding=[ dict(system='http://hpo.jax.org/app/', code=code) ])) entries.append(dict(code=otherHPO, coefficient=corr)) if not entries: print('No correlated Phenotypes for Med ', thisMed) else: thisCPMed.correlatedPhenotypes = clinicalprofile.ClinicalProfileLabScalarDistributionCorrelatedPhenotypes( dict(topn=topN, entry=entries)) except: print('No correlated Phenotypes for Med ', thisMed) meds.append(thisCPMed) except Exception as e: print(e) print('This med did not work ', thisMed) clinicalProfile.medication = meds if age_high != None: filename = cohort + '_resources/jh-medications-' + cohort + '-' + sex + '-' + race + '-' + str( int(age_low)) + '-' + str(int(age_high)) + '.json' else: filename = cohort + '_resources/jh-medications-' + cohort + '-' + sex + '-' + race + '-' + str( age_low) + '.json' with open(filename, 'w') as outfile: json.dump(clinicalProfile.as_json(), outfile, indent=4) del (clinicalProfile) return print('Write to ' + filename + ' successful')
# 3 records, modify if more are required limit = 100 for index, row in itertools.islice(df_a.iterrows(), limit): # for index, row in df_a.iterrows(): patient = p.Patient() # not using rec_id as pandas id, leaving empty patient.gender = row['sex'] name = hn.HumanName() name.given = [row['given_name']] name.family = row['surname'] name.use = 'official' patient.name = [name] phone = cp.ContactPoint() phone.system = 'phone' phone.value = row['phone_number'] patient.telecom = [phone] patient.birthDate = fd.FHIRDate(row['date_of_birth']) emr = ident.Identifier() emr.system = 'http://clientregistry.org/openmrs' emr.value = row['rec_id'] art = ident.Identifier() art.system = 'http://system1/artnumber' art.value = row['art_number'] nin = ident.Identifier() nin.system = 'http://system1/nationalid' nin.value = row['uganda_nin'] patient.identifier = [emr, art, nin] # print(json.dumps(patient.as_json())) headers = {'Content-Type': 'application/json'} start = time.time() response = post(server,
def getEmptyFhirJSON(patientID, start, end, refSeq, nocall=False): logging.info("[FHIR: Converting XML to JSON]") noCallRegion, queryRange = getNoCallableData(NO_CALL_FILE, QUERY_RANGE_FILE) nocallRows = len(noCallRegion.index) start = queryRange.at[0, "START"] end = queryRange.at[0, "END"] if not noCallRegion.empty: if noCallRegion['START'].iloc[0] <= queryRange['START'].iloc[0]: noCallRegion['START'].iloc[0] = queryRange['START'].iloc[0] if noCallRegion['END'].iloc[-1] >= queryRange['END'].iloc[0]: noCallRegion['END'].iloc[-1] = queryRange['END'].iloc[0] else: nocall = False contained_uid = uuid4().hex[:13] patient_reference = reference.FHIRReference( {"reference": "Patient/" + patientID}) variant_reference = reference.FHIRReference( {"reference": "#rs-" + contained_uid}) report = dr.DiagnosticReport() report.id = "dr-" + uuid4().hex[:13] report.meta = meta.Meta({ "profile": [ "http://hl7.org/fhir/uv/genomics-reporting/StructureDefinition/diagnosticreport" ] }) report.code = concept.CodeableConcept({ "coding": [{ "system": "http://loinc.org", "code": "53041-0", "display": "DNA region of interest panel" }] }) report.status = "final" report.subject = patient_reference report.issued = date.FHIRDate(Utilities.getFhirDate()) report.result = [variant_reference] observation_rs = observation.Observation() contained_rs = observation_rs observation_dv = observation.Observation() contained_dv = observation_dv observation_sid = observation.Observation() contained_sid = observation_sid contained_rs.id = "rs-" + contained_uid observation_rs.resource_type = "Observation" contained_rs.meta = meta.Meta({ "profile": [ "http://hl7.org/fhir/uv/genomics-reporting/StructureDefinition/obs-region-studied" ] }) observation_rs.code = concept.CodeableConcept({ "coding": [{ "system": "http://loinc.org", "code": "53041-0", "display": "DNA region of interest panel" }] }) observation_rs.status = "final" observation_rs.category = [ concept.CodeableConcept({ "coding": [{ "system": "http://terminology.hl7.org/CodeSystem/observation-category", "code": "laboratory" }] }) ] observation_rs.subject = patient_reference observation_rs_component1 = observation.ObservationComponent() observation_rs_component1.code = concept.CodeableConcept({ "coding": [{ "system": "http://loinc.org", "code": "51959-5", "display": "Range(s) of DNA sequence examined" }] }) observation_rs_component1.valueRange = valRange.Range({ "low": { "value": int(start) }, "high": { "value": int(end) } }) observation_rs_component2 = observation.ObservationComponent() observation_rs_component2.code = concept.CodeableConcept({ "coding": [{ "system": "http://loinc.org", "code": "tbd-coordinate system", "display": "Genomic coordinate system" }] }) observation_rs_component2.valueCodeableConcept = concept.CodeableConcept({ "coding": [{ "system": "http://hl7.org/fhir/uv/genomics-reporting/CodeSystem/genetic-coordinate-system", "code": "1" }] }) observation_rs_component3 = observation.ObservationComponent() observation_rs_component3.code = concept.CodeableConcept({ "coding": [{ "system": "http://loinc.org", "code": "48013-7", "display": "Genomic reference sequence ID" }] }) observation_rs_component3.valueCodeableConcept = concept.CodeableConcept({ "coding": [{ "system": "http://www.ncbi.nlm.nih.gov/nuccore", "code": refSeq }] }) if nocall: #component Region-studied (No call region) nocallComponents = [] for i in range(nocallRows): nocallComponents.append('observation_rs_component' + str(i + 4)) observation_rs_components = [] for (index, i) in zip(noCallRegion.index, nocallComponents): i = observation.ObservationComponent() i.code = concept.CodeableConcept({ "coding": [{ "system": "http://loinc.org", "code": "TBD-noCallRegion", "display": "No call region" }] }) observation_rs_components.append(i) if nocall: observation_rs.component = [ observation_rs_component2, observation_rs_component3 ] + observation_rs_components else: observation_rs.component = [ observation_rs_component2, observation_rs_component3 ] response = report.as_json() od = OrderedDict() od["resourceType"] = response['resourceType'] od["id"] = response['id'] od["meta"] = response['meta'] od["contained"] = response['contained'] od["status"] = response['status'] od["code"] = response['code'] od["subject"] = response['subject'] od["issued"] = response['issued'] od["result"] = response['result'] with open(FHIR_JSON_RESULT + 'fhir.json', 'w') as fp: json.dump(od, fp, indent=4) return FHIR_JSON_RESULT
def effective_date_time(self): return fd.FHIRDate(str(datetime.now()))
def create_fhir_object(self): """ method: create_fhir_object() Create a fhir-client.model.address.Adress object and stores to the self.fhir attribute :return: None """ # Initialize FHIRclient Address object # Assign Address object attributes to FHIRclient Address object fa = fhir_address.Address() if self.address1: fa.line = [self.address1] if self.address2: fa.line.append(self.address2) if self.city: fa.city = self.city if self.state: fa.state = self.state if self.zipcode: fa.postalCode = self.zipcode fa.text = self.formatted_address() if isinstance(self.start_date, date) or isinstance(self.end_date, date): p = period.Period() if self.start_date: fhirdate_start = fhirdate.FHIRDate() fhirdate_start.date = self.start_date p.start = fhirdate_start if self.end_date: fhirdate_end = fhirdate.FHIRDate() fhirdate_end.date = self.end_date p.end = fhirdate_end fa.period = p if self.use: fa.use = self.use.lower() if self.is_postal and self.is_physical: fa.type = 'both' elif self.is_postal: fa.type = 'postal' elif self.is_physical: fa.type = 'physical' if self.district: fa.district = self.district if self.country: fa.country = self.country self.fhir = fa
def writeLabProfile(labs_counts, labs_frequencyPerYear, labs_fractionOfSubjects,labs_units, labs_names, labs_stats, labs_aboveBelowNorm, labs_correlatedLabsCoefficients, labs_abscorrelation, labs_correlatedMedsCoefficients, labs_correlatedProceduresCoefficients, labs_correlatedDiagnosisCoefficients, labs_correlatedPhenotypesCoefficients, cohort='All', sex='All', race='All', age_low='All', age_high=None, topN=10, correlationCutoff=0.3): """Write out Lab Clinical Profile to JSON File and save locally Keywords: Structures from output of calculateAnyProfile(profileType='labs') cohort -- short name for cohort, special characters besides hyphens are prohibited (default 'All') sex -- specification of whether this is a 'All', 'Male', or 'Female' sex profile (default 'All') race -- specification of whether this is 'All', 'White or Caucasian', 'Black or African American', 'Other' race profile (default 'All') age_low -- low age range for this profile (default 'All') age_high -- high age range for this profile (default None) topN -- integer representing the maximum number of correlations to report in the profile, ranked descending (default 10) correlationCutoff -- minimum correlation coefficient value to report for whole profile (default 0.3) """ import os import sys import sqlalchemy import urllib.parse import pandas as pd import numpy as np import getpass from dataclasses import dataclass from SciServer import Authentication from datetime import datetime import json from fhir_loader import fhir_loader from fhirclient.models import clinicalprofile, fhirreference, identifier, codeableconcept, fhirdate, quantity import pymssql # Initialize profile clinicalProfile = clinicalprofile.ClinicalProfile() clinicalProfile.resourceType = 'ClinicalProfile' if sex == 'M': sex = 'Male' elif sex =='F': sex = 'Female' # Header info if (age_low != 'All'): clinicalProfile.id = 'jh-labs-'+cohort+'-'+sex+'-'+race+'-'+str(int(age_low))+'-'+str(int(age_high)) clinicalProfile.identifier = [identifier.Identifier({'value': 'jh-labs-'+cohort+'-'+sex+'-'+race+'-'+ str(int(age_low))+'-'+str(int(age_high))})] clinicalProfile.cohort = fhirreference.FHIRReference({'reference': 'Group/jh-labs-'+cohort+'-'+sex+'-'+race+'-'+str(int(age_low)) +'-'+str(int(age_high))}) else: clinicalProfile.id = 'jh-labs-'+cohort+'-'+sex+'-'+race+'-'+str(age_low) clinicalProfile.identifier = [identifier.Identifier({'value': 'jh-labs-'+cohort+'-'+sex+'-'+race+'-'+str(age_low)})] clinicalProfile.cohort = fhirreference.FHIRReference({'reference': 'Group/jh-labs-'+cohort+'-'+sex+'-'+race+'-'+str(age_low)}) clinicalProfile.status = 'draft' clinicalProfile.population = fhirreference.FHIRReference({'reference': 'Group/jh-labs-'+cohort}) clinicalProfile.date = fhirdate.FHIRDate(str(datetime.now()).replace(' ', 'T')) clinicalProfile.reporter = fhirreference.FHIRReference({'reference': 'Organization/JHM', 'type': 'Organization', 'display': 'Johns Hopkins School of Medicine'}) ## LABS labs = list() corrmat = (pd.DataFrame(labs_correlatedLabsCoefficients).unstack(level=[0,1]).corr(min_periods=50) .droplevel(level=0).droplevel(level=0,axis=1)) lab_names = pd.DataFrame({'lab_name':labs_names}).reset_index() lab_counts = pd.DataFrame({'lab_counts':labs_counts}).reset_index().rename({'index':'LAB_LOINC'},axis=1) lab_info = lab_names.merge(lab_counts, how='inner', on='LAB_LOINC').set_index('LAB_LOINC') for thisLab in lab_info.index: # Check if STDEV is NaN and skip that lab if so if np.isnan(float(labs_stats.loc[thisLab]['std'].median())): continue # Build the profile thisCPLab = clinicalprofile.ClinicalProfileLab() # try: thisCPLab.code = [codeableconcept.CodeableConcept(dict(coding=[dict(system='http://loinc.org', code=thisLab)], text=lab_info.loc[thisLab]['lab_name'][0]))] thisCPLab.count = int(lab_info.loc[thisLab]['lab_counts']) thisCPLab.frequencyPerYear = round(float(labs_frequencyPerYear.loc[thisLab].mean()),3) thisCPLab.fractionOfSubjects = round(float(labs_fractionOfSubjects.loc[thisLab].mean()),3) thisCPLab.scalarDistribution = clinicalprofile.ClinicalProfileLabScalarDistribution() thisCPLab.scalarDistribution.units = quantity.Quantity(dict(unit=str(labs_units.loc[thisLab][0]))) thisCPLab.scalarDistribution.min = round(float(labs_stats.loc[thisLab]['min'].min()),3) thisCPLab.scalarDistribution.max = round(float(labs_stats.loc[thisLab]['max'].max()),3) thisCPLab.scalarDistribution.mean = round(float(labs_stats.loc[thisLab]['mean'].mean()),3) thisCPLab.scalarDistribution.median = round(float(labs_stats.loc[thisLab]['median'].median()),3) thisCPLab.scalarDistribution.stdDev = round(float(labs_stats.loc[thisLab]['std'].median()),3) deciles = list() for dec in labs_stats.columns[5:]: deciles.append(clinicalprofile.ClinicalProfileLabScalarDistributionDecile( dict(nth=int(dec), value=round(labs_stats.loc[thisLab][dec].mean(),3)))) thisCPLab.scalarDistribution.decile = deciles thisCPLab.scalarDistribution.fractionAboveNormal = round(float(labs_aboveBelowNorm.loc[thisLab].aboveNorm.mean()),3) thisCPLab.scalarDistribution.fractionBelowNormal = round(float(labs_aboveBelowNorm.loc[thisLab].belowNorm.mean()),3) try: yearly_vals = dict() for year in corrmat.loc[thisLab].index: crosstab = corrmat.loc[(thisLab, year)] yearly_vals[year] = (crosstab[crosstab.index.get_level_values(level=1).astype('float') == year] .droplevel(level=1)) topNcorrs = pd.DataFrame(yearly_vals).apply(np.mean, axis=1).drop(thisLab).nlargest(topN).round(3) entries = list() for code, corr in topNcorrs.iteritems(): if corr <= correlationCutoff: continue otherLoinc = [(dict(coding=[dict(system='http://loinc.org', code=code)], text=str(lab_info.loc[code]['lab_name'][0])))] entries.append(dict(labcode=otherLoinc, coefficient=corr)) if not entries: print('No correlated Labs for Lab ', thisLab) else: thisCPLab.scalarDistribution.correlatedLabs = clinicalprofile.ClinicalProfileLabScalarDistributionCorrelatedLabs( dict(topn=topN, entry=entries)) except: print('No correlated Labs for Lab ', thisLab) try: topNcorrs = (pd.DataFrame(labs_correlatedMedsCoefficients.loc[thisLab].groupby(['JH_INGREDIENT_RXNORM_CODE']) .Relative_Counts.mean()) .Relative_Counts.nlargest(topN).round(3)) entries = list() for code, corr in topNcorrs.iteritems(): if corr <= correlationCutoff: continue otherRX = [dict(medicationCodeableConcept=dict(coding= [dict(system='http://www.nlm.nih.gov/research/umls/rxnorm/', code=code)]))] entries.append(dict(meds=otherRX, coefficient=corr)) if not entries: print('No correlated Meds for Lab ', thisLab) else: thisCPLab.scalarDistribution.correlatedMedications = clinicalprofile.\ ClinicalProfileLabScalarDistributionCorrelatedMedications( dict(topn=topN, entry=entries)) except: print('No correlated Meds for Lab ', thisLab) try: topNcorrs = (pd.DataFrame(labs_correlatedDiagnosisCoefficients.loc[thisLab].groupby(['DX']) .Relative_Counts.mean()) .Relative_Counts.nlargest(topN).round(3)) entries = list() for code, corr in topNcorrs.iteritems(): if corr <= correlationCutoff: continue otherDX = (dict(coding=[dict(system='http://www.icd10data.com/', code=code)])) entries.append(dict(code=otherDX, coefficient=corr)) if not entries: print('No correlated Diagnoses for Lab ', thisLab) else: thisCPLab.scalarDistribution.correlatedDiagnoses = clinicalprofile.\ ClinicalProfileLabScalarDistributionCorrelatedDiagnoses( dict(topn=topN, entry=entries)) except: print('No correlated Diagnoses for Lab ', thisLab) try: topNcorrs = (pd.DataFrame(labs_correlatedProceduresCoefficients.loc[thisLab].groupby(['RAW_PX']) .Relative_Counts.mean()) .Relative_Counts.nlargest(topN).round(3)) entries = list() for code, corr in topNcorrs.iteritems(): if corr <= correlationCutoff: continue otherProc = [(dict(coding=[dict(system='http://www.ama-assn.org/practice-management/cpt', code=code)]))] entries.append(dict(code=otherProc, coefficient=corr)) if not entries: print('No correlated Procedures for Lab ', thisLab) else: thisCPLab.scalarDistribution.correlatedProcedures = clinicalprofile.\ ClinicalProfileLabScalarDistributionCorrelatedProcedures( dict(topn=topN, entry=entries)) except: print('No correlated Procedures for Lab ', thisLab) try: topNcorrs = (pd.DataFrame(labs_correlatedPhenotypesCoefficients.loc[thisLab].groupby(['HPO']) .Relative_Counts.mean()) .Relative_Counts.nlargest(topN).round(3)) entries = list() for code, corr in topNcorrs.iteritems(): if corr <= correlationCutoff: continue otherHPO = (dict(coding=[dict(system='http://hpo.jax.org/app/', code=code)])) entries.append(dict(code=otherHPO, coefficient=corr)) if not entries: print('No correlated Phenotypes for Lab ', thisLab) else: thisCPLab.scalarDistribution.correlatedPhenotypes = clinicalprofile.\ ClinicalProfileLabScalarDistributionCorrelatedPhenotypes( dict(topn=topN, entry=entries)) except: print('No correlated Phenotypes for Lab ', thisLab) labs.append(thisCPLab) # except: # print('This lab did not work ', thisLab) clinicalProfile.lab = labs if age_high != None: filename = cohort+'_resources/jh-labs-'+cohort+'-'+sex+'-'+race+'-'+str(int(age_low))+'-'+str(int(age_high))+'.json' else: filename = cohort+'_resources/jh-labs-'+cohort+'-'+sex+'-'+race+'-'+str(age_low)+'.json' with open(filename, 'w') as outfile: json.dump(clinicalProfile.as_json(), outfile, indent=4) del(clinicalProfile) return print('Write to '+ filename + ' successful')