Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 0 additions & 12 deletions .github/workflows/build-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -291,18 +291,6 @@ jobs:
with:
node-version: "22"

- name: Install Sushi
run: |
npm install -g fsh-sushi
sushi build
echo "Installed + run sushi"
working-directory: apps/bfd-model-idr/sushi

- name: Install fhirpath
run: |
npm install fhirpath
working-directory: apps/bfd-model-idr

- name: Install uv
uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0
with:
Expand Down
7 changes: 0 additions & 7 deletions .github/workflows/ci-pipeline-synthetic.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,16 +29,9 @@ jobs:
with:
java-version: "25"
distribution: "corretto"
- name: Install dependencies
run: npm install -g fsh-sushi && npm install fhirpath
working-directory: apps/bfd-model-idr
- name: Sync UV in bfd-model-idr
run: uv sync
working-directory: apps/bfd-model-idr
- name: Build sushi
run: |
cd ${{ github.workspace }}/apps/bfd-model-idr
sushi build ./sushi
- name: Generate v3 Data Dictionary
run: uv run gen_dd.py
working-directory: apps/bfd-model-idr
Expand Down
3 changes: 2 additions & 1 deletion apps/bfd-model-idr/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,5 @@ sushi/fsh-generated/*
validator_cli.jar
ReferenceTables/source-to-target-mappings
data/*
temp_packages/*
temp_packages/*
node_modules
5 changes: 1 addition & 4 deletions apps/bfd-model-idr/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,6 @@ npm --version
brew install npm
```

```sh
npm install -g fsh-sushi fhirpath
```

### Install packages (via uv)

Expand All @@ -51,7 +48,7 @@ uv sync
To compile the .fsh files from this folder

```sh
cd sushi && sushi build && cd ..
npm run sushi-build
```

This will generate the StructureDefinition and CodeSystem resources necessary for synthetic data generation. Running compile_resources.py is not necessary to generate synthetic data.
Expand Down
14 changes: 7 additions & 7 deletions apps/bfd-model-idr/claims_generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,8 @@
CLM_RLT_COND_SGNTR_MBR,
CLM_VAL,
CNTRCT_PBP_NUM,
PRVDR_HSTRY,
PRAUC,
PRVDR_HSTRY,
GeneratorUtil,
RowAdapter,
adapters_to_dicts,
Expand Down Expand Up @@ -788,7 +788,7 @@ def generate(

if sushi:
print("Running sushi build")
_, stderr = run_command(["sushi", "build"], cwd="./sushi")
_, stderr = run_command("npm run sushi-build", cwd=".")
if stderr:
print("SUSHI errors:")
print(stderr)
Expand Down Expand Up @@ -828,12 +828,12 @@ def generate(

other_util = OtherGeneratorUtil()

generated_provider_histories, generated_type_1_npis, generated_type_2_npis = other_util.gen_provider_history(amount=14, init_provider_historys=files[PRVDR_HSTRY])

out_tables[PRVDR_HSTRY].extend(
generated_provider_histories
generated_provider_histories, generated_type_1_npis, generated_type_2_npis = (
other_util.gen_provider_history(amount=14, init_provider_historys=files[PRVDR_HSTRY])
)

out_tables[PRVDR_HSTRY].extend(generated_provider_histories)

# This table is special in that its data is mostly static and read from a static file, so we
# don't need to do anything fancy with it
out_tables[CLM_ANSI_SGNTR] = other_util.gen_synthetic_clm_ansi_sgntr()
Expand Down Expand Up @@ -1051,7 +1051,7 @@ def generate(
else idx,
diagnoses=diagnoses,
init_clm_line=init_clm_line,
type_1_npis= generated_type_1_npis
type_1_npis=generated_type_1_npis,
)
adj_clms_tbls[CLM_LINE].append(clm_line)

Expand Down
18 changes: 11 additions & 7 deletions apps/bfd-model-idr/compile_resources.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@
import json
import subprocess
import sys
import requests
from pathlib import Path

MATCHBOX_SERVER = "http://localhost:8080/matchboxv3"
import requests

MATCHBOX_SERVER = "http://localhost:18080/matchboxv3"


def run_command(cmd, cwd=None):
Expand Down Expand Up @@ -39,6 +40,7 @@ def get_referenced_maps(compiled_map_path):
print("Error reading map:", e)
return set()


def get_sushi_resources():
try:
sushi_dir = Path(__file__).parent.absolute() / "sushi" / "fsh-generated" / "resources"
Expand All @@ -50,6 +52,7 @@ def get_sushi_resources():
print(f"Error getting SUSHI resources: {e}")
return ""


# populate matchbox's tx library
def upload_resources(resource_dir, server_url):
print("Uploading resources to matchbox")
Expand Down Expand Up @@ -196,9 +199,10 @@ def main():
script_dir = Path(__file__).parent.absolute()

# Generate Structure Definitions + CodeSystems
if(args.sushi):
if args.sushi:
print("Running sushi build")
stdout, stderr = run_command("sushi build", cwd=script_dir / "sushi")
run_command("npm install", cwd=script_dir)
stdout, stderr = run_command("npm run sushi-build", cwd=script_dir)
print("SUSHI output:")
print(stdout)
if stderr:
Expand Down Expand Up @@ -234,14 +238,14 @@ def main():
referenced_maps = get_referenced_maps(compiled_map_path)
map_imports = " ".join([f"-ig {map_file}" for map_file in referenced_maps])

#Augment source file if needed. Currently just for providers.
# Augment source file if needed. Currently just for providers.
(input_file,) = {args.input}
if 'EOB' in input_file:
if "EOB" in input_file:
print("Augmenting input file")
profile_flag = f" {args.profileType}" if args.profileType else ""
augmentation_cmd = f"python augment_sample_resources.py {args.input}{profile_flag}"
stdout, stderr = run_command(augmentation_cmd, cwd=script_dir)
input_file = 'out/temporary-sample.json'
input_file = "out/temporary-sample.json"

print("Executing Transform")
execute_cmd = f"java -jar validator_cli.jar {input_file} -output {args.output} -transform \
Expand Down
30 changes: 24 additions & 6 deletions apps/bfd-model-idr/docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,30 @@ services:
container_name: matchbox
restart: on-failure
ports:
- "8080:8080"
- "18080:8080"
depends_on:
- matchbox-db
entrypoint: ["java", "-Xms1G", "-Xmx4G", "-XX:+UseG1GC", "-XX:+UseCompressedOops", "-Xss512k", "-Dfhir.settings.path=/config/fhir-settings.json", "-Dspring.config.additional-location=optional:file:/config/application.yaml", "-jar", "/matchbox.jar"]
entrypoint:
[
"java",
"-Xms1G",
"-Xmx4G",
"-XX:+UseG1GC",
"-XX:+UseCompressedOops",
"-Xss512k",
"-Dfhir.settings.path=/config/fhir-settings.json",
"-Dspring.config.additional-location=optional:file:/config/application.yaml",
"-jar",
"/matchbox.jar",
]
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8080/matchboxv3/actuator/health"]
test:
[
"CMD",
"curl",
"-f",
"http://localhost:8080/matchboxv3/actuator/health",
]
interval: 5s
timeout: 5s
retries: 30
Expand All @@ -34,8 +52,8 @@ services:
ports:
- "15432:5432"
environment:
POSTGRES_DB: 'matchbox'
POSTGRES_USER: 'matchbox'
POSTGRES_PASSWORD: 'matchbox'
POSTGRES_DB: "matchbox"
POSTGRES_USER: "matchbox"
POSTGRES_PASSWORD: "matchbox"
volumes:
- ./data:/var/lib/postgresql/data
40 changes: 27 additions & 13 deletions apps/bfd-model-idr/gen_dd.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,21 @@
dd_df = []
structure_def_names_descriptions = {}


def run_subprocess(args: list[str]) -> subprocess.CompletedProcess[bytes]:
return subprocess.run(
args,
cwd=Path().parent,
check=True,
stdout=subprocess.PIPE,
)


if not Path("./sushi/fsh-generated/resources").exists():
print("Generating sushi files")
run_subprocess(["npm", "install"])
run_subprocess(["npm", "run", "sushi-build"])

for resource_type in sample_sources_by_profile:
with Path(sample_sources_by_profile[resource_type]).open() as file:
sample_resources_by_profile[resource_type] = json.load(file)
Expand Down Expand Up @@ -84,10 +99,13 @@
"Pharmacy",
"PriorAuth",
]


for walk_info in os.walk(dd_support_folder):
files = list(filter(lambda file: ".yaml" in file, walk_info[2]))
for file_name in files:
with Path(str(dd_support_folder) + "/" + str(file_name)).open() as file:
print("Generating", file_name)
data = yaml.safe_load(file)
current_resource_type = file_name[0 : len(file_name) - 5]
for entry in data:
Expand All @@ -110,16 +128,13 @@
entry["FHIR Resource"] = "AuditEvent"

# This opportunistically populates examples based upon the samples created from executing FML
result = subprocess.run(
result = run_subprocess(
[
"node",
"eval_fhirpath.js",
json.dumps(sample_resources_by_profile[entry["appliesTo"][0]]),
entry["fhirPath"],
],
cwd=os.path.dirname(__file__),
check=True,
stdout=subprocess.PIPE,
]
)
entry["example"] = json.loads(result.stdout)
if "iif" in entry["fhirPath"] or "union" in entry["fhirPath"]:
Expand All @@ -134,20 +149,20 @@

# Populate the element names + missing descriptions
if entry["inputPath"] in structure_def_names_descriptions:
entry["Field Name"] = structure_def_names_descriptions[
entry["inputPath"]
]["name"]
entry["Field Name"] = structure_def_names_descriptions[entry["inputPath"]][
"name"
]
if "definition" in structure_def_names_descriptions[entry["inputPath"]]:
entry["Description"] = structure_def_names_descriptions[
entry["inputPath"]
]["definition"]
#nameOverride and definitionOverride only exist when a field is derived IN fml.
]["definition"]
# nameOverride and definitionOverride only exist when a field is derived IN fml.
if "nameOverride" in entry:
entry["Field Name"] = entry["nameOverride"]
entry["Description"] = entry["definitionOverride"]
elif "Description" not in entry or not entry["Description"]:
raise ValueError(
f"Entry {entry.get("inputPath", 'Unknown')} has no definition. "
f"Entry {entry.get('inputPath', 'Unknown')} has no definition. "
)
entry.pop("inputPath")
dd_df.append(entry)
Expand All @@ -156,8 +171,7 @@


def replace_str(input_str):
# Yes, the below is intentional.
if input_str == input_str and len(str(input_str)) > 0:
if isinstance(input_str, str) and len(str(input_str)) > 0:
return "https://bluebutton.cms.gov/fhir/CodeSystem/" + str(input_str).replace("_", "-")
return ""

Expand Down
Loading
Loading