Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[TA] Healthcare Design update #18200

Merged
merged 12 commits into from
Feb 2, 2021
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 30 additions & 8 deletions sdk/textanalytics/Azure.AI.TextAnalytics/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -411,7 +411,7 @@ catch (RequestFailedException exception)
### Recognize Healthcare Entities Asynchronously
Text Analytics for health is a containerized service that extracts and labels relevant medical information from unstructured texts such as doctor's notes, discharge summaries, clinical documents, and electronic health records. For more information see [How to: Use Text Analytics for health][healthcare].

```C# Snippet:RecognizeHealthcareEntitiesAsync
```C# Snippet:TextAnalyticsSampleHealthcareBatchAsync
string document = @"RECORD #333582770390100 | MH | 85986313 | | 054351 | 2/14/2001 12:00:00 AM | CORONARY ARTERY DISEASE | Signed | DIS | \
Admission Date: 5/22/2001 Report Status: Signed Discharge Date: 4/24/2001 ADMISSION DIAGNOSIS: CORONARY ARTERY DISEASE. \
HISTORY OF PRESENT ILLNESS: The patient is a 54-year-old gentleman with a history of progressive angina over the past several months. \
Expand All @@ -422,16 +422,29 @@ Text Analytics for health is a containerized service that extracts and labels re
minimal ST depressions in the anterior lateral leads , thought due to fatigue and wrist pain , his anginal equivalent. Due to the patient's \
increased symptoms and family history and history left main disease with total occasional of his RCA was referred for revascularization with open heart surgery.";

AnalyzeHealthcareEntitiesOperation healthOperation = await client.StartHealthcareAsync(document);
List<string> batchInput = new List<string>()
{
document,
document,
};

AnalyzeHealthcareEntitiesOptions options = new AnalyzeHealthcareEntitiesOptions()
{
Top = 1,
Skip = 0,
IncludeStatistics = true
};

AnalyzeHealthcareEntitiesOperation healthOperation = await client.StartAnalyzeHealthcareEntitiesAsync(batchInput, "en", options);

await healthOperation.WaitForCompletionAsync();

RecognizeHealthcareEntitiesResultCollection results = healthOperation.Value;
AnalyzeHealthcareEntitiesResultCollection results = healthOperation.Value;

Console.WriteLine($"Results of Azure Text Analytics \"Healthcare Async\" Model, version: \"{results.ModelVersion}\"");
Console.WriteLine("");

foreach (DocumentHealthcareResult result in results)
foreach (AnalyzeHealthcareEntitiesResult result in results)
{
Console.WriteLine($" Recognized the following {result.Entities.Count} healthcare entities:");

Expand All @@ -441,17 +454,26 @@ Text Analytics for health is a containerized service that extracts and labels re
Console.WriteLine($" Category: {entity.Category}");
Console.WriteLine($" Offset: {entity.Offset}");
Console.WriteLine($" Length: {entity.Length}");
Console.WriteLine($" IsNegated: {entity.IsNegated}");
Console.WriteLine($" Links:");

foreach (HealthcareEntityLink healthcareEntityLink in entity.Links)
foreach (EntityDataSource entityDataSource in entity.DataSources)
{
Console.WriteLine($" ID: {healthcareEntityLink.Id}");
Console.WriteLine($" DataSource: {healthcareEntityLink.DataSource}");
Console.WriteLine($" Entity ID in Data Source: {entityDataSource.EntityId}");
Console.WriteLine($" DataSource: {entityDataSource.Name}");
}
}

Console.WriteLine($" Document statistics:");
Console.WriteLine($" Character count (in Unicode graphemes): {result.Statistics.CharacterCount}");
Console.WriteLine($" Transaction count: {result.Statistics.TransactionCount}");
Console.WriteLine("");
}
Console.WriteLine($"Request statistics:");
Console.WriteLine($" Document Count: {results.Statistics.DocumentCount}");
Console.WriteLine($" Valid Document Count: {results.Statistics.ValidDocumentCount}");
Console.WriteLine($" Transaction Count: {results.Statistics.TransactionCount}");
Console.WriteLine($" Invalid Document Count: {results.Statistics.InvalidDocumentCount}");
Console.WriteLine("");
}
```

Expand Down

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ var client = new TextAnalyticsClient(new Uri(endpoint), new AzureKeyCredential(a

To recognize healthcare entities in a document, use the `StarthealthcareAsyc` method. The returned type is a Long Running operation of type `HealthcareOperation` which polls for the results from the API.

```C# Snippet:RecognizeHealthcareEntities
```C# Snippet:TextAnalyticsSampleHealthcareBatchAsync
string document = @"RECORD #333582770390100 | MH | 85986313 | | 054351 | 2/14/2001 12:00:00 AM | CORONARY ARTERY DISEASE | Signed | DIS | \
Admission Date: 5/22/2001 Report Status: Signed Discharge Date: 4/24/2001 ADMISSION DIAGNOSIS: CORONARY ARTERY DISEASE. \
HISTORY OF PRESENT ILLNESS: The patient is a 54-year-old gentleman with a history of progressive angina over the past several months. \
Expand All @@ -28,36 +28,58 @@ To recognize healthcare entities in a document, use the `StarthealthcareAsyc` me
minimal ST depressions in the anterior lateral leads , thought due to fatigue and wrist pain , his anginal equivalent. Due to the patient's \
increased symptoms and family history and history left main disease with total occasional of his RCA was referred for revascularization with open heart surgery.";

AnalyzeHealthcareEntitiesOperation healthOperation = client.StartHealthcare(document);
List<string> batchInput = new List<string>()
{
document,
document,
};

AnalyzeHealthcareEntitiesOptions options = new AnalyzeHealthcareEntitiesOptions()
{
Top = 1,
Skip = 0,
IncludeStatistics = true
};

AnalyzeHealthcareEntitiesOperation healthOperation = await client.StartAnalyzeHealthcareEntitiesAsync(batchInput, "en", options);

await healthOperation.WaitForCompletionAsync();

RecognizeHealthcareEntitiesResultCollection results = healthOperation.Value;
AnalyzeHealthcareEntitiesResultCollection results = healthOperation.Value;

Console.WriteLine($"Results of Azure Text Analytics \"Healthcare\" Model, version: \"{results.ModelVersion}\"");
Console.WriteLine($"Results of Azure Text Analytics \"Healthcare Async\" Model, version: \"{results.ModelVersion}\"");
Console.WriteLine("");

foreach (DocumentHealthcareResult result in results)
foreach (AnalyzeHealthcareEntitiesResult result in results)
{
Console.WriteLine($" Recognized the following {result.Entities.Count} healthcare entities:");
Console.WriteLine($" Recognized the following {result.Entities.Count} healthcare entities:");

foreach (HealthcareEntity entity in result.Entities)
foreach (HealthcareEntity entity in result.Entities)
{
Console.WriteLine($" Entity: {entity.Text}");
Console.WriteLine($" Category: {entity.Category}");
Console.WriteLine($" Offset: {entity.Offset}");
Console.WriteLine($" Length: {entity.Length}");
Console.WriteLine($" Links:");

foreach (EntityDataSource entityDataSource in entity.DataSources)
{
Console.WriteLine($" Entity: {entity.Text}");
Console.WriteLine($" Category: {entity.Category}");
Console.WriteLine($" Offset: {entity.Offset}");
Console.WriteLine($" Length: {entity.Length}");
Console.WriteLine($" IsNegated: {entity.IsNegated}");
Console.WriteLine($" Links:");

foreach (HealthcareEntityLink healthcareEntityLink in entity.Links)
{
Console.WriteLine($" ID: {healthcareEntityLink.Id}");
Console.WriteLine($" DataSource: {healthcareEntityLink.DataSource}");
}
Console.WriteLine($" Entity ID in Data Source: {entityDataSource.EntityId}");
Console.WriteLine($" DataSource: {entityDataSource.Name}");
}
Console.WriteLine("");
}

Console.WriteLine($" Document statistics:");
Console.WriteLine($" Character count (in Unicode graphemes): {result.Statistics.CharacterCount}");
Console.WriteLine($" Transaction count: {result.Statistics.TransactionCount}");
Console.WriteLine("");
}
Console.WriteLine($"Request statistics:");
Console.WriteLine($" Document Count: {results.Statistics.DocumentCount}");
Console.WriteLine($" Valid Document Count: {results.Statistics.ValidDocumentCount}");
Console.WriteLine($" Transaction Count: {results.Statistics.TransactionCount}");
Console.WriteLine($" Invalid Document Count: {results.Statistics.InvalidDocumentCount}");
Console.WriteLine("");
}
```

Expand All @@ -81,16 +103,16 @@ To recognize healthcare entities in multiple documents, call `StartHealthcareBat
document,
};

AnalyzeHealthcareEntitiesOperation healthOperation = await client.StartHealthcareBatchAsync(batchInput, "en");
AnalyzeHealthcareEntitiesOperation healthOperation = await client.StartAnalyzeHealthcareEntitiesAsync(batchInput, "en");

await healthOperation.WaitForCompletionAsync();

RecognizeHealthcareEntitiesResultCollection results = healthOperation.Value;
AnalyzeHealthcareEntitiesResultCollection results = healthOperation.Value;

Console.WriteLine($"Results of Azure Text Analytics \"Healthcare Async\" Model, version: \"{results.ModelVersion}\"");
Console.WriteLine("");

foreach (DocumentHealthcareResult result in results)
foreach (AnalyzeHealthcareEntitiesResult result in results)
{
Console.WriteLine($" Recognized the following {result.Entities.Count} healthcare entities:");

Expand All @@ -100,13 +122,12 @@ To recognize healthcare entities in multiple documents, call `StartHealthcareBat
Console.WriteLine($" Category: {entity.Category}");
Console.WriteLine($" Offset: {entity.Offset}");
Console.WriteLine($" Length: {entity.Length}");
Console.WriteLine($" IsNegated: {entity.IsNegated}");
Console.WriteLine($" Links:");

foreach (HealthcareEntityLink healthcareEntityLink in entity.Links)
foreach (EntityDataSource entityDataSource in entity.DataSources)
{
Console.WriteLine($" ID: {healthcareEntityLink.Id}");
Console.WriteLine($" DataSource: {healthcareEntityLink.DataSource}");
Console.WriteLine($" Entity ID in Data Source: {entityDataSource.EntityId}");
Console.WriteLine($" DataSource: {entityDataSource.Name}");
}
}
Console.WriteLine("");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
namespace Azure.AI.TextAnalytics
{
/// <summary> The AnalyzeHealthcareEntitiesOperation class for LRO. </summary>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

are you thinking on having a separate PR to improve the docstrings?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not sure what should be the docstrings, are there any guidelines around it? can you provide some example doc strings?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sadly I don't think there are any guidelines for it, but think of it as the way to explain to a user what each class, property, method is about.
You could use the docstring in other endpoints or libraries as guidance

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i.e. is a user reads The AnalyzeHealthcareEntitiesOperation class for LRO. it actually doesn't mean anything for them. What is LRO? and what is the purpose of this class?
something like
Tracks the status of a long-running operation that analyze the healthcare entities from the given documents. or something along those lines

public class AnalyzeHealthcareEntitiesOperation : Operation<RecognizeHealthcareEntitiesResultCollection>
public class AnalyzeHealthcareEntitiesOperation : Operation<AnalyzeHealthcareEntitiesResultCollection>
{
/// <summary>Provides communication with the Text Analytics Azure Cognitive Service through its REST API.</summary>
private readonly TextAnalyticsRestClient _serviceClient;
Expand All @@ -35,6 +35,21 @@ public class AnalyzeHealthcareEntitiesOperation : Operation<RecognizeHealthcareE
/// </summary>
public override string Id { get; }

/// <summary>
/// CreatedOn
/// </summary>
public DateTimeOffset CreatedOn { get; }

/// <summary>
/// ExpiresOn
/// </summary>
public DateTimeOffset ExpiresOn { get; }

/// <summary>
/// LastModified
/// </summary>
public DateTimeOffset LastModified { get; }

/// <summary>
/// Gets the status of the operation.
/// </summary>
Expand All @@ -51,7 +66,7 @@ public class AnalyzeHealthcareEntitiesOperation : Operation<RecognizeHealthcareE
/// <remarks>
/// This property can be accessed only after the operation completes successfully (HasValue is true).
/// </remarks>
public override RecognizeHealthcareEntitiesResultCollection Value
public override AnalyzeHealthcareEntitiesResultCollection Value
{
get
{
Expand Down Expand Up @@ -80,7 +95,7 @@ public override RecognizeHealthcareEntitiesResultCollection Value
private Response _response;

/// <summary>The result of the long-running operation. <c>null</c> until result is received on status update.</summary>
private RecognizeHealthcareEntitiesResultCollection _value;
private AnalyzeHealthcareEntitiesResultCollection _value;

private int? _top { get; }
private int? _skip { get; }
Expand Down Expand Up @@ -169,7 +184,7 @@ public override async ValueTask<Response> UpdateStatusAsync(CancellationToken ca
/// <remarks>
/// This method will periodically call UpdateStatusAsync till HasCompleted is true, then return the final result of the operation.
/// </remarks>
public override ValueTask<Response<RecognizeHealthcareEntitiesResultCollection>> WaitForCompletionAsync(CancellationToken cancellationToken = default) =>
public override ValueTask<Response<AnalyzeHealthcareEntitiesResultCollection>> WaitForCompletionAsync(CancellationToken cancellationToken = default) =>
this.DefaultWaitForCompletionAsync(cancellationToken);

/// <summary>
Expand All @@ -185,7 +200,7 @@ public override ValueTask<Response<RecognizeHealthcareEntitiesResultCollection>>
/// <remarks>
/// This method will periodically call UpdateStatusAsync till HasCompleted is true, then return the final result of the operation.
/// </remarks>
public override ValueTask<Response<RecognizeHealthcareEntitiesResultCollection>> WaitForCompletionAsync(TimeSpan pollingInterval, CancellationToken cancellationToken = default) =>
public override ValueTask<Response<AnalyzeHealthcareEntitiesResultCollection>> WaitForCompletionAsync(TimeSpan pollingInterval, CancellationToken cancellationToken = default) =>
this.DefaultWaitForCompletionAsync(pollingInterval, cancellationToken);

/// <summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,13 @@ namespace Azure.AI.TextAnalytics
/// Options that allow callers to specify details about how the operation
/// is run and what information is returned from it by the service.
/// </summary>
public class HealthcareOptions : TextAnalyticsRequestOptions
public class AnalyzeHealthcareEntitiesOptions : TextAnalyticsRequestOptions
{
/// <summary>
/// Initializes a new instance of the <see cref="HealthcareOptions"/>
/// Initializes a new instance of the <see cref="AnalyzeHealthcareEntitiesOptions"/>
/// class.
/// </summary>
public HealthcareOptions()
public AnalyzeHealthcareEntitiesOptions()
{
deyaaeldeen marked this conversation as resolved.
Show resolved Hide resolved
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using Azure.AI.TextAnalytics.Models;

namespace Azure.AI.TextAnalytics
{
/// <summary>
/// DocumentHealthcareEntities.
/// </summary>
public partial class AnalyzeHealthcareEntitiesResult : TextAnalyticsResult
{
private readonly IReadOnlyCollection<HealthcareEntity> _entities;

internal AnalyzeHealthcareEntitiesResult(string id, TextDocumentStatistics statistics,
IReadOnlyList<HealthcareEntity> healthcareEntities,
IList<TextAnalyticsWarning> warnings)
: base(id, statistics)
{
_entities = healthcareEntities;
maririos marked this conversation as resolved.
Show resolved Hide resolved
Warnings = new ReadOnlyCollection<TextAnalyticsWarning>(warnings);
}

internal AnalyzeHealthcareEntitiesResult(string id, TextAnalyticsError error) : base(id, error) { }

/// <summary> Warnings encountered while processing document. </summary>
public IReadOnlyCollection<TextAnalyticsWarning> Warnings { get; } = new List<TextAnalyticsWarning>();

/// <summary>
/// Gets the collection of healthcare entities in the document.
/// </summary>
public IReadOnlyCollection<HealthcareEntity> Entities
{
get
{
if (HasError)
{
#pragma warning disable CA1065 // Do not raise exceptions in unexpected locations
throw new InvalidOperationException($"Cannot access result for document {Id}, due to error {Error.ErrorCode}: {Error.Message}");
#pragma warning restore CA1065 // Do not raise exceptions in unexpected locations
}
return _entities;
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,21 @@

using System.Collections.Generic;
using System.Collections.ObjectModel;
using Azure.AI.TextAnalytics.Models;

namespace Azure.AI.TextAnalytics
{
/// <summary>
/// Collection of <see cref="DocumentHealthcareResult"/> objects corresponding
/// Collection of <see cref="AnalyzeHealthcareEntitiesResult"/> objects corresponding
/// to a batch of documents, and information about the batch operation.
/// </summary>
public class RecognizeHealthcareEntitiesResultCollection : ReadOnlyCollection<DocumentHealthcareResult>
public class AnalyzeHealthcareEntitiesResultCollection : ReadOnlyCollection<AnalyzeHealthcareEntitiesResult>
{
/// <summary>
/// </summary>
/// <param name="list"></param>
/// <param name="statistics"></param>
/// <param name="modelVersion"></param>
internal RecognizeHealthcareEntitiesResultCollection(IList<DocumentHealthcareResult> list, TextDocumentBatchStatistics statistics, string modelVersion) : base(list)
internal AnalyzeHealthcareEntitiesResultCollection(IList<AnalyzeHealthcareEntitiesResult> list, TextDocumentBatchStatistics statistics, string modelVersion) : base(list)
{
Statistics = statistics;
ModelVersion = modelVersion;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ internal partial class DocumentHealthcareEntitiesInternal
/// <summary> Unique, non-empty document identifier. </summary>
public string Id { get; }
/// <summary> Healthcare entities. </summary>
public IReadOnlyList<HealthcareEntity> Entities { get; }
public IReadOnlyList<HealthcareEntityInternal> Entities { get; }
/// <summary> Healthcare entity relations. </summary>
public IReadOnlyList<HealthcareRelationInternal> Relations { get; }
/// <summary> Warnings encountered while processing document. </summary>
Expand Down
Loading