From 78e43cd45eef01607f2f94c008614c67116ed27f Mon Sep 17 00:00:00 2001 From: RunasSudo Date: Sat, 4 Feb 2023 14:09:58 +1100 Subject: [PATCH] Include RPBS items --- find_pbs_brand_names.py | 4 ++ html/index.html | 13 ++++- import_pbs_xml.py | 107 +++++++++++++++++++++++----------------- 3 files changed, 77 insertions(+), 47 deletions(-) diff --git a/find_pbs_brand_names.py b/find_pbs_brand_names.py index a7bf684..b5242b2 100755 --- a/find_pbs_brand_names.py +++ b/find_pbs_brand_names.py @@ -71,6 +71,10 @@ for mp_code in sorted(brand_names.keys()): # Conflict continue + # Exceptions + if short_name == 'Coloxyl with': + continue + # Can shorten if brand_name in brand_names[mp_code]: brand_names[mp_code].remove(brand_name) diff --git a/html/index.html b/html/index.html index 2d98a13..6b731ba 100644 --- a/html/index.html +++ b/html/index.html @@ -170,7 +170,10 @@ td = document.createElement('td'); td.innerText = item['maximum_prescribable_units']; tr.appendChild(td); td = document.createElement('td'); td.innerText = item['number_repeats']; tr.appendChild(td); - if (item['benefit_type'] === 'unrestricted') { + if (item['program'] === 'R1') { + td = document.createElement('td'); td.innerHTML = 'RPBS'; tr.appendChild(td); + tr.classList.add('table-secondary'); + } else if (item['benefit_type'] === 'unrestricted') { td = document.createElement('td'); tr.appendChild(td); } else if (item['benefit_type'] === 'restricted') { td = document.createElement('td'); td.innerHTML = 'Restricted'; tr.appendChild(td); @@ -193,6 +196,14 @@ const regexIsNumber = /^[0-9]+$/.compile(); function comparePBSItems(item1, item2) { + // Sort RPBS, etc. benefits after other items + if (item1['program'] === 'GE' && item2['program'] !== 'GE') { + return -1; + } + if (item2['program'] === 'GE' && item1['program'] !== 'GE') { + return 1; + } + // Sort tablets/capsules before other forms if ((item1['mpp_preferred_term'].indexOf(' tablet, ') >= 0 || item1['mpp_preferred_term'].indexOf(' capsule, ') >= 0) && !(item2['mpp_preferred_term'].indexOf(' tablet, ') >= 0 || item2['mpp_preferred_term'].indexOf(' capsule, ') >= 0)) { diff --git a/import_pbs_xml.py b/import_pbs_xml.py index c59f8bd..2dea9e3 100755 --- a/import_pbs_xml.py +++ b/import_pbs_xml.py @@ -24,7 +24,7 @@ cur = con.cursor() # Init schema cur.execute('DROP TABLE IF EXISTS pbs_item') -cur.execute('CREATE TABLE pbs_item (code TEXT PRIMARY KEY, mpp_code TEXT, maximum_prescribable_units INTEGER, number_repeats INTEGER, benefit_type TEXT)') +cur.execute('CREATE TABLE pbs_item (code TEXT PRIMARY KEY, mpp_code TEXT, maximum_prescribable_units INTEGER, number_repeats INTEGER, benefit_type TEXT, program TEXT)') cur.execute('DROP TABLE IF EXISTS pbs_mpp') cur.execute('CREATE TABLE pbs_mpp (code TEXT PRIMARY KEY, mp_code TEXT, preferred_term TEXT)') @@ -60,8 +60,8 @@ print('Parsed XML') root = tree.getroot() ns = {'pbs': 'http://schema.pbs.gov.au/', 'xlink': 'http://www.w3.org/1999/xlink', 'xml': 'http://www.w3.org/XML/1998/namespace', 'rdf': 'http://www.w3.org/1999/02/22-rdf-syntax-ns#', 'dbk': 'http://docbook.org/ns/docbook'} -# Get General Schedule -program = next(p for p in root.find('pbs:schedule', ns).findall('pbs:program', ns) if p.find('pbs:info', ns).find('pbs:code', ns).text == 'GE') +# ----------------------------------------- +# Parse items from each desired PBS program mpps_to_parse = set() tpps_to_parse = set() @@ -69,46 +69,56 @@ mps_to_parse = set() restrictions_to_parse = set() criteria_to_parse = set() -# Get schedule items (prescribing-rule) in schedule -for item in program.findall('pbs:prescribing-rule', ns): - code = item.find('pbs:code', ns).text +def parse_program(program_code): + # Get program + program = next(p for p in root.find('pbs:schedule', ns).findall('pbs:program', ns) if p.find('pbs:info', ns).find('pbs:code', ns).text == program_code) - # Only get benefits available to medical practitioners - benefits = [b for b in item.find('pbs:benefit-types-list', ns).findall('pbs:benefit-type', ns) if b.find('pbs:member-of-list', ns).find('pbs:member-of[@rdf:resource="http://pbs.gov.au/prescriber/medical"]', ns)] - - if not benefits: - continue - - assert len(benefits) == 1 - benefit = benefits[0] - - mpp_id = item.find('pbs:ready-prepared', ns).find('pbs:mpp-reference', ns).get('{http://www.w3.org/1999/xlink}href').lstrip('#') - mpp_code = item.find('pbs:ready-prepared', ns).find('pbs:mpp-reference', ns).find('pbs:code', ns).text - - max_units = item.find('pbs:ready-prepared', ns).find('pbs:maximum-prescribable[@rdf:resource="http://pbs.gov.au/reference/unit-of-use"]', ns).find('pbs:value', ns).text - max_repeats = item.find('pbs:ready-prepared', ns).find('pbs:number-repeats', ns).find('pbs:value', ns).text - - benefit_type = { - 'http://pbs.gov.au/benefit-type/unrestricted': 'unrestricted', - 'http://pbs.gov.au/benefit-type/restricted': 'restricted', - 'http://pbs.gov.au/benefit-type/streamlined': 'streamlined', - 'http://pbs.gov.au/benefit-type/authority-required': 'authority', - }[benefit.get('{http://www.w3.org/1999/02/22-rdf-syntax-ns#}resource')] - - cur.execute('INSERT INTO pbs_item (code, mpp_code, maximum_prescribable_units, number_repeats, benefit_type) VALUES (?, ?, ?, ?, ?)', (code, mpp_code, max_units, max_repeats, benefit_type)) - - # Get restrictions - if restrictions := benefit.find('pbs:restriction-references-list', ns): - for restriction_reference in restrictions.findall('pbs:restriction-reference', ns): - restriction_id = restriction_reference.get('{http://www.w3.org/1999/xlink}href').lstrip('#') - restriction_code = restriction_reference.find('pbs:code', ns).text - cur.execute('INSERT INTO pbs_item_restriction (item_code, restriction_code) VALUES (?, ?)', (code, restriction_code)) - - # Queue this restriction for parsing - restrictions_to_parse.add(restriction_id) - - # Queue the MPP for parsing - mpps_to_parse.add(mpp_id) + # Get schedule items (prescribing-rule) in schedule + for item in program.findall('pbs:prescribing-rule', ns): + code = item.find('pbs:code', ns).text + + # Only get benefits available to medical practitioners + benefits = [b for b in item.find('pbs:benefit-types-list', ns).findall('pbs:benefit-type', ns) if b.find('pbs:member-of-list', ns).find('pbs:member-of[@rdf:resource="http://pbs.gov.au/prescriber/medical"]', ns)] + + if not benefits: + continue + + assert len(benefits) == 1 + benefit = benefits[0] + + mpp_id = item.find('pbs:ready-prepared', ns).find('pbs:mpp-reference', ns).get('{http://www.w3.org/1999/xlink}href').lstrip('#') + mpp_code = item.find('pbs:ready-prepared', ns).find('pbs:mpp-reference', ns).find('pbs:code', ns).text + + max_units = item.find('pbs:ready-prepared', ns).find('pbs:maximum-prescribable[@rdf:resource="http://pbs.gov.au/reference/unit-of-use"]', ns).find('pbs:value', ns).text + max_repeats = item.find('pbs:ready-prepared', ns).find('pbs:number-repeats', ns).find('pbs:value', ns).text + + benefit_type = { + 'http://pbs.gov.au/benefit-type/unrestricted': 'unrestricted', + 'http://pbs.gov.au/benefit-type/restricted': 'restricted', + 'http://pbs.gov.au/benefit-type/streamlined': 'streamlined', + 'http://pbs.gov.au/benefit-type/authority-required': 'authority', + }[benefit.get('{http://www.w3.org/1999/02/22-rdf-syntax-ns#}resource')] + + cur.execute('INSERT INTO pbs_item (code, mpp_code, maximum_prescribable_units, number_repeats, benefit_type, program) VALUES (?, ?, ?, ?, ?, ?)', (code, mpp_code, max_units, max_repeats, benefit_type, program_code)) + + # Get restrictions + if restrictions := benefit.find('pbs:restriction-references-list', ns): + for restriction_reference in restrictions.findall('pbs:restriction-reference', ns): + restriction_id = restriction_reference.get('{http://www.w3.org/1999/xlink}href').lstrip('#') + restriction_code = restriction_reference.find('pbs:code', ns).text + cur.execute('INSERT INTO pbs_item_restriction (item_code, restriction_code) VALUES (?, ?)', (code, restriction_code)) + + # Queue this restriction for parsing + restrictions_to_parse.add(restriction_id) + + # Queue the MPP for parsing + mpps_to_parse.add(mpp_id) + +parse_program('GE') # General Schedule +parse_program('R1') # Repatriation PBS + +# ---------------- +# Parse MPPs, etc. # Parse MPPs for mpp_id in sorted(list(mpps_to_parse)): @@ -171,10 +181,15 @@ for restriction_id in sorted(list(restrictions_to_parse)): severity_term = severity.find('pbs:preferred-term', ns).text.strip() indication_strings.append(severity_term) - condition_id = indication.find('pbs:condition-reference', ns).get('{http://www.w3.org/1999/xlink}href').lstrip('#') - condition = root.find('pbs:prescribing-texts-list', ns).find('pbs:condition[@xml:id="' + condition_id + '"]', ns) - condition_term = condition.find('pbs:preferred-term', ns).text.strip() - indication_strings.append(condition_term) + if condition_reference := indication.find('pbs:condition-reference', ns): + condition_id = condition_reference.get('{http://www.w3.org/1999/xlink}href').lstrip('#') + condition = root.find('pbs:prescribing-texts-list', ns).find('pbs:condition[@xml:id="' + condition_id + '"]', ns) + condition_term = condition.find('pbs:preferred-term', ns).text.strip() + indication_strings.append(condition_term) + + if not indication_strings: + # TODO: Might have a + indication_strings = ['Unknown indication'] # Get operator and criteria operators = restriction.findall('pbs:any', ns) + restriction.findall('pbs:all', ns) + restriction.findall('pbs:one-of', ns)