public async Task <List <MachineLearningData> > GetOutcomesForTreatmentsAsync(
            BackPainDemographics demographics,
            Dictionary <string, string> treatments,
            CancellationToken cancellationToken)
        {
            // Runs Azure Machine Learning calls for the treatments in parallel to get results faster
            var awaitedResults = await Task.WhenAll(treatments
                                                    .Keys
                                                    .AsParallel()
                                                    .Select(t => GetOutcomeForTreatmentAsync(demographics, t, cancellationToken)));

            // Orders the results by the result strength
            var results = awaitedResults
                          .Where(y => y.ResultStrength < int.MaxValue)
                          .OrderBy(y => y.ResultStrength)
                          .ToList();

            return(results);
        }
Beispiel #2
0
        private async Task PredictBackPainTreatmentAsync(
            ITurnContext turnContext,
            BackPainDemographics demographics,
            CancellationToken cancellationToken)
        {
            // Let them know we're working on getting their data
            await turnContext.SendActivityAsync(
                MessageFactory.Text("Thank you. I'm working on an answer for you. It may take a few seconds."),
                cancellationToken);

            var treatments = BackPainTranslations.Treatments;

            // Get treatment options from Azure Machine Learning
            var results = await _healthOutcomeService
                          .GetOutcomesForTreatmentsAsync(
                demographics,
                treatments,
                cancellationToken);

            if (results == null || !results.Any())
            {
                // if there are no results, let them know
                await turnContext.SendActivityAsync(
                    MessageFactory.Text("I'm sorry. I could not get any results suggesting care options."),
                    cancellationToken);
            }
            else
            {
                // get the best result that is considered a success
                var theResult = results.FirstOrDefault(y => y.ResultStrength < 3);

                if (theResult == null)
                {
                    if (results.Count == 1)
                    {
                        // if there are no success options and there is only one result
                        var bestOption = results.Single();
                        var message    = "Unfortunately, it seems it is unlikely that any of the treatment options will be successful. " +
                                         $"But your best option seems to be **{treatments[bestOption.Treatment]}**. " +
                                         "I suggest you discuss this with your doctor.";
                        await turnContext.SendActivityAsync(
                            MessageFactory.Text(message),
                            cancellationToken);
                    }
                    else
                    {
                        // if there are two or more results, offer up the top two
                        var bestOptions = results.Take(2).ToArray();
                        var message     = "Unfortunately, it seems it is unlikely that any of the treatment options will be successful. " +
                                          $"But your best options seem to be **{treatments[bestOptions[0].Treatment]}** or **{treatments[bestOptions[1].Treatment]}**. " +
                                          "I suggest you discuss these with your doctor.";
                        await turnContext.SendActivityAsync(
                            MessageFactory.Text(message),
                            cancellationToken);
                    }
                }
                else
                {
                    // if there was at least one successful option, return the highest ranked one
                    var message = $"Your best treatment option with a likely successful result is **{treatments[theResult.Treatment]}**. " +
                                  "I suggest you discuss it with your doctor.";
                    await turnContext.SendActivityAsync(MessageFactory.Text(message), cancellationToken);
                }
            }
        }
        private async Task <MachineLearningData> GetOutcomeForTreatmentAsync(
            BackPainDemographics demographics,
            string treatmentCode,
            CancellationToken cancellationToken)
        {
            using (var client = new HttpClient())
            {
                // Azure Machine Learning API uses strange data structures
                var scoreRequest = new
                {
                    Inputs = new Dictionary <string, List <Dictionary <string, string> > >
                    {
                        {
                            "input1",
                            new List <Dictionary <string, string> >
                            {
                                new Dictionary <string, string>
                                {
                                    { "ID", "1" },
                                    { "Diagnosis", string.Empty },
                                    { "Spinal_Canal_Stenosis", string.Empty },
                                    { "Neural_Foraminal_Narrowing", string.Empty },
                                    { "Disc", string.Empty },
                                    { "Annular_Tear", string.Empty },
                                    { "Ligamentum_Flavum", string.Empty },
                                    { "Facet_Arthropathy", string.Empty },
                                    { "Synovial_Cyst_mm", "1" },
                                    { "Perineurial_Cyst_mm", "1" },
                                    { "Tarlov_Cyst_mm", "1" },
                                    { "Sponylolysis", string.Empty },
                                    { "Spondyolithesis", string.Empty },
                                    { "Anterolithesis", string.Empty },
                                    { "Retrolisthesis", string.Empty },
                                    { "Compression", string.Empty },
                                    { "Pain_Chronicity", "1" },
                                    { "Pain_Severity", demographics.LevelOfPain },
                                    { "Radiculopathy", string.Empty },
                                    { "Cancer_History", demographics.CancerHistory },
                                    { "Spinal_Infect_Hist", string.Empty },
                                    { "Cauda_Equina", string.Empty },
                                    { "Neurologic_Deficits", string.Empty },
                                    { "Osteoporosis", string.Empty },
                                    { "Osteopenia", string.Empty },
                                    { "Prev_PT", demographics.HadPhysicalTherapy },
                                    { "Prev_CBT", demographics.CognitiveBehavioralTherapy },
                                    { "Prev_Exercise_Thera", string.Empty },
                                    { "Prev_Pharma_Thera", string.Empty },
                                    { "Prev_Surgical_Thera", string.Empty },
                                    { "Unexplained_Wt_Loss", string.Empty },
                                    { "Fever", demographics.Fever },
                                    { "IVDU", string.Empty },
                                    { "Recent_Infection", string.Empty },
                                    { "Urinary_Retention", string.Empty },
                                    { "Fecal_Incontinence", string.Empty },
                                    { "Saddle_Anesthesia", string.Empty },
                                    { "Use_Corticosterioids", string.Empty },
                                    { "Management_Plan", string.Empty },
                                    { "Opioid_Use", demographics.OpioidUse },
                                    { "Psychiatric_History", demographics.PsychiatricCare },
                                    { "PCP", string.Empty },
                                    { "Self_Referral", string.Empty },
                                    { "Gender", demographics.BiologicalSex },
                                    { "Age", demographics.Age },
                                    { "Height_in", "1" },
                                    { "Weight_lbs", "1" },
                                    { "BMI", "1" },
                                    { "Race", demographics.Race },
                                    { "National_Origin", string.Empty },
                                    { "Marital_Status", string.Empty },
                                    { "Income_Level", "1" },
                                    { "Zip_Code", "1" },
                                    { "Education", string.Empty },
                                    { "Encounter_Date", string.Empty },
                                    { "Prior_Surgery", demographics.PreviousBackSurgery },
                                    { "Acute_Chronic", string.Empty },
                                    { "Overall_Health", string.Empty },
                                    { "Activity_Level", "1" },
                                    { "Sport", string.Empty },
                                    { "Employment_Activity", string.Empty },
                                    { "TV_Hours_Per_Day", "1" },
                                    { "Treatment", treatmentCode },
                                    { "Outcome", string.Empty },
                                },
                            }
                        },
                    },
                    GlobalParameters = new Dictionary <string, string>(),
                };

                client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", _apiKey);
                client.BaseAddress = _azureMachineLearningUri;

                // WARNING: The 'await' statement below can result in a deadlock
                // if you are calling this code from the UI thread of an ASP.Net application.
                // One way to address this would be to call ConfigureAwait(false)
                // so that the execution does not attempt to resume on the original context.
                // For instance, replace code such as:
                //      result = await DoSomeTask()
                // with the following:
                //      result = await DoSomeTask().ConfigureAwait(false)
                var response = await client.PostAsJsonAsync(string.Empty, scoreRequest, cancellationToken).ConfigureAwait(false);

                if (response.IsSuccessStatusCode)
                {
                    var result = await response.Content.ReadAsStringAsync();

                    var output = JsonConvert.DeserializeObject <RootObject>(result);
                    return(output.Results.output1.FirstOrDefault());
                }

                Console.WriteLine("The request failed with status code: {0}", response.StatusCode);

                // Print the headers - they include the request ID and the timestamp,
                // which are useful for debugging the failure
                Console.WriteLine(response.Headers.ToString());

                return(new MachineLearningData
                {
                    Treatment = treatmentCode,
                    ResultStrength = int.MaxValue,
                });
            }
        }