Top Level Namespace
Defined Under Namespace
Modules: Formulary
Constant Summary collapse
- FHIR_SERVER =
Read the const variables from options or set default value.
"https://davinci-drug-formulary-ri.logicahealth.org"
- CONFORMANCE_DEFINITIONS_URL =
.conformance_url || "https://build.fhir.org/ig/HL7/davinci-pdex-formulary/branches/master/definitions.json.zip"
- FAILED_UPLOAD =
[]
- FHIR_SERVER_BASE =
.fhir_server || "https://davinci-drug-formulary-ri.logicahealth.org"
- PAYERS =
[]
- FORMULARIES =
[]
- LOCATIONS =
[]
- NDOUTS =
[]
Instance Method Summary collapse
- #extract_location_id_from_reference(reference) ⇒ Object
-
#generate_bulk_export ⇒ Object
Generates the grouped bulk data export.
-
#generate_export_json(output_directory, request, output) ⇒ Object
Constructs and write the export.json file to the specified destination.
-
#generate_formulary_bulk_data ⇒ Object
Group each formulary resource with its associated Location, Basic, and MedicationKnowledge resources.
-
#generate_ndjson(resource_type, resource_list, output_directory) ⇒ Object
Writing ndjson files for a given resource type.
-
#generate_payer_bulk_data ⇒ Object
Group payer insurance resources with their associated Formulary, Basic, MK, and Location resources.
- #get_all_insurance_plans ⇒ Object
- #get_all_location_resources ⇒ Object
-
#get_related_basic_and_medicationknowledge(formulary_id, output_directory) ⇒ Object
Get all Basic and MK resources linked to the given InsurancePlan.
-
#get_related_locations(location_ids, output_directory) ⇒ Object
Retrieve location resources with given ids.
-
#get_resource_json_files(resource_directory) ⇒ Array [String]
A list of resource file's names from the resource directory.
- #retry_failed_upload ⇒ Object
-
#upload_all_resources ⇒ Object
Runs all the upload methods.
- #upload_conformance_resources ⇒ Object
- #upload_resource(resource) ⇒ Object
- #upload_sample_resources ⇒ Object
Instance Method Details
#extract_location_id_from_reference(reference) ⇒ Object
61 62 63 64 |
# File 'scripts/plan_specific_ndjson.rb', line 61 def extract_location_id_from_reference(reference) reference = [] if reference.nil? reference.map { |area| area[:reference].split("/").last } end |
#generate_bulk_export ⇒ Object
Generates the grouped bulk data export
154 155 156 157 158 159 160 161 162 163 164 |
# File 'scripts/plan_specific_ndjson.rb', line 154 def generate_bulk_export # Delete the bulk_export directory if it exists. FileUtils.rm_rf("bulk_export") get_all_insurance_plans get_all_location_resources p "===============================================================" p "Creating the Bulk export folder output ..." generate_payer_bulk_data generate_formulary_bulk_data end |
#generate_export_json(output_directory, request, output) ⇒ Object
Constructs and write the export.json file to the specified destination
95 96 97 98 99 100 101 102 103 104 105 106 |
# File 'scripts/plan_specific_ndjson.rb', line 95 def generate_export_json(output_directory, request, output) export = { transactionTime: Time.now.strftime("%FT%T%:z"), request: request, requiresAccessToken: false, output: output, } file_path = File.join(output_directory, "export.json") File.open(file_path, "w") do |file| file.write(JSON.pretty_generate(export)) end end |
#generate_formulary_bulk_data ⇒ Object
Group each formulary resource with its associated Location, Basic, and MedicationKnowledge resources.
137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 |
# File 'scripts/plan_specific_ndjson.rb', line 137 def generate_formulary_bulk_data p "There are no Formulary resources available to generate bulk data." if FORMULARIES.empty? FORMULARIES.each do |formulary| NDOUTS.clear request = "#{FHIR_SERVER}/fhir/InsurancePlan/#{formulary[:id]}/$export" output_directory = File.join("bulk_export", formulary[:id]) FileUtils.mkdir_p(output_directory) generate_ndjson("InsurancePlan", [formulary], output_directory) (formulary[:id], output_directory) location_ids = extract_location_id_from_reference(formulary[:coverageArea]) (location_ids, output_directory) generate_export_json(output_directory, request, NDOUTS) end end |
#generate_ndjson(resource_type, resource_list, output_directory) ⇒ Object
Writing ndjson files for a given resource type
73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 |
# File 'scripts/plan_specific_ndjson.rb', line 73 def generate_ndjson(resource_type, resource_list, output_directory) p "===============================================================" p "Generating ndjson file of type #{resource_type}..." outfile = File.join(output_directory, "#{resource_type}.ndjson") ndout = { type: resource_type, url: "#{FHIR_SERVER}/resources/#{output_directory.split("/").last}/#{resource_type}.ndjson", } NDOUTS << ndout begin o = File.open(outfile, "w") p "Writing #{resource_list.size} #{resource_type} resource instances to #{outfile}..." resource_list.each { |instance| o.puts(JSON.generate(instance)) } rescue StandardError => e puts "An error occured when generating file #{outfile}: #{e.}" ensure o.close end end |
#generate_payer_bulk_data ⇒ Object
Group payer insurance resources with their associated Formulary, Basic, MK, and Location resources
109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 |
# File 'scripts/plan_specific_ndjson.rb', line 109 def generate_payer_bulk_data p "There are no payer resources available to generate bulk data." if PAYERS.empty? PAYERS.each do |payer| NDOUTS.clear request = "#{FHIR_SERVER}/fhir/InsurancePlan/#{payer[:id]}/$export" output_directory = File.join("bulk_export", payer[:id]) FileUtils.mkdir_p(output_directory) = [] payer[:coverage].each do |coverage| formulary = coverage[:extension].find { |ext| ext[:url] == "http://hl7.org/fhir/us/davinci-drug-formulary/StructureDefinition/usdf-FormularyReference-extension" } unless formulary.nil? << formulary[:valueReference][:reference].split("/").last end end = FORMULARIES.find_all { |formulary| .include?(formulary[:id]) } .prepend(payer) generate_ndjson("InsurancePlan", , output_directory) .each { |id| (id, output_directory) } location_ids = extract_location_id_from_reference(payer[:coverageArea]) (location_ids, output_directory) generate_export_json(output_directory, request, NDOUTS) end end |
#get_all_insurance_plans ⇒ Object
23 24 25 26 27 28 29 30 31 32 |
# File 'scripts/plan_specific_ndjson.rb', line 23 def get_all_insurance_plans p "===============================================================" p "Reading all InsurancePlan resources..." plan_files = get_resource_json_files("output/InsurancePlan") plan_files.each do |json_file| resource = JSON.parse(File.read(json_file), symbolize_names: true) json_file.include?("Payer") ? PAYERS << resource : FORMULARIES << resource end p "Found a total of #{PAYERS.size} PAYERS and #{FORMULARIES.size} Formulary plans." end |
#get_all_location_resources ⇒ Object
34 35 36 37 38 39 |
# File 'scripts/plan_specific_ndjson.rb', line 34 def get_all_location_resources location_files = get_resource_json_files("location_resources") location_files.each do |json_file| LOCATIONS << JSON.parse(File.read(json_file), symbolize_names: true) end end |
#get_related_basic_and_medicationknowledge(formulary_id, output_directory) ⇒ Object
Get all Basic and MK resources linked to the given InsurancePlan
44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 |
# File 'scripts/plan_specific_ndjson.rb', line 44 def (formulary_id, output_directory) p "===============================================================" p "Getting all Basic and MedicationKnowledge related to Formulary with ID= #{formulary_id}..." id_digits = formulary_id.split("-").last basic_files = get_resource_json_files("output/Basic").select { |f_name| f_name.include?(id_digits) } basic_resources = basic_files.map { |json_f| JSON.parse(File.read(json_f), symbolize_names: true) } # Get the reference ids to retrieve related medication_knowledge_resources ref_ids = basic_resources.map { |resource| resource[:id].split("-").last } medication_knowledge_files = get_resource_json_files("output/MedicationKnowledge").select { |f_name| ref_ids.any? { |id| f_name.include?(id) } } medication_knowledge_resources = medication_knowledge_files.map { |json_f| JSON.parse(File.read(json_f), symbolize_names: true) } p "There are #{basic_resources.size} Basic resources and #{medication_knowledge_resources.size} MedicationKnowledge resources related to Formulary with ID = #{formulary_id}" generate_ndjson("Basic", basic_resources, output_directory) generate_ndjson("MedicationKnowledge", medication_knowledge_resources, output_directory) end |
#get_related_locations(location_ids, output_directory) ⇒ Object
Retrieve location resources with given ids
67 68 69 70 |
# File 'scripts/plan_specific_ndjson.rb', line 67 def (location_ids, output_directory) specific_locations = LOCATIONS.find_all { |loc| location_ids.include?(loc[:id]) } generate_ndjson("Location", specific_locations, output_directory) end |
#get_resource_json_files(resource_directory) ⇒ Array [String]
Returns a list of resource file's names from the resource directory.
18 19 20 21 |
# File 'scripts/plan_specific_ndjson.rb', line 18 def get_resource_json_files(resource_directory) file_path = File.join(resource_directory, "*.json") file_names = Dir.glob(file_path) end |
#retry_failed_upload ⇒ Object
87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 |
# File 'scripts/upload.rb', line 87 def retry_failed_upload n = FAILED_UPLOAD.size while !FAILED_UPLOAD.empty? && n > 0 puts "#{FAILED_UPLOAD.count} resource(s) failed to upload. Retrying..." failed_upload_copy = FAILED_UPLOAD.dup FAILED_UPLOAD.clear failed_upload_copy.each do |resource| response = upload_resource(resource) FAILED_UPLOAD << resource unless response&.success? end n -= 1 end puts "Ending the program ..." if FAILED_UPLOAD.empty? puts "All resources were uploaded successfully." else puts "#{FAILED_UPLOAD.count} resource(s) failed to upload" end end |
#upload_all_resources ⇒ Object
Runs all the upload methods
108 109 110 111 112 |
# File 'scripts/upload.rb', line 108 def upload_all_resources upload_conformance_resources upload_sample_resources retry_failed_upload end |
#upload_conformance_resources ⇒ Object
21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 |
# File 'scripts/upload.rb', line 21 def upload_conformance_resources definitions_file = Tempfile.new begin definitions_data = HTTParty.get(CONFORMANCE_DEFINITIONS_URL, verify: false) definitions_file.write(definitions_data) rescue => e puts "Unable to upload conformance definitions." puts "Error#upload_conformance_resources: #{e.}" return ensure definitions_file.close end begin Zip::File.open(definitions_file.path) do |zip_file| conf_resources = zip_file.entries .select { |entry| entry.name.end_with? ".json" } .reject { |entry| entry.name.start_with? "ImplementationGuide" } puts "Uploading #{conf_resources.count} conformance resources..." conf_resources.each do |entry| resource = JSON.parse(entry.get_input_stream.read, symbolize_names: true) response = upload_resource(resource) FAILED_UPLOAD << resource unless response&.success? end end rescue => e puts "Error#upload_conformance_resources: #{e.}" puts "Please provide a valid conformance URL" ensure definitions_file.unlink end end |
#upload_resource(resource) ⇒ Object
71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 |
# File 'scripts/upload.rb', line 71 def upload_resource(resource) resource_type = resource[:resourceType] id = resource[:id] begin HTTParty.put( "#{FHIR_SERVER}/#{resource_type}/#{id}", body: resource.to_json, headers: { 'Content-Type': "application/json" }, ) rescue => e puts "An exception occured when trying to load the resource #{resource[:resource_type]}/#{resource[:id]}." puts "Error#upload_resource: #{e.}" return end end |
#upload_sample_resources ⇒ Object
54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 |
# File 'scripts/upload.rb', line 54 def upload_sample_resources location_file_path = File.join("location_resources", "*.json") file_path = File.join("output", "**/*.json") filenames = Dir.glob([file_path, location_file_path]) # .partition { |filename| filename.include? "InsurancePlan" } # .flatten puts "Uploading #{filenames.length} resources" filenames.each_with_index do |filename, index| resource = JSON.parse(File.read(filename), symbolize_names: true) response = upload_resource(resource) FAILED_UPLOAD << resource unless response&.success? if index % 100 == 0 puts "#{FAILED_UPLOAD.count} out of #{index + 1} attempted resources failed to be uploaded successfully." end end end |