SDK implementation for Radiology Insights (in public preview) (#28577)

### Packages impacted by this PR


### Issues associated with this PR


### Describe the problem that is addressed by this PR


### What are the possible designs available to address the problem? If
there are more than one possible design, why was the one in this PR
chosen?


### Are there test cases added in this PR? _(If not, why?)_


### Provide a list of related PRs _(if any)_


### Command used to generate this PR:**_(Applicable only to SDK release
request PRs)_

### Checklists
- [ ] Added impacted package name to the issue description
- [ ] Does this PR needs any fixes in the SDK Generator?** _(If so,
create an Issue in the
[Autorest/typescript](https://github.com/Azure/autorest.typescript)
repository and link it here)_
- [ ] Added a changelog (if necessary)

---------

Co-authored-by: Asaf Levi <asaflevi@microsoft.com>
Co-authored-by: KarolGel <138193722+KarolGel@users.noreply.github.com>
Co-authored-by: tomsft <138026577+tomsft@users.noreply.github.com>
Co-authored-by: Karolien Gellynck <kgellynck@microsoft.com>
Co-authored-by: Tom Deray <tomderay@microsoft.com>
This commit is contained in:
koen-mertens 2024-03-06 09:55:05 +01:00 коммит произвёл GitHub
Родитель 2256ce3703
Коммит e49cb8addb
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: B5690EEEBB952194
39 изменённых файлов: 4915 добавлений и 3 удалений

4
.github/CODEOWNERS поставляемый
Просмотреть файл

@ -148,6 +148,10 @@
# AzureSdkOwners: @deyaaeldeen @jeremymeng
/sdk/eventhub/ @deyaaeldeen @jeremymeng @HarshaNalluru
# ServiceLabel: %Cognitive - Health Insights
# PRLabel: %Cognitive - Health Insights
/sdk/healthinsights/ @tomsft @koen-mertens
# PRLabel: %Azure.Identity
# ServiceLabel: %Azure.Identity
# AzureSdkOwners: @KarishmaGhiya @maorleger

17
.vscode/cspell.json поставляемый
Просмотреть файл

@ -59,9 +59,11 @@
"CONTOSO",
"deps",
"deserialization",
"deserializers",
"devboxes",
"devcenter",
"devdeps",
"dicom",
"dotenv",
"DTDL",
"dtmi",
@ -89,6 +91,7 @@
"lcov",
"lcovonly",
"Localizable",
"loinc",
"Lucene",
"Mibps",
"mkdir",
@ -102,6 +105,8 @@
"npmjs",
"ODATA",
"Odbc",
"Onco",
"oncophenotype",
"openai",
"perfstress",
"personalizer",
@ -148,9 +153,7 @@
"USUK",
"Vertica",
"westus",
"Xiaomi",
"Onco",
"oncophenotype"
"Xiaomi"
],
"allowCompoundWords": true,
"overrides": [
@ -464,6 +467,14 @@
"presentationml"
]
},
{
"filename": "sdk/healthinsights/azure-healthinsights-radiologyinsights/**",
"words": [
"ctxt",
"mros",
"nify"
]
},
{
"filename": "sdk/notificationhubs/notification-hubs/review/notification-hubs.api.md",
"words": [

Просмотреть файл

@ -875,6 +875,9 @@ dependencies:
'@rush-temp/health-insights-clinicalmatching':
specifier: file:./projects/health-insights-clinicalmatching.tgz
version: file:projects/health-insights-clinicalmatching.tgz
'@rush-temp/health-insights-radiologyinsights':
specifier: file:./projects/health-insights-radiologyinsights.tgz
version: file:projects/health-insights-radiologyinsights.tgz
'@rush-temp/identity':
specifier: file:./projects/identity.tgz
version: file:projects/identity.tgz
@ -19290,6 +19293,50 @@ packages:
- utf-8-validate
dev: false
file:projects/health-insights-radiologyinsights.tgz:
resolution: {integrity: sha512-YZUxq+zA38cuNkYUDIoF/PRJTqCl89BoTSHefdqKb4s8OVwTSsMQQNLRVl/hUMJQKWEamwyckQbm1WQAcUpbBA==, tarball: file:projects/health-insights-radiologyinsights.tgz}
name: '@rush-temp/health-insights-radiologyinsights'
version: 0.0.0
dependencies:
'@azure/abort-controller': 1.1.0
'@azure/identity': 4.0.1
'@microsoft/api-extractor': 7.39.1(@types/node@18.19.17)
'@types/chai': 4.3.11
'@types/mocha': 10.0.6
'@types/node': 18.19.17
autorest: 3.7.1
c8: 8.0.1
chai: 4.3.10
cross-env: 7.0.3
dotenv: 16.4.5
eslint: 8.56.0
esm: 3.2.25
karma: 6.4.2(debug@4.3.4)
karma-chrome-launcher: 3.2.0
karma-coverage: 2.2.1
karma-env-preprocessor: 0.1.1
karma-firefox-launcher: 2.1.2
karma-junit-reporter: 2.0.1(karma@6.4.2)
karma-mocha: 2.0.1
karma-mocha-reporter: 2.2.5(karma@6.4.2)
karma-source-map-support: 1.4.0
karma-sourcemap-loader: 0.4.0
mkdirp: 2.1.6
mocha: 10.3.0
rimraf: 5.0.5
source-map-support: 0.5.21
ts-node: 10.9.2(@types/node@18.19.17)(typescript@5.3.3)
tslib: 2.6.2
typescript: 5.3.3
transitivePeerDependencies:
- '@swc/core'
- '@swc/wasm'
- bufferutil
- debug
- supports-color
- utf-8-validate
dev: false
file:projects/identity-broker.tgz:
resolution: {integrity: sha512-RE+YqSTaxxR3bgxMrHGjkuJjywZPJpdr10nDdOkrJ22/So+aW0kisoQEPaQ6WBL7HD6PSN9fWxfTBYsKfBGe2w==, tarball: file:projects/identity-broker.tgz}
name: '@rush-temp/identity-broker'

Просмотреть файл

@ -1473,6 +1473,11 @@
"projectFolder": "sdk/healthinsights/health-insights-clinicalmatching-rest",
"versionPolicyName": "client"
},
{
"packageName": "@azure-rest/health-insights-radiologyinsights",
"projectFolder": "sdk/healthinsights/health-insights-radiologyinsights-rest",
"versionPolicyName": "client"
},
{
"packageName": "@azure/arm-deploymentmanager",
"projectFolder": "sdk/deploymentmanager/arm-deploymentmanager",

Просмотреть файл

@ -31,3 +31,5 @@ extends:
safeName: azureresthealthinsightscancerprofiling
- name: azure-rest-health-insights-clinicalmatching
safeName: azureresthealthinsightsclinicalmatching
- name: azure-rest-health-insights-radiologyinsights
safeName: azureresthealthinsightsradiologyinsights

Просмотреть файл

@ -0,0 +1,11 @@
{
"plugins": ["@azure/azure-sdk"],
"extends": ["plugin:@azure/azure-sdk/azure-sdk-base"],
"rules": {
"@azure/azure-sdk/ts-modules-only-named": "warn",
"@azure/azure-sdk/ts-apiextractor-json-types": "warn",
"@azure/azure-sdk/ts-package-json-types": "warn",
"@azure/azure-sdk/ts-package-json-engine-is-present": "warn",
"tsdoc/syntax": "warn"
}
}

Просмотреть файл

@ -0,0 +1,5 @@
# Release History
## 1.0.0-beta.1 (2024-03-05)
- First release of package, see README.md for details.

Просмотреть файл

@ -0,0 +1,275 @@
# Azure Cognitive Services Health Insights Radiology Insights REST client library for JavaScript
[Health Insights][health_insights] is an Azure Applied AI Service built with the Azure Cognitive Services Framework, that leverages multiple Cognitive Services, Healthcare API services and other Azure resources.
[Radiology Insights][radiology_insights_docs] is a model that aims to provide quality checks as feedback on errors and inconsistencies (mismatches) and ensures critical findings are identified and communicated using the full context of the report. Follow-up recommendations and clinical findings with measurements (sizes) documented by the radiologist are also identified.
**Please rely heavily on our [REST client docs](https://github.com/Azure/azure-sdk-for-js/blob/main/documentation/rest-clients.md) to use this library**
Key links:
Key links:
- [Source code]
- [Package (NPM)]
- [API reference documentation]
- [Product Information](https://docs.microsoft.com/rest/api/maps/route)
- [Samples]
## Getting started
### Currently supported environments
- LTS versions of Node.js
- Latest versions of Safari, Chrome, Edge and Firefox.
### Prerequisites
- LTS versions of Node.js
- You must have an [Azure subscription](https://azure.microsoft.com/free/) to use this package.
- An existing Cognitive Services Health Insights instance.
### Install the `@azure-rest/health-insights-radiologyinsights` package
Install the RadiologyInsights REST client library for JavaScript with `npm`:
```bash
npm install @azure-rest/health-insights-radiologyinsights
```
### Create and authenticate a `RadiologyInsightsClient`
|SDK version|Supported API version of service |
|-------------|---------------|
|1.0.0-beta.1 | 2024-01-19-preview|
To use an [Azure Active Directory (AAD) token credential][token_credential],
provide an instance of the desired credential type obtained from the [Azure Identity library][azure_identity].
To authenticate with AAD, you must first `npm` install [`@azure/identity`][identity]
After setup, you can choose which type of [credential][credential] from `@azure/identity` to use.
As an example, [DefaultAzureCredential][defaultazurecredential]
can be used to authenticate the client.
Set the values of the client ID, tenant ID, and client secret of the AAD application as environment variables:
AZURE_CLIENT_ID, AZURE_TENANT_ID, AZURE_CLIENT_SECRET
## Examples
### Create a RadiologyInsights asynchronous client
```typescript
const apiKey = process.env["HEALTH_INSIGHTS_API_KEY"] || "";
const endpoint = process.env["HEALTH_INSIGHTS_ENDPOINT"] || "";
const credential = new AzureKeyCredential(apiKey);
const client = RadiologyInsightsRestClient(endpoint, credential);
```
### Build a request, send it to the client and print the description of a Critical Result Inference
```typescript
export async function main() {
const credential = new AzureKeyCredential(apiKey);
const client = AzureHealthInsightsClient(endpoint, credential);
// Create request body
const radiologyInsightsParameter = createRequestBody();
// Initiate radiology insights job and retrieve results
const initialResponse = await client.path("/radiology-insights/jobs").post(radiologyInsightsParameter);
if (isUnexpected(initialResponse)) {
throw initialResponse;
}
const poller = await getLongRunningPoller(client, initialResponse);
const RadiologyInsightsResult = await poller.pollUntilDone();
if (isUnexpected(RadiologyInsightsResult)) {
throw RadiologyInsightsResult;
}
const resultBody = RadiologyInsightsResult.body;
printResults(resultBody);
}
function createRequestBody(): CreateJobParameters {
const codingData = {
system: "Http://hl7.org/fhir/ValueSet/cpt-all",
code: "USPELVIS",
display: "US PELVIS COMPLETE"
};
const code = {
coding: [codingData]
};
const patientInfo = {
sex: "female",
birthDate: new Date("1959-11-11T19:00:00+00:00"),
};
const encounterData = {
id: "encounterid1",
period: {
"start": "2021-8-28T00:00:00",
"end": "2021-8-28T00:00:00"
},
class: "inpatient"
};
const authorData = {
"id": "authorid1",
"name": "authorname1"
};
const orderedProceduresData = {
code: code,
description: "US PELVIS COMPLETE"
};
const administrativeMetadata = {
orderedProcedures: [orderedProceduresData],
encounterId: "encounterid1"
};
const content = {
sourceType: "inline",
value: "CLINICAL HISTORY: "
+ "\r\n20-year-old female presenting with abdominal pain. Surgical history significant for appendectomy."
+ "\r\n "
+ "\r\nCOMPARISON: "
+ "\r\nRight upper quadrant sonographic performed 1 day prior."
+ "\r\n "
+ "\r\nTECHNIQUE: "
+ "\r\nTransabdominal grayscale pelvic sonography with duplex color Doppler "
+ "\r\nand spectral waveform analysis of the ovaries."
+ "\r\n "
+ "\r\nFINDINGS: "
+ "\r\nThe uterus is unremarkable given the transabdominal technique with "
+ "\r\nendometrial echo complex within physiologic normal limits. The "
+ "\r\novaries are symmetric in size, measuring 2.5 x 1.2 x 3.0 cm and the "
+ "\r\nleft measuring 2.8 x 1.5 x 1.9 cm.\n \r\nOn duplex imaging, Doppler signal is symmetric."
+ "\r\n "
+ "\r\nIMPRESSION: "
+ "\r\n1. Normal pelvic sonography. Findings of testicular torsion."
+ "\r\n\nA new US pelvis within the next 6 months is recommended."
+ "\n\nThese results have been discussed with Dr. Jones at 3 PM on November 5 2020.\n "
+ "\r\n"
};
const patientDocumentData = {
type: "note",
clinicalType: "radiologyReport",
id: "docid1",
language: "en",
authors: [authorData],
specialtyType: "radiology",
administrativeMetadata: administrativeMetadata,
content: content,
createdDateTime: new Date("2021-06-01T00:00:00.000"),
orderedProceduresAsCsv: "US PELVIS COMPLETE"
};
const patientData = {
id: "Samantha Jones",
info: patientInfo,
encounters: [encounterData],
patientDocuments: [patientDocumentData]
};
const inferenceTypes = [
"finding",
"ageMismatch",
"lateralityDiscrepancy",
"sexMismatch",
"completeOrderDiscrepancy",
"limitedOrderDiscrepancy",
"criticalResult",
"criticalRecommendation",
"followupRecommendation",
"followupCommunication",
"radiologyProcedure"];
const followupRecommendationOptions = {
includeRecommendationsWithNoSpecifiedModality: true,
includeRecommendationsInReferences: true,
provideFocusedSentenceEvidence: true
};
const findingOptions = {
provideFocusedSentenceEvidence: true
};
const inferenceOptions = {
followupRecommendationOptions: followupRecommendationOptions,
findingOptions: findingOptions
};
const configuration = {
inferenceOptions: inferenceOptions,
inferenceTypes: inferenceTypes,
locale: "en-US",
verbose: false,
includeEvidence: true
};
const radiologyInsightsData = {
patients: [patientData],
configuration: configuration
};
return {
body: radiologyInsightsData
}
}
function printResults(radiologyInsightsResult: RadiologyInsightsResultOutput): void {
if (radiologyInsightsResult.status === "succeeded") {
const results = radiologyInsightsResult.result;
if (results !== undefined) {
results.patientResults.forEach((patientResult: { inferences: any[]; }) => {
if (patientResult.inferences) {
patientResult.inferences.forEach((inference) => {
if (inference.kind === "criticalResult") {
if ("result" in inference) {
console.log("Critical Result Inference found: " + inference.result.description);
}
}
});
}
});
}
} else {
const error = radiologyInsightsResult.error;
if (error) {
console.log(error.code, ":", error.message);
}
}
}
```
## Troubleshooting
### Logging
Enabling logging may help uncover useful information about failures. In order to see a log of HTTP requests and responses, set the `AZURE_LOG_LEVEL` environment variable to `info`. Alternatively, logging can be enabled at runtime by calling `setLogLevel` in the `@azure/logger`:
```javascript
const { setLogLevel } = require("@azure/logger");
setLogLevel("info");
```
For more detailed instructions on how to enable logs, you can look at the [@azure/logger package docs](https://github.com/Azure/azure-sdk-for-js/tree/main/sdk/core/logger).
<!-- LINKS -->
[health_insights]: https://learn.microsoft.com/azure/azure-health-insights/overview
[radiology_insights_docs]: https://learn.microsoft.com/azure/azure-health-insights/radiology-insights/
[azure_identity]: https://github.com/Azure/azure-sdk-for-js/tree/master/sdk/identity/identity
[identity]: https://www.npmjs.com/package/@azure/identity
[token_credential]: https://github.com/Azure/azure-sdk-for-js/blob/main/sdk/identity/identity/samples/AzureIdentityExamples.md#authenticating-with-a-pre-fetched-access-token
[defaultazurecredential]: https://github.com/Azure/azure-sdk-for-js/tree/master/sdk/identity/identity#defaultazurecredential
[credential]: https://github.com/Azure/azure-sdk-for-js/tree/main/sdk/identity/identity#credentials

Просмотреть файл

@ -0,0 +1,18 @@
{
"$schema": "https://developer.microsoft.com/json-schemas/api-extractor/v7/api-extractor.schema.json",
"mainEntryPointFilePath": "./types/src/index.d.ts",
"docModel": { "enabled": true },
"apiReport": { "enabled": true, "reportFolder": "./review" },
"dtsRollup": {
"enabled": true,
"untrimmedFilePath": "",
"publicTrimmedFilePath": "./types/health-insights-radiologyinsights-rest.d.ts"
},
"messages": {
"tsdocMessageReporting": { "default": { "logLevel": "none" } },
"extractorMessageReporting": {
"ae-missing-release-tag": { "logLevel": "none" },
"ae-unresolved-link": { "logLevel": "none" }
}
}
}

Просмотреть файл

@ -0,0 +1,6 @@
{
"AssetsRepo": "Azure/azure-sdk-assets",
"AssetsRepoPrefixPath": "js",
"TagPrefix": "js/healthinsights/health-insights-radiologyinsights-rest",
"Tag": "js/healthinsights/health-insights-radiologyinsights-rest_01fb35ae43"
}

Просмотреть файл

@ -0,0 +1,130 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
// https://github.com/karma-runner/karma-chrome-launcher
process.env.CHROME_BIN = require("puppeteer").executablePath();
require("dotenv").config();
const { relativeRecordingsPath } = require("@azure-tools/test-recorder");
process.env.RECORDINGS_RELATIVE_PATH = relativeRecordingsPath();
module.exports = function (config) {
config.set({
// base path that will be used to resolve all patterns (eg. files, exclude)
basePath: "./",
// frameworks to use
// available frameworks: https://npmjs.org/browse/keyword/karma-adapter
frameworks: ["source-map-support", "mocha"],
plugins: [
"karma-mocha",
"karma-mocha-reporter",
"karma-chrome-launcher",
"karma-firefox-launcher",
"karma-env-preprocessor",
"karma-coverage",
"karma-sourcemap-loader",
"karma-junit-reporter",
"karma-source-map-support",
],
// list of files / patterns to load in the browser
files: [
"dist-test/index.browser.js",
{
pattern: "dist-test/index.browser.js.map",
type: "html",
included: false,
served: true,
},
],
// list of files / patterns to exclude
exclude: [],
// preprocess matching files before serving them to the browser
// available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
preprocessors: {
"**/*.js": ["sourcemap", "env"],
// IMPORTANT: COMMENT following line if you want to debug in your browsers!!
// Preprocess source file to calculate code coverage, however this will make source file unreadable
// "dist-test/index.js": ["coverage"]
},
envPreprocessor: [
"TEST_MODE",
"HEALTH_INSIGHTS_ENDPOINT",
"HEALTH_INSIGHTS_KEY",
"RECORDINGS_RELATIVE_PATH",
],
// test results reporter to use
// possible values: 'dots', 'progress'
// available reporters: https://npmjs.org/browse/keyword/karma-reporter
reporters: ["mocha", "coverage", "junit"],
coverageReporter: {
// specify a common output directory
dir: "coverage-browser/",
reporters: [
{ type: "json", subdir: ".", file: "coverage.json" },
{ type: "lcovonly", subdir: ".", file: "lcov.info" },
{ type: "html", subdir: "html" },
{ type: "cobertura", subdir: ".", file: "cobertura-coverage.xml" },
],
},
junitReporter: {
outputDir: "", // results will be saved as $outputDir/$browserName.xml
outputFile: "test-results.browser.xml", // if included, results will be saved as $outputDir/$browserName/$outputFile
suite: "", // suite will become the package name attribute in xml testsuite element
useBrowserName: false, // add browser name to report and classes names
nameFormatter: undefined, // function (browser, result) to customize the name attribute in xml testcase element
classNameFormatter: undefined, // function (browser, result) to customize the classname attribute in xml testcase element
properties: {}, // key value pair of properties to add to the <properties> section of the report
},
// web server port
port: 9876,
// enable / disable colors in the output (reporters and logs)
colors: true,
// level of logging
// possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
logLevel: config.LOG_INFO,
// enable / disable watching file and executing tests whenever any file changes
autoWatch: false,
// --no-sandbox allows our tests to run in Linux without having to change the system.
// --disable-web-security allows us to authenticate from the browser without having to write tests using interactive auth, which would be far more complex.
browsers: ["ChromeHeadlessNoSandbox"],
customLaunchers: {
ChromeHeadlessNoSandbox: {
base: "ChromeHeadless",
flags: ["--no-sandbox", "--disable-web-security"],
},
},
// Continuous Integration mode
// if true, Karma captures browsers, runs the tests and exits
singleRun: false,
// Concurrency level
// how many browser should be started simultaneous
concurrency: 1,
browserNoActivityTimeout: 60000000,
browserDisconnectTimeout: 10000,
browserDisconnectTolerance: 3,
client: {
mocha: {
// change Karma's debug.html to the mocha web reporter
reporter: "html",
timeout: "600000",
},
},
});
};

Просмотреть файл

@ -0,0 +1,125 @@
{
"name": "@azure-rest/health-insights-radiologyinsights",
"sdk-type": "client",
"author": "Microsoft Corporation",
"version": "1.0.0-beta.1",
"description": "A generated SDK for Health Insights Radiology Insights Rest",
"keywords": [
"node",
"azure",
"cloud",
"typescript",
"browser",
"isomorphic"
],
"license": "MIT",
"main": "dist/index.js",
"module": "./dist-esm/src/index.js",
"types": "./types/health-insights-radiologyinsights-rest.d.ts",
"repository": "github:Azure/azure-sdk-for-js",
"bugs": {
"url": "https://github.com/Azure/azure-sdk-for-js/issues"
},
"files": [
"dist/",
"dist-esm/src/",
"types/health-insights-radiologyinsights.d.ts",
"README.md",
"LICENSE",
"review/*"
],
"engines": {
"node": ">=18.0.0"
},
"scripts": {
"build:browser": "tsc -p . && cross-env ONLY_BROWSER=true rollup -c 2>&1",
"build:node": "tsc -p . && cross-env ONLY_NODE=true rollup -c 2>&1",
"build:samples": "echo skipped.",
"build:test": "tsc -p . && dev-tool run bundle",
"build:debug": "tsc -p . && dev-tool run bundle && api-extractor run --local",
"check-format": "dev-tool run vendored prettier --list-different --config ../../../.prettierrc.json --ignore-path ../../../.prettierignore \"src/**/*.ts\" \"*.{js,json}\" \"test/**/*.ts\"",
"clean": "rimraf --glob dist dist-browser dist-esm test-dist temp types *.tgz *.log",
"execute:samples": "echo skipped",
"extract-api": "rimraf review && mkdirp ./review && api-extractor run --local",
"format": "dev-tool run vendored prettier --write --config ../../../.prettierrc.json --ignore-path ../../../.prettierignore \"src/**/*.ts\" \"*.{js,json}\" \"test/**/*.ts\"",
"generate:client": "echo skipped",
"integration-test:browser": "dev-tool run test:browser",
"integration-test:node": "dev-tool run test:node-js-input -- --timeout 5000000 'dist-esm/test/**/*.spec.js'",
"integration-test": "npm run integration-test:node && npm run integration-test:browser",
"lint:fix": "eslint package.json api-extractor.json src test --ext .ts --fix --fix-type [problem,suggestion]",
"lint": "eslint package.json api-extractor.json src test --ext .ts",
"pack": "npm pack 2>&1",
"test:browser": "npm run clean && npm run build:test && npm run unit-test:browser",
"test:node": "npm run clean && npm run build:test && npm run unit-test:node",
"test": "npm run clean && npm run build:test && npm run unit-test",
"unit-test": "npm run unit-test:node && npm run unit-test:browser",
"unit-test:node": "dev-tool run test:node-ts-input -- --timeout 1200000 --exclude 'test/**/browser/*.spec.ts' 'test/**/*.spec.ts'",
"unit-test:browser": "dev-tool run test:browser",
"build": "npm run clean && tsc -p . && dev-tool run bundle && mkdirp ./review && api-extractor run --local"
},
"sideEffects": false,
"autoPublish": false,
"dependencies": {
"@azure/core-auth": "^1.6.0",
"@azure-rest/core-client": "^1.2.0",
"@azure/core-rest-pipeline": "^1.14.0",
"@azure/logger": "^1.0.0",
"tslib": "^2.2.0",
"@azure/core-lro": "^2.5.4",
"@azure/abort-controller": "^1.0.0"
},
"devDependencies": {
"@microsoft/api-extractor": "^7.31.1",
"autorest": "latest",
"@types/node": "^18.0.0",
"dotenv": "^16.0.0",
"eslint": "^8.0.0",
"mkdirp": "^2.1.2",
"rimraf": "^5.0.0",
"source-map-support": "^0.5.9",
"typescript": "~5.3.3",
"@azure/dev-tool": "^1.0.0",
"@azure/eslint-plugin-azure-sdk": "^3.0.0",
"@azure-tools/test-credential": "^1.0.0",
"@azure/identity": "^4.0.1",
"@azure-tools/test-recorder": "^3.0.0",
"mocha": "^10.0.0",
"esm": "^3.2.18",
"@types/mocha": "^10.0.0",
"cross-env": "^7.0.2",
"@types/chai": "^4.2.8",
"chai": "^4.2.0",
"karma-chrome-launcher": "^3.0.0",
"karma-coverage": "^2.0.0",
"karma-env-preprocessor": "^0.1.1",
"karma-firefox-launcher": "^2.1.2",
"karma-junit-reporter": "^2.0.1",
"karma-mocha-reporter": "^2.2.5",
"karma-mocha": "^2.0.1",
"karma-source-map-support": "~1.4.0",
"karma-sourcemap-loader": "^0.4.0",
"karma": "^6.2.0",
"c8": "^8.0.0",
"ts-node": "^10.0.0"
},
"homepage": "https://github.com/Azure/azure-sdk-for-js/tree/main/sdk/healthinsights/health-insights-radiologyinsights-rest/README.md",
"//metadata": {
"constantPaths": [
{
"path": "src/azureHealthInsightsClient.ts",
"prefix": "userAgentInfo"
}
]
},
"browser": {
"./dist-esm/test/public/utils/env.js": "./dist-esm/test/public/utils/env.browser.js"
},
"//sampleConfiguration": {
"productName": "HealthInsightsRadiologyInsights",
"productSlugs": [
"azure"
],
"disableDocsMs": true,
"apiRefLink": "https://docs.microsoft.com/javascript/api"
}
}

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -0,0 +1,209 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
/**
* Displays the critical results of the Radiology Insights request.
*/
import { AzureKeyCredential } from "@azure/core-auth";
import * as dotenv from "dotenv";
import AzureHealthInsightsClient, {
CreateJobParameters,
getLongRunningPoller,
isUnexpected,
RadiologyInsightsResultOutput,
} from "../src";
dotenv.config();
// You will need to set this environment variables or edit the following values
const apiKey = process.env["AZURE_HEALTH_INSIGHTS_KEY"] || "";
const endpoint = process.env["AZURE_HEALTH_INSIGHTS_ENDPOINT"] || "";
/**
* Print the critical result inference
*/
function printResults(radiologyInsightsResult: RadiologyInsightsResultOutput): void {
if (radiologyInsightsResult.status === "succeeded") {
const results = radiologyInsightsResult.result;
if (results !== undefined) {
results.patientResults.forEach((patientResult: { inferences: any[]; }) => {
if (patientResult.inferences) {
patientResult.inferences.forEach((inference) => {
if (inference.kind === "criticalResult") {
if ("result" in inference) {
console.log("Critical Result Inference found: " + inference.result.description);
}
}
});
}
});
}
} else {
const error = radiologyInsightsResult.error;
if (error) {
console.log(error.code, ":", error.message);
}
}
}
// Create request body for radiology insights
function createRequestBody(): CreateJobParameters {
const codingData = {
system: "Http://hl7.org/fhir/ValueSet/cpt-all",
code: "USPELVIS",
display: "US PELVIS COMPLETE"
};
const code = {
coding: [codingData]
};
const patientInfo = {
sex: "female",
birthDate: new Date("1959-11-11T19:00:00+00:00"),
};
const encounterData = {
id: "encounterid1",
period: {
"start": "2021-8-28T00:00:00",
"end": "2021-8-28T00:00:00"
},
class: "inpatient"
};
const authorData = {
"id": "authorid1",
"name": "authorname1"
};
const orderedProceduresData = {
code: code,
description: "US PELVIS COMPLETE"
};
const administrativeMetadata = {
orderedProcedures: [orderedProceduresData],
encounterId: "encounterid1"
};
const content = {
sourceType: "inline",
value: "CLINICAL HISTORY: "
+ "\r\n20-year-old female presenting with abdominal pain. Surgical history significant for appendectomy."
+ "\r\n "
+ "\r\nCOMPARISON: "
+ "\r\nRight upper quadrant sonographic performed 1 day prior."
+ "\r\n "
+ "\r\nTECHNIQUE: "
+ "\r\nTransabdominal grayscale pelvic sonography with duplex color Doppler "
+ "\r\nand spectral waveform analysis of the ovaries."
+ "\r\n "
+ "\r\nFINDINGS: "
+ "\r\nThe uterus is unremarkable given the transabdominal technique with "
+ "\r\nendometrial echo complex within physiologic normal limits. The "
+ "\r\novaries are symmetric in size, measuring 2.5 x 1.2 x 3.0 cm and the "
+ "\r\nleft measuring 2.8 x 1.5 x 1.9 cm.\n \r\nOn duplex imaging, Doppler signal is symmetric."
+ "\r\n "
+ "\r\nIMPRESSION: "
+ "\r\n1. Normal pelvic sonography. Findings of testicular torsion."
+ "\r\n\nA new US pelvis within the next 6 months is recommended."
+ "\n\nThese results have been discussed with Dr. Jones at 3 PM on November 5 2020.\n "
+ "\r\n"
};
const patientDocumentData = {
type: "note",
clinicalType: "radiologyReport",
id: "docid1",
language: "en",
authors: [authorData],
specialtyType: "radiology",
administrativeMetadata: administrativeMetadata,
content: content,
createdDateTime: new Date("2021-06-01T00:00:00.000"),
orderedProceduresAsCsv: "US PELVIS COMPLETE"
};
const patientData = {
id: "Samantha Jones",
info: patientInfo,
encounters: [encounterData],
patientDocuments: [patientDocumentData]
};
const inferenceTypes = [
"finding",
"ageMismatch",
"lateralityDiscrepancy",
"sexMismatch",
"completeOrderDiscrepancy",
"limitedOrderDiscrepancy",
"criticalResult",
"criticalRecommendation",
"followupRecommendation",
"followupCommunication",
"radiologyProcedure"];
const followupRecommendationOptions = {
includeRecommendationsWithNoSpecifiedModality: true,
includeRecommendationsInReferences: true,
provideFocusedSentenceEvidence: true
};
const findingOptions = {
provideFocusedSentenceEvidence: true
};
const inferenceOptions = {
followupRecommendationOptions: followupRecommendationOptions,
findingOptions: findingOptions
};
// Create RI Configuration
const configuration = {
inferenceOptions: inferenceOptions,
inferenceTypes: inferenceTypes,
locale: "en-US",
verbose: false,
includeEvidence: true
};
// create RI Data
const radiologyInsightsData = {
patients: [patientData],
configuration: configuration
};
return {
body: radiologyInsightsData
}
}
export async function main() {
const credential = new AzureKeyCredential(apiKey);
const client = AzureHealthInsightsClient(endpoint, credential);
// Create request body
const radiologyInsightsParameter = createRequestBody();
// Initiate radiology insights job and retrieve results
const initialResponse = await client.path("/radiology-insights/jobs").post(radiologyInsightsParameter);
if (isUnexpected(initialResponse)) {
throw initialResponse;
}
const poller = await getLongRunningPoller(client, initialResponse);
const RadiologyInsightsResult = await poller.pollUntilDone();
if (isUnexpected(RadiologyInsightsResult)) {
throw RadiologyInsightsResult;
}
const resultBody = RadiologyInsightsResult.body;
printResults(resultBody);
}
main().catch((err) => {
console.error("The critical result encountered an error:", err);
});

Просмотреть файл

@ -0,0 +1,50 @@
# HealthInsightsRadiologyInsights samples for JavaScript (Beta)
These sample programs show how to use the JavaScript client libraries for HealthInsightsRadiologyInsights in some common scenarios.
| **File Name** | **Description** |
| --------------------------------------------------------------------------------------------------- | ------------------------- |
| [sample_critical_result_inference_async.js][sample_critical_result_inference_async] | Infer critical results from a radiology report (async) |
## Prerequisites
The sample programs are compatible with [LTS versions of Node.js](https://github.com/nodejs/release#release-schedule).
You need [an Azure subscription][freesub] to run these sample programs.
Samples retrieve credentials to access the service endpoint from environment variables. Alternatively, edit the source code to include the appropriate credentials. See each individual sample for details on which environment variables/credentials it requires to function.
Adapting the samples to run in the browser may require some additional consideration. For details, please see the [package README][package].
## Setup
To run the samples using the published version of the package:
1. Install the dependencies using `npm`:
```bash
npm install
```
2. Edit the file `sample.env`, adding the correct credentials to access the Azure service and run the samples. Then rename the file from `sample.env` to just `.env`. The sample programs will read this file automatically.
3. Run whichever samples you like (note that some samples may require additional setup, see the table above):
```bash
node sample_critical_result_inference_async.js
```
Alternatively, run a single sample with the correct environment variables set (setting up the `.env` file is not required if you do this), for example (cross-platform):
```bash
npx cross-env AZURE_HEALTH_INSIGHTS_KEY="<health insights key>" AZURE_HEALTH_INSIGHTS_ENDPOINT="<health insights endpoint>" node sample_critical_result_inference_async.js
```
## Next Steps
Take a look at our [API Documentation][apiref] for more information about the APIs that are available in the clients.
[sample_critical_result_inference_async]: https://github.com/Azure/azure-sdk-for-js/blob/main/sdk/healthinsights/health-insights-radiologyinsights-rest/samples/v1-beta/javascript/sample_critical_result_inference_async.js
[apiref]: https://docs.microsoft.com/javascript/api
[freesub]: https://azure.microsoft.com/free/
[package]: https://github.com/Azure/azure-sdk-for-js/tree/main/sdk/healthinsights/health-insights-radiologyinsights-rest/README.md

Просмотреть файл

@ -0,0 +1,33 @@
{
"name": "@azure-samples/health-insights-radiologyinsights-js-beta",
"private": true,
"version": "1.0.0",
"description": "HealthInsightsRadiologyInsights samples for JavaScript (Beta)",
"engines": {
"node": ">=18.0.0"
},
"repository": {
"type": "git",
"url": "git+https://github.com/Azure/azure-sdk-for-js.git",
"directory": "sdk/healthinsights/health-insights-radiologyinsights-rest"
},
"keywords": [
"node",
"azure",
"cloud",
"typescript",
"browser",
"isomorphic"
],
"author": "Microsoft Corporation",
"license": "MIT",
"bugs": {
"url": "https://github.com/Azure/azure-sdk-for-js/issues"
},
"homepage": "https://github.com/Azure/azure-sdk-for-js/tree/main/sdk/healthinsights/health-insights-radiologyinsights-rest",
"dependencies": {
"@azure-rest/health-insights-radiologyinsights": "latest",
"dotenv": "latest",
"@azure/core-auth": "^1.3.0"
}
}

Просмотреть файл

@ -0,0 +1,3 @@
# App registration secret for AAD authentication
AZURE_HEALTH_INSIGHTS_KEY=
AZURE_HEALTH_INSIGHTS_ENDPOINT=

Просмотреть файл

@ -0,0 +1,215 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
/**
* Displays the critical results of the Radiology Insights request.
*/
const dotenv = require("dotenv");
const AzureHealthInsightsClient = require("@azure-rest/health-insights-radiologyinsights").default,
{ getLongRunningPoller, isUnexpected } = require("@azure-rest/health-insights-radiologyinsights");
const { AzureKeyCredential } = require("@azure/core-auth");
dotenv.config();
// You will need to set this environment variables or edit the following values
const apiKey = process.env["AZURE_HEALTH_INSIGHTS_KEY"] || "";
const endpoint = process.env["AZURE_HEALTH_INSIGHTS_ENDPOINT"] || "";
/**
* Print the critical result inference
*/
function printResults(radiologyInsightsResult) {
if (radiologyInsightsResult.status === "succeeded") {
const results = radiologyInsightsResult.result;
if (results !== undefined) {
results.patientResults.forEach((patientResult) => {
if (patientResult.inferences) {
patientResult.inferences.forEach((inference) => {
if (inference.kind === "criticalResult") {
if ("result" in inference) {
console.log("Critical Result Inference found: " + inference.result.description);
}
}
});
}
});
}
} else {
const errors = radiologyInsightsResult.errors;
if (errors) {
for (const error of errors) {
console.log(error.code, ":", error.message);
}
}
}
}
// Create request body for radiology insights
function createRequestBody() {
const codingData = {
system: "Http://hl7.org/fhir/ValueSet/cpt-all",
code: "USPELVIS",
display: "US PELVIS COMPLETE"
};
const code = {
coding: [codingData]
};
const patientInfo = {
sex: "female",
birthDate: new Date("1959-11-11T19:00:00+00:00"),
};
const encounterData = {
id: "encounterid1",
period: {
"start": "2021-8-28T00:00:00",
"end": "2021-8-28T00:00:00"
},
class: "inpatient"
};
const authorData = {
"id": "authorid1",
"name": "authorname1"
};
const orderedProceduresData = {
code: code,
description: "US PELVIS COMPLETE"
};
const administrativeMetadata = {
orderedProcedures: [orderedProceduresData],
encounterId: "encounterid1"
};
const content = {
sourceType: "inline",
value: "CLINICAL HISTORY: "
+ "\r\n20-year-old female presenting with abdominal pain. Surgical history significant for appendectomy."
+ "\r\n "
+ "\r\nCOMPARISON: "
+ "\r\nRight upper quadrant sonographic performed 1 day prior."
+ "\r\n "
+ "\r\nTECHNIQUE: "
+ "\r\nTransabdominal grayscale pelvic sonography with duplex color Doppler "
+ "\r\nand spectral waveform analysis of the ovaries."
+ "\r\n "
+ "\r\nFINDINGS: "
+ "\r\nThe uterus is unremarkable given the transabdominal technique with "
+ "\r\nendometrial echo complex within physiologic normal limits. The "
+ "\r\novaries are symmetric in size, measuring 2.5 x 1.2 x 3.0 cm and the "
+ "\r\nleft measuring 2.8 x 1.5 x 1.9 cm.\n \r\nOn duplex imaging, Doppler signal is symmetric."
+ "\r\n "
+ "\r\nIMPRESSION: "
+ "\r\n1. Normal pelvic sonography. Findings of testicular torsion."
+ "\r\n\nA new US pelvis within the next 6 months is recommended."
+ "\n\nThese results have been discussed with Dr. Jones at 3 PM on November 5 2020.\n "
+ "\r\n"
};
const patientDocumentData = {
type: "note",
clinicalType: "radiologyReport",
id: "docid1",
language: "en",
authors: [authorData],
specialtyType: "radiology",
administrativeMetadata: administrativeMetadata,
content: content,
createdDateTime: new Date("2021-06-01T00:00:00.000"),
orderedProceduresAsCsv: "US PELVIS COMPLETE"
};
const patientData = {
id: "Samantha Jones",
info: patientInfo,
encounters: [encounterData],
patientDocuments: [patientDocumentData]
};
const inferenceTypes = [
"finding",
"ageMismatch",
"lateralityDiscrepancy",
"sexMismatch",
"completeOrderDiscrepancy",
"limitedOrderDiscrepancy",
"criticalResult",
"criticalRecommendation",
"followupRecommendation",
"followupCommunication",
"radiologyProcedure"];
const followupRecommendationOptions = {
includeRecommendationsWithNoSpecifiedModality: true,
includeRecommendationsInReferences: true,
provideFocusedSentenceEvidence: true
};
const findingOptions = {
provideFocusedSentenceEvidence: true
};
const inferenceOptions = {
followupRecommendationOptions: followupRecommendationOptions,
findingOptions: findingOptions
};
// Create RI Configuration
const configuration = {
inferenceOptions: inferenceOptions,
inferenceTypes: inferenceTypes,
locale: "en-US",
verbose: false,
includeEvidence: true
};
// create RI Data
const radiologyInsightsData = {
patients: [patientData],
configuration: configuration
};
const radiologyInsightsParameter = {
body: radiologyInsightsData
};
return {
body: radiologyInsightsData
}
}
async function main() {
const credential = new AzureKeyCredential(apiKey);
const client = new AzureHealthInsightsClient(endpoint, credential);
// Create request body
const radiologyInsightsParameter = createRequestBody();
// Initiate radiology insights job and retrieve results
const initialResponse = await client.path("/radiology-insights/jobs").post(radiologyInsightsParameter);
if (isUnexpected(initialResponse)) {
throw initialResponse;
}
const poller = await getLongRunningPoller(client, initialResponse);
const RadiologyInsightsResult = await poller.pollUntilDone();
if (isUnexpected(RadiologyInsightsResult)) {
throw RadiologyInsightsResult;
}
const resultBody = RadiologyInsightsResult.body;
printResults(resultBody);
}
main().catch((err) => {
console.error("The critical result encountered an error:", err);
});
module.exports = { main };

Просмотреть файл

@ -0,0 +1,63 @@
# HealthInsightsRadiologyInsights client library samples for TypeScript (Beta)
These sample programs show how to use the TypeScript client libraries for HealthInsightsRadiologyInsights in some common scenarios.
| **File Name** | **Description** |
| --------------------------------------------------------------------------------------------------- | ------------------------- |
| [sample_critical_result_inference_async.js][sample_critical_result_inference_async] | Infer critical results from a radiology report (async) |
## Prerequisites
The sample programs are compatible with [LTS versions of Node.js](https://github.com/nodejs/release#release-schedule).
Before running the samples in Node, they must be compiled to JavaScript using the TypeScript compiler. For more information on TypeScript, see the [TypeScript documentation][typescript]. Install the TypeScript compiler using:
```bash
npm install -g typescript
```
You need [an Azure subscription][freesub] to run these sample programs.
Samples retrieve credentials to access the service endpoint from environment variables. Alternatively, edit the source code to include the appropriate credentials. See each individual sample for details on which environment variables/credentials it requires to function.
Adapting the samples to run in the browser may require some additional consideration. For details, please see the [package README][package].
## Setup
To run the samples using the published version of the package:
1. Install the dependencies using `npm`:
```bash
npm install
```
2. Compile the samples:
```bash
npm run build
```
3. Edit the file `sample.env`, adding the correct credentials to access the Azure service and run the samples. Then rename the file from `sample.env` to just `.env`. The sample programs will read this file automatically.
4. Run whichever samples you like (note that some samples may require additional setup, see the table above):
```bash
node dist/sample_critical_result_inference_async.js
```
Alternatively, run a single sample with the correct environment variables set (setting up the `.env` file is not required if you do this), for example (cross-platform):
```bash
npx cross-env HEALTH_INSIGHTS_API_KEY="<health insights api key>" HEALTH_INSIGHTS_ENDPOINT="<health insights endpoint>" node dist/sample_critical_result_inference_async.js
```
## Next Steps
Take a look at our [API Documentation][apiref] for more information about the APIs that are available in the clients.
[sample_critical_result_inference_async]: https://github.com/Azure/azure-sdk-for-js/blob/main/sdk/healthinsights/health-insights-radiologyinsights-rest/samples/v1-beta/typescript/src/sample_critical_result_inference_async.ts
[apiref]: https://docs.microsoft.com/javascript/api
[freesub]: https://azure.microsoft.com/free/
[package]: https://github.com/Azure/azure-sdk-for-js/tree/main/sdk/healthinsights/health-insights-clinicalmatching-rest/README.md
[typescript]: https://www.typescriptlang.org/docs/home.html

Просмотреть файл

@ -0,0 +1,42 @@
{
"name": "@azure-samples/health-insights-radiologyinsights-ts-beta",
"private": true,
"version": "1.0.0",
"description": "HealthInsightsradiologyinsights client library samples for TypeScript (Beta)",
"engines": {
"node": ">=18.0.0"
},
"scripts": {
"build": "tsc",
"prebuild": "rimraf dist/"
},
"repository": {
"type": "git",
"url": "git+https://github.com/Azure/azure-sdk-for-js.git",
"directory": "sdk/healthinsights/health-insights-radiologyinsights-rest"
},
"keywords": [
"node",
"azure",
"cloud",
"typescript",
"browser",
"isomorphic"
],
"author": "Microsoft Corporation",
"license": "MIT",
"bugs": {
"url": "https://github.com/Azure/azure-sdk-for-js/issues"
},
"homepage": "https://github.com/Azure/azure-sdk-for-js/tree/main/sdk/healthinsights/health-insights-radiologyinsights-rest",
"dependencies": {
"@azure-rest/health-insights-radiologyinsights": "latest",
"@azure/core-auth": "^1.3.0",
"dotenv": "latest"
},
"devDependencies": {
"@types/node": "^18.0.0",
"rimraf": "latest",
"typescript": "~5.3.3"
}
}

Просмотреть файл

@ -0,0 +1,3 @@
# App registration secret for AAD authentication
HEALTH_INSIGHTS_API_KEY=
HEALTH_INSIGHTS_ENDPOINT=

Просмотреть файл

@ -0,0 +1,211 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
/**
* Displays the critical results of the Radiology Insights request.
*/
import { AzureKeyCredential } from "@azure/core-auth";
import * as dotenv from "dotenv";
import AzureHealthInsightsClient, {
CreateJobParameters,
getLongRunningPoller,
isUnexpected,
RadiologyInsightsResultOutput,
} from "@azure-rest/health-insights-radiologyinsights";
dotenv.config();
// You will need to set this environment variables or edit the following values
const apiKey = process.env["AZURE_HEALTH_INSIGHTS_KEY"] || "";
const endpoint = process.env["AZURE_HEALTH_INSIGHTS_ENDPOINT"] || "";
/**
* Print the critical result inference
*/
function printResults(radiologyInsightsResult: RadiologyInsightsResultOutput): void {
if (radiologyInsightsResult.status === "succeeded") {
const results = radiologyInsightsResult.result;
if (results !== undefined) {
results.patientResults.forEach((patientResult: { inferences: any[]; }) => {
if (patientResult.inferences) {
patientResult.inferences.forEach((inference) => {
if (inference.kind === "criticalResult") {
if ("result" in inference) {
console.log("Critical Result Inference found: " + inference.result.description);
}
}
});
}
});
}
} else {
const error = radiologyInsightsResult.error;
if (error) {
console.log(error.code, ":", error.message);
}
}
}
// Create request body for radiology insights
function createRequestBody(): CreateJobParameters {
const codingData = {
system: "Http://hl7.org/fhir/ValueSet/cpt-all",
code: "USPELVIS",
display: "US PELVIS COMPLETE"
};
const code = {
coding: [codingData]
};
const patientInfo = {
sex: "female",
birthDate: new Date("1959-11-11T19:00:00+00:00"),
};
const encounterData = {
id: "encounterid1",
period: {
"start": "2021-8-28T00:00:00",
"end": "2021-8-28T00:00:00"
},
class: "inpatient"
};
const authorData = {
"id": "authorid1",
"name": "authorname1"
};
const orderedProceduresData = {
code: code,
description: "US PELVIS COMPLETE"
};
const administrativeMetadata = {
orderedProcedures: [orderedProceduresData],
encounterId: "encounterid1"
};
const content = {
sourceType: "inline",
value: "CLINICAL HISTORY: "
+ "\r\n20-year-old female presenting with abdominal pain. Surgical history significant for appendectomy."
+ "\r\n "
+ "\r\nCOMPARISON: "
+ "\r\nRight upper quadrant sonographic performed 1 day prior."
+ "\r\n "
+ "\r\nTECHNIQUE: "
+ "\r\nTransabdominal grayscale pelvic sonography with duplex color Doppler "
+ "\r\nand spectral waveform analysis of the ovaries."
+ "\r\n "
+ "\r\nFINDINGS: "
+ "\r\nThe uterus is unremarkable given the transabdominal technique with "
+ "\r\nendometrial echo complex within physiologic normal limits. The "
+ "\r\novaries are symmetric in size, measuring 2.5 x 1.2 x 3.0 cm and the "
+ "\r\nleft measuring 2.8 x 1.5 x 1.9 cm.\n \r\nOn duplex imaging, Doppler signal is symmetric."
+ "\r\n "
+ "\r\nIMPRESSION: "
+ "\r\n1. Normal pelvic sonography. Findings of testicular torsion."
+ "\r\n\nA new US pelvis within the next 6 months is recommended."
+ "\n\nThese results have been discussed with Dr. Jones at 3 PM on November 5 2020.\n "
+ "\r\n"
};
const patientDocumentData = {
type: "note",
clinicalType: "radiologyReport",
id: "docid1",
language: "en",
authors: [authorData],
specialtyType: "radiology",
administrativeMetadata: administrativeMetadata,
content: content,
createdDateTime: new Date("2021-06-01T00:00:00.000"),
orderedProceduresAsCsv: "US PELVIS COMPLETE"
};
const patientData = {
id: "Samantha Jones",
info: patientInfo,
encounters: [encounterData],
patientDocuments: [patientDocumentData]
};
const inferenceTypes = [
"finding",
"ageMismatch",
"lateralityDiscrepancy",
"sexMismatch",
"completeOrderDiscrepancy",
"limitedOrderDiscrepancy",
"criticalResult",
"criticalRecommendation",
"followupRecommendation",
"followupCommunication",
"radiologyProcedure"];
const followupRecommendationOptions = {
includeRecommendationsWithNoSpecifiedModality: true,
includeRecommendationsInReferences: true,
provideFocusedSentenceEvidence: true
};
const findingOptions = {
provideFocusedSentenceEvidence: true
};
const inferenceOptions = {
followupRecommendationOptions: followupRecommendationOptions,
findingOptions: findingOptions
};
// Create RI Configuration
const configuration = {
inferenceOptions: inferenceOptions,
inferenceTypes: inferenceTypes,
locale: "en-US",
verbose: false,
includeEvidence: true
};
// create RI Data
const radiologyInsightsData = {
patients: [patientData],
configuration: configuration
};
return {
body: radiologyInsightsData
}
}
export async function main() {
const credential = new AzureKeyCredential(apiKey);
const client = AzureHealthInsightsClient(endpoint, credential);
// Create request body
const radiologyInsightsParameter = createRequestBody();
// Initiate radiology insights job and retrieve results
const initialResponse = await client.path("/radiology-insights/jobs").post(radiologyInsightsParameter);
if (isUnexpected(initialResponse)) {
throw initialResponse;
}
const poller = await getLongRunningPoller(client, initialResponse);
const RadiologyInsightsResult = await poller.pollUntilDone();
if (isUnexpected(RadiologyInsightsResult)) {
throw RadiologyInsightsResult;
}
const resultBody = RadiologyInsightsResult.body;
printResults(resultBody);
}
main().catch((err) => {
console.error("The critical result encountered an error:", err);
});

Просмотреть файл

@ -0,0 +1,17 @@
{
"compilerOptions": {
"target": "ES2020",
"module": "commonjs",
"moduleResolution": "node",
"resolveJsonModule": true,
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"strict": true,
"alwaysStrict": true,
"outDir": "dist",
"rootDir": "src"
},
"include": [
"src/**.ts"
]
}

Просмотреть файл

@ -0,0 +1,41 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
import { getClient, ClientOptions } from "@azure-rest/core-client";
import { logger } from "./logger";
import { KeyCredential } from "@azure/core-auth";
import { AzureHealthInsightsClient } from "./clientDefinitions";
/**
* Initialize a new instance of `AzureHealthInsightsClient`
* @param endpoint - Supported Cognitive Services endpoints (protocol and hostname, for example: https://westus2.api.cognitive.microsoft.com).
* @param credentials - uniquely identify client credential
* @param options - the parameter for all optional parameters
*/
export default function createClient(
endpoint: string,
credentials: KeyCredential,
options: ClientOptions = {},
): AzureHealthInsightsClient {
const baseUrl = options.baseUrl ?? `${endpoint}/health-insights`;
options.apiVersion = options.apiVersion ?? "2023-09-01-preview";
const userAgentInfo = `azsdk-js-health-insights-radiologyinsights-rest/1.0.0-beta.1`;
const userAgentPrefix =
options.userAgentOptions && options.userAgentOptions.userAgentPrefix
? `${options.userAgentOptions.userAgentPrefix} ${userAgentInfo}`
: `${userAgentInfo}`;
options = {
...options,
userAgentOptions: {
userAgentPrefix,
},
loggingOptions: {
logger: options.loggingOptions?.logger ?? logger.info,
},
credentials: {
apiKeyHeaderName: options.credentials?.apiKeyHeaderName ?? "Ocp-Apim-Subscription-Key",
},
};
return getClient(baseUrl, credentials, options) as AzureHealthInsightsClient;
}

Просмотреть файл

@ -0,0 +1,34 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
import { GetJobParameters, CreateJobParameters } from "./parameters";
import {
GetJob200Response,
GetJobDefaultResponse,
CreateJob202Response,
CreateJobDefaultResponse,
} from "./responses";
import { Client, StreamableMethod } from "@azure-rest/core-client";
export interface GetJob {
/** Gets the status and details of the Radiology Insights job. */
get(options?: GetJobParameters): StreamableMethod<GetJob200Response | GetJobDefaultResponse>;
}
export interface CreateJob {
/** Creates a Radiology Insights job with the given request body. */
post(
options?: CreateJobParameters,
): StreamableMethod<CreateJob202Response | CreateJobDefaultResponse>;
}
export interface Routes {
/** Resource for '/radiology-insights/jobs/\{id\}' has methods for the following verbs: get */
(path: "/radiology-insights/jobs/{id}", id: string): GetJob;
/** Resource for '/radiology-insights/jobs' has methods for the following verbs: post */
(path: "/radiology-insights/jobs"): CreateJob;
}
export type AzureHealthInsightsClient = Client & {
path: Routes;
};

Просмотреть файл

@ -0,0 +1,15 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
import AzureHealthInsightsClient from "./azureHealthInsightsClient";
export * from "./azureHealthInsightsClient";
export * from "./parameters";
export * from "./responses";
export * from "./clientDefinitions";
export * from "./isUnexpected";
export * from "./models";
export * from "./outputModels";
export * from "./pollingHelper";
export default AzureHealthInsightsClient;

Просмотреть файл

@ -0,0 +1,106 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
import {
GetJob200Response,
GetJobDefaultResponse,
CreateJob202Response,
CreateJobLogicalResponse,
CreateJobDefaultResponse,
} from "./responses";
const responseMap: Record<string, string[]> = {
"GET /radiology-insights/jobs/{id}": ["200"],
"POST /radiology-insights/jobs": ["202"],
"GET /radiology-insights/jobs": ["200", "202"],
};
export function isUnexpected(
response: GetJob200Response | GetJobDefaultResponse,
): response is GetJobDefaultResponse;
export function isUnexpected(
response: CreateJob202Response | CreateJobLogicalResponse | CreateJobDefaultResponse,
): response is CreateJobDefaultResponse;
export function isUnexpected(
response:
| GetJob200Response
| GetJobDefaultResponse
| CreateJob202Response
| CreateJobLogicalResponse
| CreateJobDefaultResponse,
): response is GetJobDefaultResponse | CreateJobDefaultResponse {
const lroOriginal = response.headers["x-ms-original-url"];
const url = new URL(lroOriginal ?? response.request.url);
const method = response.request.method;
let pathDetails = responseMap[`${method} ${url.pathname}`];
if (!pathDetails) {
pathDetails = getParametrizedPathSuccess(method, url.pathname);
}
return !pathDetails.includes(response.status);
}
function getParametrizedPathSuccess(method: string, path: string): string[] {
const pathParts = path.split("/");
// Traverse list to match the longest candidate
// matchedLen: the length of candidate path
// matchedValue: the matched status code array
let matchedLen = -1,
matchedValue: string[] = [];
// Iterate the responseMap to find a match
for (const [key, value] of Object.entries(responseMap)) {
// Extracting the path from the map key which is in format
// GET /path/foo
if (!key.startsWith(method)) {
continue;
}
const candidatePath = getPathFromMapKey(key);
// Get each part of the url path
const candidateParts = candidatePath.split("/");
// track if we have found a match to return the values found.
let found = true;
for (let i = candidateParts.length - 1, j = pathParts.length - 1; i >= 1 && j >= 1; i--, j--) {
if (candidateParts[i]?.startsWith("{") && candidateParts[i]?.indexOf("}") !== -1) {
const start = candidateParts[i]!.indexOf("}") + 1,
end = candidateParts[i]?.length;
// If the current part of the candidate is a "template" part
// Try to use the suffix of pattern to match the path
// {guid} ==> $
// {guid}:export ==> :export$
const isMatched = new RegExp(`${candidateParts[i]?.slice(start, end)}`).test(
pathParts[j] || "",
);
if (!isMatched) {
found = false;
break;
}
continue;
}
// If the candidate part is not a template and
// the parts don't match mark the candidate as not found
// to move on with the next candidate path.
if (candidateParts[i] !== pathParts[j]) {
found = false;
break;
}
}
// We finished evaluating the current candidate parts
// Update the matched value if and only if we found the longer pattern
if (found && candidatePath.length > matchedLen) {
matchedLen = candidatePath.length;
matchedValue = value;
}
}
return matchedValue;
}
function getPathFromMapKey(mapKey: string): string {
const pathStart = mapKey.indexOf("/");
return mapKey.slice(pathStart);
}

Просмотреть файл

@ -0,0 +1,5 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
import { createClientLogger } from "@azure/logger";
export const logger = createClientLogger("health-insights-radiologyinsights");

Просмотреть файл

@ -0,0 +1,715 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
/**
* Base for all elements
* Based on [FHIR Element](https://www.hl7.org/fhir/datatypes.html#Element)
*/
export interface Extension extends Element {
/** Source of the definition for the extension code - a logical name or a URL. */
url: string;
/** Value as Quantity */
valueQuantity?: Quantity;
/** Value as CodeableConcept */
valueCodeableConcept?: CodeableConcept;
/** Value as string */
valueString?: string;
/** Value as boolean */
valueBoolean?: boolean;
/** Value as integer */
valueInteger?: number;
/** Value as Range. */
valueRange?: Range;
/** Value as Ratio. */
valueRatio?: Ratio;
/** Value as SampledData. */
valueSampledData?: SampledData;
/** Value as time (hh:mm:ss) */
valueTime?: Date | string;
/** Value as dateTime. */
valueDateTime?: string;
/** Value as Period. */
valuePeriod?: Period;
/** Value as reference. */
valueReference?: Reference;
}
/**
* A measured or measurable amount
* Based on [FHIR Quantity](https://www.hl7.org/fhir/R4/datatypes.html#Quantity)
*/
export interface Quantity extends Element {
/** Numerical value (with implicit precision) */
value?: number;
/** \< | \<= | \>= | \> - how to understand the value */
comparator?: string;
/** Unit representation */
unit?: string;
/** System that defines coded unit form */
system?: string;
/** Coded form of the unit */
code?: string;
}
/**
* The base definition for all elements contained inside a resource.
* Based on [FHIR Element](https://www.hl7.org/fhir/R4/element.html)
*/
export interface Element {
/** Unique id for inter-element referencing */
id?: string;
/** Additional Content defined by implementations */
extension?: Array<Extension>;
}
/**
* Concept - reference to a terminology or just text
* Based on [FHIR CodeableConcept](https://www.hl7.org/fhir/R4/datatypes.html#CodeableConcept)
*/
export interface CodeableConcept extends Element {
/** Code defined by a terminology system */
coding?: Array<Coding>;
/** Plain text representation of the concept */
text?: string;
}
/**
* A Coding is a representation of a defined concept using a symbol from a defined "code system".
* Based on [FHIR Coding](https://www.hl7.org/fhir/R4/datatypes.html#Coding)
*/
export interface Coding extends Element {
/** Identity of the terminology system */
system?: string;
/** Version of the system - if relevant */
version?: string;
/** Symbol in syntax defined by the system */
code?: string;
/** Representation defined by the system */
display?: string;
}
/**
* A set of ordered Quantities defined by a low and high limit
* Based on [FHIR Range](https://www.hl7.org/fhir/R4/datatypes.html#Range)
*/
export interface Range extends Element {
/** Low limit */
low?: Quantity;
/** High limit */
high?: Quantity;
}
/**
* A ratio of two Quantity values - a numerator and a denominator
* Based on [FHIR Ratio](https://www.hl7.org/fhir/R4/datatypes.html#Ratio)
*/
export interface Ratio extends Element {
/** Numerator value */
numerator?: Quantity;
/** Denominator value */
denominator?: Quantity;
}
/**
* A series of measurements taken by a device
* Based on [FHIR SampledData](https://www.hl7.org/fhir/R4/datatypes.html#SampledData)
*/
export interface SampledData extends Element {
/** Zero value and units */
origin: Quantity;
/** Number of milliseconds between samples */
period: number;
/** Multiply data by this before adding to origin */
factor?: number;
/** Lower limit of detection */
lowerLimit?: number;
/** Upper limit of detection */
upperLimit?: number;
/** Number of sample points at each time point */
dimensions: number;
/** Decimal values with spaces, or "E" | "U" | "L" */
data?: string;
}
/**
* A time period defined by a start and end date and optionally time
* Based on [FHIR Period](https://www.hl7.org/fhir/R4/datatypes.html#Period)
*/
export interface Period extends Element {
/** Starting time with inclusive boundary */
start?: string;
/** End time with inclusive boundary, if not ongoing */
end?: string;
}
/**
* A reference from one resource to another
* Based on [FHIR Reference](https://www.hl7.org/fhir/R4/references.html)
*/
export interface Reference extends Element {
/** Literal reference, Relative, internal or absolute URL */
reference?: string;
/** Type the reference refers to (e.g. "Patient") */
type?: string;
/** Logical reference, when literal reference is not known */
identifier?: Identifier;
/** Text alternative for the resource */
display?: string;
}
/**
* An identifier intended for computation
* Based on [FHIR Identifier](https://www.hl7.org/fhir/R4/identifier.html)
*/
export interface Identifier extends Element {
/** usual | official | temp | secondary | old (If known) */
use?: string;
/** Description of identifier */
type?: CodeableConcept;
/** The namespace for the identifier value */
system?: string;
/** The value that is unique */
value?: string;
/** Time period when id is/was valid for use */
period?: Period;
/** Organization that issued id (may be just text) */
assigner?: Reference;
}
/**
* Any resource that is a [DomainResource](https://www.hl7.org/fhir/domainresource.html) may include a human-readable narrative that contains a summary of the resource and may be used to represent the content of the resource to a human.
* Based on [FHIR Narrative](https://www.hl7.org/fhir/R4/narrative.html#Narrative)
*/
export interface Narrative extends Element {
/** generated, extensions, additional, empty */
status: string;
/** xhtml */
div: string;
}
/**
* A text note which also contains information about who made the statement and when
* Based on [FHIR Annotation](https://www.hl7.org/fhir/R4/datatypes.html#Annotation)
*/
export interface Annotation extends Element {
/** Individual responsible for the annotation */
authorString?: string;
/** When the annotation was made */
time?: string;
/** The annotation - text content (as markdown) */
text: string;
}
/**
* Component results
* Based on [FHIR Observation.component](https://www.hl7.org/fhir/R4/observation.html)
*/
export interface ObservationComponent extends Element {
/** Type of component observation (code / type) */
code: CodeableConcept;
/** Value as Quantity */
valueQuantity?: Quantity;
/** Value as CodeableConcept */
valueCodeableConcept?: CodeableConcept;
/** Value as string */
valueString?: string;
/** Value as boolean */
valueBoolean?: boolean;
/** Value as integer */
valueInteger?: number;
/** Value as Range. */
valueRange?: Range;
/** Value as Ratio. */
valueRatio?: Ratio;
/** Value as SampledData. */
valueSampledData?: SampledData;
/** Value as time (hh:mm:ss) */
valueTime?: Date | string;
/** Value as dateTime. */
valueDateTime?: string;
/** Value as Period. */
valuePeriod?: Period;
/** Value as reference. */
valueReference?: Reference;
/** Why the component result is missing */
dataAbsentReason?: CodeableConcept;
/** High, low, normal, etc. */
interpretation?: Array<CodeableConcept>;
/** Provides guide for interpretation of component result */
referenceRange?: Array<ObservationReferenceRange>;
}
/**
* Provides guide for interpretation of component result
* Based on [FHIR Observation.referenceRange](https://www.hl7.org/fhir/R4/observation.html)
*/
export interface ObservationReferenceRange {
/** Low Range, if relevant */
low?: Quantity;
/** High Range, if relevant */
high?: Quantity;
/** Reference range qualifier */
type?: CodeableConcept;
/** Reference range population */
appliesTo?: Array<CodeableConcept>;
/** Applicable age range, if relevant */
age?: Range;
/** Text based reference range in an observation */
text?: string;
}
/** Contact details (See: https://www.hl7.org/fhir/R4/metadatatypes.html#ContactDetail) */
export interface ContactDetail extends Element {
/** Name of an individual to contact */
name?: string;
/** Contact details for individual or organization */
telecom?: Array<ContactPoint>;
}
/**
* Details for all kinds of technology mediated contact points for a person or organization, including telephone, email, etc.
* See https://www.hl7.org/fhir/R4/datatypes.html#ContactPoint
*/
export interface ContactPoint {
/**
* phone | fax | email | pager | url | sms | other
*
* Possible values: "phone", "fax", "email", "pager", "url", "sms", "other"
*/
system?: string;
/** The actual contact point details */
value?: string;
/**
* home | work | temp | old | mobile - purpose of this contact point
*
* Possible values: "home", "work", "temp", "old", "mobile"
*/
use?: string;
/** Specify preferred order of use (1 = highest) */
rank?: number;
/** Time period when the contact point was/is in use */
period?: Period;
}
/**
* Detailed information about observations
* Based on [FHIR Observation](https://www.hl7.org/fhir/R4/observation.html)
*/
export interface Observation extends DomainResourceParent {
/** resourceType */
resourceType: "Observation";
/** Business Identifier for observation */
identifier?: Array<Identifier>;
/**
* registered | preliminary | final | amended +
*
* Possible values: "registered", "preliminary", "final", "amended", "corrected", "cancelled", "entered-in-error", "unknown"
*/
status: string;
/** Classification of type of observation */
category?: Array<CodeableConcept>;
/** Type of observation (code / type) */
code: CodeableConcept;
/** Who and/or what the observation is about */
subject?: Reference;
/** Healthcare event during which this observation is made */
encounter?: Reference;
/** Clinically relevant time/time-period for observation */
effectiveDateTime?: string;
/** Clinically relevant time/time-period for observation */
effectivePeriod?: Period;
/** Clinically relevant time/time-period for observation */
effectiveInstant?: string;
/** Date/Time this version was made available */
issued?: string;
/** Actual result */
valueQuantity?: Quantity;
/** Actual result */
valueCodeableConcept?: CodeableConcept;
/** Actual result */
valueString?: string;
/** Actual result */
valueBoolean?: boolean;
/** Actual result */
valueInteger?: number;
/** Actual result */
valueRange?: Range;
/** Actual result */
valueRatio?: Ratio;
/** Actual result */
valueSampledData?: SampledData;
/** Actual result */
valueTime?: Date | string;
/** Actual result */
valueDateTime?: string;
/** Actual result */
valuePeriod?: Period;
/** Why the result is missing */
dataAbsentReason?: CodeableConcept;
/** High, low, normal, etc. */
interpretation?: Array<CodeableConcept>;
/** Comments about the observation */
note?: Array<Annotation>;
/** Observed body part */
bodySite?: CodeableConcept;
/** How it was done */
method?: CodeableConcept;
/** Provides guide for interpretation */
referenceRange?: Array<ObservationReferenceRange>;
/** Related resource that belongs to the Observation group */
hasMember?: Array<Reference>;
/** Related measurements the observation is made from */
derivedFrom?: Array<Reference>;
/** Component results */
component?: Array<ObservationComponent>;
}
/**
* A resource with narrative, extensions, and contained resources
* Based on [FHIR DomainResource](https://www.hl7.org/fhir/domainresource.html)
*/
export interface DomainResourceParent extends Resource {
/** Text summary of the resource, for human interpretation */
text?: Narrative;
/** Contained, inline Resources */
contained?: Array<Resource>;
/** Additional Content defined by implementations */
extension?: Array<Extension>;
/** Extensions that cannot be ignored */
modifierExtension?: Array<Extension>;
resourceType: string;
}
/**
* Resource is the ancestor of DomainResource from which most resources are derived. Bundle, Parameters, and Binary extend Resource directly.
* Based on [FHIR Resource](https://www.hl7.org/fhir/r4/resource.html
*/
export interface Resource extends Record<string, unknown> {
/** The type of resource */
resourceType: string;
/** Resource Id */
id?: string;
/** Metadata about the resource */
meta?: Meta;
/** A set of rules under which this content was created */
implicitRules?: string;
/** Language of the resource content */
language?: string;
}
/**
* Metadata about a resource
* Based on [FHIR Meta](https://www.hl7.org/fhir/R4/resource.html#Meta)
*/
export interface Meta {
/** The version specific identifier, as it appears in the version portion of the URL. This value changes when the resource is created, updated, or deleted. */
versionId?: string;
/** When the resource last changed - e.g. when the version changed. */
lastUpdated?: string;
/** A uri that identifies the source system of the resource. This provides a minimal amount of Provenance information that can be used to track or differentiate the source of information in the resource. The source may identify another FHIR server, document, message, database, etc. */
source?: string;
/** A list of profiles (references to [StructureDefinition](https://www.hl7.org/fhir/structuredefinition.html) resources) that this resource claims to conform to. The URL is a reference to [StructureDefinition.url](https://www.hl7.org/fhir/structuredefinition-definitions.html#StructureDefinition.url). */
profile?: string[];
/** Security labels applied to this resource. These tags connect specific resources to the overall security policy and infrastructure. */
security?: Array<Coding>;
/** Tags applied to this resource. Tags are intended to be used to identify and relate resources to process and workflow, and applications are not required to consider the tags when interpreting the meaning of a resource. */
tag?: Array<Coding>;
}
/**
* Detailed information about conditions, problems or diagnoses
* Based on [FHIR Condition](https://www.hl7.org/fhir/R4/condition.html)
*/
export interface Condition extends DomainResourceParent {
/** resourceType */
resourceType: "Condition";
/** External Ids for this condition */
identifier?: Array<Identifier>;
/** active | recurrence | relapse | inactive | remission | resolved */
clinicalStatus?: CodeableConcept;
/** unconfirmed | provisional | differential | confirmed | refuted | entered-in-error */
verificationStatus?: CodeableConcept;
/** problem-list-item | encounter-diagnosis */
category?: Array<CodeableConcept>;
/** Subjective severity of condition */
severity?: CodeableConcept;
/** Identification of the condition, problem or diagnosis */
code?: CodeableConcept;
/** Anatomical location, if relevant */
bodySite?: Array<CodeableConcept>;
/** Encounter created as part of */
encounter?: Reference;
/** Estimated or actual date, date-time, or age */
onsetDateTime?: string;
/** Estimated or actual date, date-time, or age */
onsetAge?: Quantity;
/** Estimated or actual date, date-time, or age */
onsetPeriod?: Period;
/** Estimated or actual date, date-time, or age */
onsetRange?: Range;
/** Estimated or actual date, date-time, or age */
onsetString?: string;
/** When in resolution/remission */
abatementDateTime?: string;
/** When in resolution/remission */
abatementAge?: Quantity;
/** When in resolution/remission */
abatementPeriod?: Period;
/** When in resolution/remission */
abatementRange?: Range;
/** When in resolution/remission */
abatementString?: string;
/** Date record was first recorded */
recordedDate?: string;
/** stge/grade, usually assessed formally */
stage?: Array<ConditionStage>;
/** Additional information about the Condition */
note?: Array<Annotation>;
}
/**
* Stage/grade, usually assessed formally
* Based on [FHIR Condition.Stage](https://www.hl7.org/fhir/R4/condition.html)
*/
export interface ConditionStage {
/** Simple summary (disease specific) */
summary?: CodeableConcept;
/** Kind of staging */
type?: CodeableConcept;
}
/**
* Detailed information about Research Study
* Based on [FHIR ResearchStudy](https://www.hl7.org/fhir/R4/researchstudy.html)
*/
export interface ResearchStudy extends DomainResourceParent {
/** resourceType */
resourceType: "ResearchStudy";
/** Business Identifier for study */
identifier?: Array<Identifier>;
/** Name for this study */
title?: string;
/** Steps followed in executing study */
protocol?: Array<Reference>;
/** Part of larger study */
partOf?: Array<Reference>;
/**
* active | administratively-completed | approved | closed-to-accrual | closed-to-accrual-and-intervention | completed | disapproved | in-review | temporarily-closed-to-accrual | temporarily-closed-to-accrual-and-intervention | withdrawn
*
* Possible values: "active", "administratively-completed", "approved", "closed-to-accrual", "closed-to-accrual-and-intervention", "completed", "disapproved", "in-review", "temporarily-closed-to-accrual", "temporarily-closed-to-accrual-and-intervention", "withdrawn"
*/
status: string;
/** treatment | prevention | diagnostic | supportive-care | screening | health-services-research | basic-science | device-feasibility */
primaryPurposeType?: CodeableConcept;
/** n-a | early-phase-1 | phase-1 | phase-1-phase-2 | phase-2 | phase-2-phase-3 | phase-3 | phase-4 */
phase?: CodeableConcept;
/** Classifications for the study */
category?: Array<CodeableConcept>;
/** Drugs, devices, etc. under study */
focus?: Array<CodeableConcept>;
/** Condition being studied */
condition?: Array<CodeableConcept>;
/** Contact details for the study */
contact?: Array<ContactDetail>;
/** Used to search for the study */
keyword?: Array<CodeableConcept>;
/** Geographic region(s) for study */
location?: Array<CodeableConcept>;
/** What this is study doing */
description?: string;
/** Inclusion & exclusion criteria */
enrollment?: Array<Reference>;
/** When the study began and ended */
period?: Period;
/** Organization that initiates and is legally responsible for the study */
sponsor?: Reference;
/** Researcher who oversees multiple aspects of the study */
principalInvestigator?: Reference;
/** Facility where study activities are conducted */
site?: Array<Reference>;
/** accrual-goal-met | closed-due-to-toxicity | closed-due-to-lack-of-study-progress | temporarily-closed-per-study-design */
reasonStopped?: CodeableConcept;
/** Comments made about the study */
note?: Array<Annotation>;
/** Defined path through the study for a subject */
arm?: { name: string; type?: CodeableConcept; description?: string }[];
/** A goal for the study */
objective?: { name: string; type?: CodeableConcept }[];
}
/** Procedure information */
export interface OrderedProcedure {
/** Additional Content defined by implementations */
extension?: Array<Extension>;
/** Procedure code */
code?: CodeableConcept;
/** Procedure description */
description?: string;
}
/** Contains the list of patients, and configuration data. */
export interface RadiologyInsightsData {
/** The list of patients, including their clinical information and data. */
patients: Array<PatientRecord>;
/** Configuration affecting the Radiology Insights model's inference. */
configuration?: RadiologyInsightsModelConfiguration;
}
/** A patient record, including their clinical information and data. */
export interface PatientRecord {
/** A given identifier for the patient. Has to be unique across all patients in a single request. */
id: string;
/** Patient structured information, including demographics and known structured clinical information. */
info?: PatientInfo;
/** Patient encounters/visits. */
encounters?: Array<Encounter>;
/** Patient unstructured clinical data, given as documents. */
patientDocuments?: Array<PatientDocument>;
}
/** Patient structured information, including demographics and known structured clinical information. */
export interface PatientInfo {
/**
* The patient's sex.
*
* Possible values: "female", "male", "unspecified"
*/
sex?: string;
/** The patient's date of birth. */
birthDate?: Date | string;
/** Known clinical information for the patient, structured. */
clinicalInfo?: Array<Resource>;
}
/** visit/encounter information */
export interface Encounter {
/** The id of the visit. */
id: string;
/**
* Time period of the visit.
* In case of admission, use timePeriod.start to indicate the admission time and timePeriod.end to indicate the discharge time.
*/
period?: TimePeriod;
/**
* The class of the encounter.
*
* Possible values: "inpatient", "ambulatory", "observation", "emergency", "virtual", "healthHome"
*/
class?: string;
}
/** A duration of time during which an event is happening */
export interface TimePeriod {
/** Starting time with inclusive boundary */
start?: Date | string;
/** End time with inclusive boundary, if not ongoing */
end?: Date | string;
}
/** A clinical document related to a patient. Document here is in the wide sense - not just a text document (note). */
export interface PatientDocument {
/**
* The type of the patient document, such as 'note' (text document) or 'fhirBundle' (FHIR JSON document).
*
* Possible values: "note", "fhirBundle", "dicom", "genomicSequencing"
*/
type: string;
/**
* The type of the clinical document.
*
* Possible values: "consultation", "dischargeSummary", "historyAndPhysical", "radiologyReport", "procedure", "progress", "laboratory", "pathologyReport"
*/
clinicalType?: string;
/** A given identifier for the document. Has to be unique across all documents for a single patient. */
id: string;
/** A 2 letter ISO 639-1 representation of the language of the document. */
language?: string;
/** The date and time when the document was created. */
createdDateTime?: Date | string;
/** Document author(s) */
authors?: Array<DocumentAuthor>;
/**
* specialty type the document
*
* Possible values: "pathology", "radiology"
*/
specialtyType?: string;
/** Administrative metadata for the document. */
administrativeMetadata?: DocumentAdministrativeMetadata;
/** The content of the patient document. */
content: DocumentContent;
}
/** Document author */
export interface DocumentAuthor {
/** author id */
id?: string;
/** Text representation of the full name */
fullName?: string;
}
/** Document administrative metadata */
export interface DocumentAdministrativeMetadata {
/** List of procedure information associated with the document. */
orderedProcedures?: Array<OrderedProcedure>;
/** Reference to the encounter associated with the document. */
encounterId?: string;
}
/** The content of the patient document. */
export interface DocumentContent {
/**
* The type of the content's source.
* In case the source type is 'inline', the content is given as a string (for instance, text).
* In case the source type is 'reference', the content is given as a URI.
*
* Possible values: "inline", "reference"
*/
sourceType: string;
/** The content of the document, given either inline (as a string) or as a reference (URI). */
value: string;
}
/** Configuration affecting the Radiology Insights model's inference. */
export interface RadiologyInsightsModelConfiguration {
/** An indication whether the model should produce verbose output. */
verbose?: boolean;
/** An indication whether the model's output should include evidence for the inferences. */
includeEvidence?: boolean;
/** This is a list of inference types to be inferred for the current request. It could be used if only part of the Radiology Insights inferences are required. If this list is omitted or empty, the model will return all the inference types. */
inferenceTypes?: string[];
/** Options regarding follow up recommendation inferences and finding inferences. */
inferenceOptions?: RadiologyInsightsInferenceOptions;
/** Local for the model to use. If not specified, the model will use the default locale. */
locale?: string;
}
/** Options regarding follow up recommendation inferences and finding inferences. */
export interface RadiologyInsightsInferenceOptions {
/** Follow-up recommendation options. */
followupRecommendationOptions?: FollowupRecommendationOptions;
/** Finding options. */
findingOptions?: FindingOptions;
}
/** Follow-up recommendation options. */
export interface FollowupRecommendationOptions {
/** Include/Exclude follow-up recommendations without a specific radiology procedure. Default is false. */
includeRecommendationsWithNoSpecifiedModality?: boolean;
/** Include/Exclude follow-up recommendations in references to a guideline or article. Default is false. */
includeRecommendationsInReferences?: boolean;
/** If this is true, provide one or more sentences as evidence for the recommendation, next to the token evidence. The start and end positions of these sentences will be put in an extension with url 'modality_sentences'. Default is false. */
provideFocusedSentenceEvidence?: boolean;
}
/** Finding options. */
export interface FindingOptions {
/** If this is true, provide the sentence that contains the first token of the finding's clinical indicator (i.e. the medical problem), if there is one. This sentence is provided as an extension with url 'ci_sentence', next to the token evidence. Default is false. */
provideFocusedSentenceEvidence?: boolean;
}
/**
* A resource with narrative, extensions, and contained resources
* Based on [FHIR DomainResource](https://www.hl7.org/fhir/domainresource.html)
*/
export type DomainResource = DomainResourceParent | Observation | Condition | ResearchStudy;

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -0,0 +1,25 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
import { RawHttpHeadersInput } from "@azure/core-rest-pipeline";
import { RequestParameters } from "@azure-rest/core-client";
import { RadiologyInsightsData } from "./models";
export type GetJobParameters = RequestParameters;
export interface CreateJobHeaders {
/** An opaque, globally-unique, client-generated string identifier for the request. */
"Repeatability-Request-ID"?: string;
/** Specifies the date and time at which the request was first created. */
"Repeatability-First-Sent"?: string;
}
export interface CreateJobBodyParam {
body?: RadiologyInsightsData;
}
export interface CreateJobHeaderParam {
headers?: RawHttpHeadersInput & CreateJobHeaders;
}
export type CreateJobParameters = CreateJobHeaderParam & CreateJobBodyParam & RequestParameters;

Просмотреть файл

@ -0,0 +1,80 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
import { Client, HttpResponse } from "@azure-rest/core-client";
import {
CreateHttpPollerOptions,
LongRunningOperation,
LroResponse,
OperationState,
SimplePollerLike,
createHttpPoller,
} from "@azure/core-lro";
import {
CreateJob202Response,
CreateJobDefaultResponse,
CreateJobLogicalResponse,
} from "./responses";
/**
* Helper function that builds a Poller object to help polling a long running operation.
* @param client - Client to use for sending the request to get additional pages.
* @param initialResponse - The initial response.
* @param options - Options to set a resume state or custom polling interval.
* @returns - A poller object to poll for operation state updates and eventually get the final response.
*/
export async function getLongRunningPoller<
TResult extends CreateJobLogicalResponse | CreateJobDefaultResponse,
>(
client: Client,
initialResponse: CreateJob202Response | CreateJobDefaultResponse,
options?: CreateHttpPollerOptions<TResult, OperationState<TResult>>,
): Promise<SimplePollerLike<OperationState<TResult>, TResult>>;
export async function getLongRunningPoller<TResult extends HttpResponse>(
client: Client,
initialResponse: TResult,
options: CreateHttpPollerOptions<TResult, OperationState<TResult>> = {},
): Promise<SimplePollerLike<OperationState<TResult>, TResult>> {
const poller: LongRunningOperation<TResult> = {
requestMethod: initialResponse.request.method,
requestPath: initialResponse.request.url,
sendInitialRequest: async () => {
// In the case of Rest Clients we are building the LRO poller object from a response that's the reason
// we are not triggering the initial request here, just extracting the information from the
// response we were provided.
return getLroResponse(initialResponse);
},
sendPollRequest: async (path) => {
// This is the callback that is going to be called to poll the service
// to get the latest status. We use the client provided and the polling path
// which is an opaque URL provided by caller, the service sends this in one of the following headers: operation-location, azure-asyncoperation or location
// depending on the lro pattern that the service implements. If non is provided we default to the initial path.
const response = await client.pathUnchecked(path ?? initialResponse.request.url).get();
const lroResponse = getLroResponse(response as TResult);
lroResponse.rawResponse.headers["x-ms-original-url"] = initialResponse.request.url;
return lroResponse;
},
};
options.resolveOnUnsuccessful = options.resolveOnUnsuccessful ?? true;
return createHttpPoller(poller, options);
}
/**
* Converts a Rest Client response to a response that the LRO implementation understands
* @param response - a rest client http response
* @returns - An LRO response that the LRO implementation understands
*/
function getLroResponse<TResult extends HttpResponse>(response: TResult): LroResponse<TResult> {
if (Number.isNaN(response.status)) {
throw new TypeError(`Status code of the response is not a number. Value: ${response.status}`);
}
return {
flatResponse: response,
rawResponse: {
...response,
statusCode: Number.parseInt(response.status),
body: response.body,
},
};
}

Просмотреть файл

@ -0,0 +1,63 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
import { RawHttpHeaders } from "@azure/core-rest-pipeline";
import { HttpResponse, ErrorResponse } from "@azure-rest/core-client";
import { RadiologyInsightsResultOutput, HealthInsightsOperationStatusOutput } from "./outputModels";
import { RepeatabilityResultOutput } from "./outputModels";
export interface GetJob200Headers {
/** The Retry-After header can indicate how long the client should wait before polling the operation status. */
"retry-after"?: number;
}
/** The request has succeeded. */
export interface GetJob200Response extends HttpResponse {
status: "200";
body: RadiologyInsightsResultOutput;
headers: RawHttpHeaders & GetJob200Headers;
}
export interface GetJobDefaultHeaders {
/** String error code indicating what went wrong. */
"x-ms-error-code"?: string;
}
export interface GetJobDefaultResponse extends HttpResponse {
status: string;
body: ErrorResponse;
headers: RawHttpHeaders & GetJobDefaultHeaders;
}
export interface CreateJob202Headers {
/** The location for monitoring the operation state. */
"operation-location": string;
/** The Retry-After header can indicate how long the client should wait before polling the operation status. */
"retry-after"?: number;
/** Indicates whether the repeatable request was accepted or rejected. */
"repeatability-result"?: RepeatabilityResultOutput;
}
/** The request has been accepted for processing, but processing has not yet completed. */
export interface CreateJob202Response extends HttpResponse {
status: "202";
body: HealthInsightsOperationStatusOutput;
headers: RawHttpHeaders & CreateJob202Headers;
}
export interface CreateJobDefaultHeaders {
/** String error code indicating what went wrong. */
"x-ms-error-code"?: string;
}
export interface CreateJobDefaultResponse extends HttpResponse {
status: string;
body: ErrorResponse;
headers: RawHttpHeaders & CreateJobDefaultHeaders;
}
/** The final response for long-running createJob operation */
export interface CreateJobLogicalResponse extends HttpResponse {
status: "200";
body: HealthInsightsOperationStatusOutput;
}

Просмотреть файл

@ -0,0 +1,159 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
import { assert } from "chai";
import { Recorder } from "@azure-tools/test-recorder";
import { Context } from "mocha";
import { createClient, createRecorder } from "./utils/recordedClient";
import { AzureHealthInsightsClient, getLongRunningPoller } from "../../src";
const codingData = {
system: "http://www.nlm.nih.gov/research/umls",
code: "C0018802",
display: "MalignantNeoplasms",
};
const codingData2 = {
system: "Http://hl7.org/fhir/ValueSet/cpt-all",
code: "111111",
display: "CT ABD/PELVIS",
};
const code = {
coding: [codingData],
};
const code2 = {
coding: [codingData2],
};
const clinicInfoData = {
resourceType: "Observation",
status: "unknown",
code: code,
valueBoolean: true,
};
const patientInfo = {
sex: "female",
birthDate: new Date("1959-11-11T19:00:00+00:00"),
clinicalInfo: [clinicInfoData],
};
const encounterData = {
id: "encounterid1",
period: {
start: "2021-8-28T00:00:00",
end: "2021-8-28T00:00:00",
},
class: "inpatient",
};
const authorData = {
id: "authorid1",
name: "authorname1",
};
const orderedProceduresData = {
code: code2,
description: "CT ABD/PELVIS",
};
const administrativeMetadata = {
orderedProcedures: [orderedProceduresData],
encounterId: "encounterid1",
};
const content = {
sourceType: "inline",
value:
"\n\nThe results were faxed to Julie Carter on July 6 2016 at 3 PM.\n\nThe results were sent via Powerscribe to George Brown, PA.\n\n\t\t",
};
const patientDocumentData = {
type: "note",
clinicalType: "radiologyReport",
id: "docid1",
language: "en",
authors: [authorData],
specialtyType: "radiology",
administrativeMetadata: administrativeMetadata,
content: content,
createdDateTime: new Date("2021-05-31T22:00:00.000Z"),
orderedProceduresAsCsv: "CT ABD/PELVIS",
};
const patientData = {
id: "Samantha Jones",
info: patientInfo,
encounters: [encounterData],
patientDocuments: [patientDocumentData],
};
const inferenceTypes = [
"finding",
"ageMismatch",
"lateralityDiscrepancy",
"sexMismatch",
"completeOrderDiscrepancy",
"limitedOrderDiscrepancy",
"criticalResult",
"criticalRecommendation",
"followupRecommendation",
"followupCommunication",
"radiologyProcedure",
];
const followupRecommendationOptions = {
includeRecommendationsWithNoSpecifiedModality: true,
includeRecommendationsInReferences: true,
provideFocusedSentenceEvidence: true,
};
const findingOptions = {
provideFocusedSentenceEvidence: true,
};
const inferenceOptions = {
followupRecommendationOptions: followupRecommendationOptions,
findingOptions: findingOptions,
};
// Create RI Configuration
const configuration = {
inferenceOptions: inferenceOptions,
inferenceTypes: inferenceTypes,
locale: "en-US",
verbose: false,
includeEvidence: true,
};
// create RI Data
const radiologyInsightsData = {
patients: [patientData],
configuration: configuration,
};
const radiologyInsightsParameter = {
body: radiologyInsightsData,
};
describe("Radiology Insights Test", () => {
let recorder: Recorder;
let client: AzureHealthInsightsClient;
beforeEach(async function (this: Context) {
recorder = await createRecorder(this);
client = await createClient(recorder);
});
afterEach(async function () {
await recorder.stop();
});
it("radiology Insights test", async function () {
const result = await client.path("/radiology-insights/jobs").post(radiologyInsightsParameter);
const poller = await getLongRunningPoller(client, result);
const res = await poller.pollUntilDone();
console.log(res);
assert.equal(res.status, "200");
});
});

Просмотреть файл

@ -0,0 +1,2 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

Просмотреть файл

@ -0,0 +1,6 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
import * as dotenv from "dotenv";
dotenv.config();

Просмотреть файл

@ -0,0 +1,43 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
import { Context } from "mocha";
import {
assertEnvironmentVariable,
Recorder,
RecorderStartOptions,
} from "@azure-tools/test-recorder";
import "./env";
import { AzureKeyCredential } from "@azure/core-auth";
import AHIClient, { AzureHealthInsightsClient } from "../../../src";
const envSetupForPlayback: Record<string, string> = {
HEALTH_INSIGHTS_ENDPOINT: "https://endpoint",
HEALTH_INSIGHTS_KEY: "fake_key",
AZURE_CLIENT_ID: "azure_client_id",
AZURE_CLIENT_SECRET: "azure_client_secret",
AZURE_TENANT_ID: "88888888-8888-8888-8888-888888888888",
SUBSCRIPTION_ID: "azure_subscription_id",
};
const recorderEnvSetup: RecorderStartOptions = {
envSetupForPlayback,
};
/**
* creates the recorder and reads the environment variables from the `.env` file.
* Should be called first in the test suite to make sure environment variables are
* read before they are being used.
*/
export async function createRecorder(context: Context): Promise<Recorder> {
const recorder = new Recorder(context.currentTest);
await recorder.start(recorderEnvSetup);
return recorder;
}
export async function createClient(recorder: Recorder): Promise<AzureHealthInsightsClient> {
const endpoint = assertEnvironmentVariable("HEALTH_INSIGHTS_ENDPOINT");
const key = assertEnvironmentVariable("HEALTH_INSIGHTS_KEY");
const credential = new AzureKeyCredential(key);
return AHIClient(endpoint, credential, recorder.configureClientOptions({}));
}

Просмотреть файл

@ -0,0 +1,11 @@
{
"extends": "../../../tsconfig.package",
"compilerOptions": {
"outDir": "./dist-esm",
"declarationDir": "./types",
"paths": {
"@azure-rest/health-insights-radiologyinsights": ["./src/index"]
}
},
"include": ["src/**/*.ts", "./test/**/*.ts", "samples-dev/**/*.ts"]
}

Просмотреть файл

@ -0,0 +1,7 @@
directory: specification/ai/HealthInsights/HealthInsights.RadiologyInsights
additionalDirectories:
- specification/ai/HealthInsights/HealthInsights.Common
- specification/ai/HealthInsights/HealthInsights.OpenAPI
commit: 3efb341e0472b4b1d85f9c015666a715d9f5fa5a
repo: Azure/azure-rest-api-specs
cleanup: false