Giter Club home page Giter Club logo

Comments (2)

grexican avatar grexican commented on August 13, 2024

The following monkeypatch, under the assumption it should be 1.29 and not 1.129, makes measure 0089 passable in cypress.

module HealthDataStandards
  module Import
    module Cat1

      # This class is the central location for taking a QRDA Cat 1 XML document and converting it
      # into the processed form we store in MongoDB. The class does this by running each measure
      # independently on the XML document
      #
      # This class is a Singleton. It should be accessed by calling PatientImporter.instance
      class PatientImporter
        alias_method :original_initialize, :initialize

        def initialize
          original_initialize

          # MONKEY PATCH: USING 1.129 (negative) instead of 1.29 (positive) for P2P Communication
          begin
            index = @section_importers[:procedures].find_index { |p| p.hqmf_oid == '2.16.840.1.113883.3.560.1.129'}

            if index.present?
              ptpcomm = @section_importers[:procedures][index]
              ptpcomm.hqmf_oid = '2.16.840.1.113883.3.560.1.29'
              @section_importers[:procedures][index] = ptpcomm

              puts "monkey patched initialize: #{@section_importers[:procedures][index].to_yaml}"
            else
              puts "MONKEY PATCH FAILED!"
            end

          rescue
            puts "Error #{$!}"
          end
        end

      end
    end
  end
end

from health-data-standards.

grexican avatar grexican commented on August 13, 2024

Actually the issue, I think, is much bigger than this. As I said above, it's not just the OID, but it's the NEGATIVE OID. Well that negative (NOT DONE) version needs to be accounted for to. And from what I see, it's not accounted for anywhere in the importer.

When generating QRDA III documents and doing performance calculations, everything still seems to come out fine. But when re-generating QRDA I documents, things don't go so well. So in order to combat this, I did 2 things:

  1. I implemented a negative version of each code. Usually that's adding 100 to the last numeric sequence in the OID. So if ti's 1.2.3.4 then the negative version of that OID is 1.2.3.104. If it's 1.2.3.95 then the negative version is 1.2.3.195. In the few cases that doesn't follow suit, the naming convention seems to be NOT DONE. So if the OID name is "Medication, Given" then the negative version is "Medication, Given not done." So given that, I implemented an automatic find-and-use negative version of codes passed in that hinges off of the negationInd flag.
  2. There were a bunch of codes in the patient importer that were incorrectly pointed to the negative version of the code. So I removed those and re-add them from the positive.

Here's the full monkey patch. I'm more than happy to turn this into a pull request and update the core code. I just need to know that it will actually be merged. I don't want to waste my time. This project seems very inactive. So I'm at least putting this here for the sake of others.

NOTE: with this monkey patch, I get 100% success flags on all ambulatory and inpatient Cypress tests on the latest package.

module HealthDataStandards
  module Import
    module Cat1

      class PatientImporter
        alias_method :original_initialize, :initialize

        def initialize
          original_initialize

          # MONKEY PATCH: USING 1.129 (negative) instead of 1.29 (positive) for Provider To Provider Communication
          # MONKEY PATCH: USING 1.103 (negative) instead of 1.3 (positive) for Diagnostic Study, Performed
          # MONKEY PATCH: USING 1.131 (negative) instead of 1.31 (positive) for Communication: From Provider to Patient
          # MONKEY PATCH: USING 1.110 (negative) instead of 1.10 (positive) for Device, Applied
          # MONKEY PATCH: Missing Substance, Administered
          begin
            index = @section_importers[:procedures].find_index { |p| p.hqmf_oid == '2.16.840.1.113883.3.560.1.129'}

            if index.present?
              importer = generate_importer(Cat1::ProcedureImporter, nil, '2.16.840.1.113883.3.560.1.29') #comm from provider to provider
              @section_importers[:procedures][index] = importer

              # puts "monkey patched initialize: #{@section_importers[:procedures][index].to_yaml}"
            else
              puts "MONKEY PATCH FAILED! - 129"
            end

            index = @section_importers[:procedures].find_index { |p| p.hqmf_oid == '2.16.840.1.113883.3.560.1.103'}

            if index.present?
              importer = generate_importer(CDA::ProcedureImporter, "./cda:entry/cda:observation[cda:templateId/@root = '2.16.840.1.113883.10.20.24.3.18']", '2.16.840.1.113883.3.560.1.3', 'performed') #diagnostic study performed
              @section_importers[:procedures][index] = importer

              # puts "monkey patched initialize: #{@section_importers[:procedures][index].to_yaml}"
            else
              puts "MONKEY PATCH FAILED! - 103"
            end

            index = @section_importers[:procedures].find_index { |p| p.hqmf_oid == '2.16.840.1.113883.3.560.1.131'}

            if index.present?
              importer = generate_importer(CDA::ProcedureImporter, "./cda:entry/cda:act[cda:templateId/@root = '2.16.840.1.113883.10.20.24.3.3']", '2.16.840.1.113883.3.560.1.31') #comm from provider to patient
              @section_importers[:procedures][index] = importer

              # puts "monkey patched initialize: #{@section_importers[:procedures][index].to_yaml}"
            else
              puts "MONKEY PATCH FAILED! - 131"
            end

            index = @section_importers[:medical_equipment].find_index { |p| p.hqmf_oid == '2.16.840.1.113883.3.560.1.110'}

            if index.present?
              importer = generate_importer(CDA::MedicalEquipmentImporter, "./cda:entry/cda:procedure[cda:templateId/@root = '2.16.840.1.113883.10.20.24.3.7']", '2.16.840.1.113883.3.560.1.10', 'applied')
              @section_importers[:medical_equipment][index] = importer

              # puts "monkey patched initialize: #{@section_importers[:procedures][index].to_yaml}"
            else
              puts "MONKEY PATCH FAILED! - 110"
            end


            index = @section_importers[:medications].find_index { |p| p.hqmf_oid == '2.16.840.1.113883.3.560.1.14'}

            if index.present?
              importer = generate_importer(CDA::MedicationImporter, "./cda:entry/cda:act[cda:templateId/@root = '2.16.840.1.113883.10.20.24.3.42']/cda:entryRelationship/cda:substanceAdministration[cda:templateId/@root='2.16.840.1.113883.10.20.22.4.16' and cda:text[not(contains(text(), 'Substance'))] ]", '2.16.840.1.113883.3.560.1.14', 'administered') #medication administered
              @section_importers[:medications][index] = importer

              importer = generate_importer(CDA::MedicationImporter, "./cda:entry/cda:act[cda:templateId/@root = '2.16.840.1.113883.10.20.24.3.42']/cda:entryRelationship/cda:substanceAdministration[cda:templateId/@root='2.16.840.1.113883.10.20.22.4.16' and cda:text[contains(text(), 'Substance')] ]", '2.16.840.1.113883.3.560.1.64', 'administered') # substance administered
              @section_importers[:medications] << importer

              # puts "monkey patched initialize: #{@section_importers[:procedures][index].to_yaml}"
            else
              puts "MONKEY PATCH FAILED! - 14"
            end

          rescue  => e
            puts "OOPS! #{e.inspect}"
            puts e.backtrace
          end
        end

        # def import_sections(record, doc)
        #
        #   context = doc.xpath("/cda:ClinicalDocument/cda:component/cda:structuredBody/cda:component/cda:section[cda:templateId/@root = '2.16.840.1.113883.10.20.24.2.1']")
        #   nrh = CDA::NarrativeReferenceHandler.new
        #   nrh.build_id_map(doc)
        #   @section_importers.each do |section, entry_packages|
        #     entry_packages.each do |entry_package|
        #       puts "#{section.to_json} - #{entry_package.to_json} - #{entry_package.package_entries(context, nrh).to_json}" if section.to_s == 'procedures' && entry_package.package_entries(context, nrh).length > 0
        #       record.send(section) << entry_package.package_entries(context, nrh)
        #     end
        #   end
        #end

      end
    end
  end
end

module HealthDataStandards
  module Import
    module CDA
      class SectionImporter

        private

        alias_method :original_extract_code, :extract_code

        # MONKEY PATCH: Only return code_hash if a code was found (fix for codeClass="UNK")
        # MONKEY PATCH: template generators expect code_system not codeSystem
        def extract_code(parent_element, code_xpath, code_system=nil)
          code_hash = original_extract_code parent_element, code_xpath, code_system

          code_hash = nil unless code_hash.present? && code_hash['code'].present?

          if code_hash.present?
            code_hash['code_system'] = code_hash['codeSystem'] if code_hash['codeSystem']
            code_hash['code_system_oid'] = code_hash['codeSystemOid'] if code_hash['codeSystemOid']
          end

          code_hash
        end

      end
    end
  end
end

module HealthDataStandards
  module Import
    module Cat1
      class EntryPackage

        attr_accessor :oid_hash, :status_hash

        alias_method :original_initialize, :initialize

        def initialize (type, oid, stat = nil)
          begin
            if oid.is_a?(Hash)
              self.oid_hash = oid
              oid = oid[:positive]
            else
              self.oid_hash = { positive: oid, negative: find_negative(oid) }
            end

            if stat.is_a?(Hash)
              self.status_hash = stat
              stat = stat[:positive]
            else
              self.status_hash = { positive: stat }
              self.status_hash[:negative] = "not " + stat if stat.present?
            end

            return original_initialize(type, oid, stat)
          rescue => e
            puts "OOPS! #{e.inspect}"
            puts e.backtrace
          end
        end

        def find_negative(oid)
          neg_oid = oid.dup # copy
          ri = neg_oid.rindex('.')
          rn = neg_oid[ri + 1, 10].to_i

          if rn < 1000
            rn = rn + 100
          else
            rn = '1' + rn.to_s
          end

          neg_oid = neg_oid[0, ri + 1] + rn.to_s

          ret = oid # default ret if can't find

          by_id = HealthDataStandards::Export::QRDA::EntryTemplateResolver.hqmf_qrda_oid_map.select { |e|
            e['hqmf_oid'] == oid
          }

          if by_id.length == 1
            # found just one positive... let's do it

            negs = HealthDataStandards::Export::QRDA::EntryTemplateResolver.hqmf_qrda_oid_map.select { |e|
              e['qrda_oid'] == by_id[0]['qrda_oid'] && (e['hqmf_oid'] == neg_oid || e['hqmf_name'] == by_id[0]['hqmf_name'] + " not done")
            }

            if negs.length == 1
              ret = negs[0]['hqmf_oid']
              puts "  FOUND NEG FOR #{oid}: #{negs[0].to_json}"
              puts " NEG SET, BUT ID MISMATCH FOR #{oid}: #{ret} != #{neg_oid}" if neg_oid != ret
            else
              puts "  NO NEG FOR #{oid}: neg_by_name.length: #{negs.length}"
            end
          else
            puts "  NO NEG SET FOR #{oid}: by_id.length: #{by_id.length}"
          end

          #puts " NEG SET: #{ret} for #{oid}" if oid != ret

          return ret
        end

        def select_oid(entry)
          return self.oid_hash[:positive] unless entry.negation_ind
          return self.oid_hash[:negative] if entry.negation_ind
        end

        def select_status(entry)
          return self.status_hash[:positive] unless entry.negation_ind
          return self.status_hash[:negative] if entry.negation_ind
        end

        def package_entries (doc, nrh)
          entries = self.importer_type.create_entries(doc, nrh)
          entries.each do |entry|

            begin
              entry.oid = self.select_oid(entry)
              entry.status = self.select_status(entry)
            rescue
              "DOH! #{$!}"
            end

          end
          entries
        end
      end
    end
  end
end

from health-data-standards.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.