File size: 4,554 Bytes
3f219b5
 
7a79e04
3f219b5
8548275
3f219b5
 
 
7a79e04
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8548275
 
 
7a79e04
 
 
 
 
 
 
8548275
 
7a79e04
8548275
 
7a79e04
ad34bdd
 
7a79e04
 
 
 
 
8548275
7a79e04
 
1532ad8
7a79e04
 
ad34bdd
 
7a79e04
 
8548275
7a79e04
 
9cf65c6
 
 
 
 
 
 
 
7a79e04
 
8548275
 
7a79e04
 
1532ad8
7a79e04
 
8548275
7a79e04
8548275
7a79e04
 
1532ad8
7a79e04
 
8548275
7a79e04
8548275
7a79e04
 
9cf65c6
7a79e04
 
ad34bdd
 
 
7a79e04
8548275
7a79e04
 
1532ad8
7a79e04
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
defmodule Medicode.CodingTest do
  use Medicode.DataCase

  import Medicode.TranscriptionChunksFixtures

  alias Medicode.Coding
  alias Medicode.Coding.CodeVector
  alias Medicode.Feedback.CodeFeedback

  def create_code_vector!(code, description) do
    description_vector = Coding.compute_vector_as_list(description)

    changeset =
      CodeVector.changeset(%CodeVector{}, %{
        code: code,
        description: description,
        description_vector: description_vector
      })

    Repo.insert!(changeset)
  end

  def create_code_feedback!(text, response, for_code) do
    code_vector = Repo.one(from v in CodeVector, where: v.code == ^for_code)
    text_vector = Coding.compute_vector_as_list(text)

    changeset =
      CodeFeedback.changeset(%CodeFeedback{}, %{
        text: text,
        text_vector: text_vector,
        response: response,
        code_vector_id: code_vector.id
      })

    Repo.insert!(changeset)
  end

  describe "process_chunk/2" do
    @input_text "This 55-year-old man with known coronary artery disease comes for a follow-up visit today."
    @feedback_text "A 42-year-old man arrived for a return check-up who had a past history of coronary artery disease."

    setup do
      create_code_vector!("74685", "Coronary artery anomaly")
      create_code_vector!("41412", "Dissection of coronary artery")
      create_code_vector!("V717", "Observation for suspected cardiovascular disease")
      create_code_vector!("V812", "Screening for other and unspecified cardiovascular conditions")
      create_code_vector!("V4589", "Other postprocedural status")

      input_chunk = transcription_chunk_fixture(%{text: @input_text})
      feedback_chunk = transcription_chunk_fixture(%{text: @feedback_text})

      {:ok, input_chunk: input_chunk, feedback_chunk: feedback_chunk}
    end

    test "Codes can be weighted multiple times when multiple prior feedback items exist for a single code",
         %{input_chunk: chunk} do
      # One negative feedback item moves the code from 1st to 4th (x0.9).
      # The net result of 2 negative and 1 positive (x0.891) is to remove the code from the results.
      create_code_feedback!(@feedback_text, false, "74685")
      create_code_feedback!(@feedback_text, true, "74685")
      create_code_feedback!(@feedback_text, false, "74685")
      results = Coding.process_chunk(chunk)

      assert Enum.map(results, & &1.code) == ["41412", "V717", "V812"]
      assert Enum.all?(results, &(&1.weighting == [:none]))
    end

    test "Weighting can cause codes to appear in results that wouldn't have been included from the initial similarity query",
         %{input_chunk: chunk} do
      # E.g. weighting up a code that isn't in the initial results
      create_code_feedback!(@feedback_text, true, "V4589")
      results = Coding.process_chunk(chunk)

      assert Enum.map(results, & &1.code) == ["74685", "41412", "V717", "V812", "V4589"]

      assert Enum.map(results, & &1.weighting) == [
               [:none],
               [:none],
               [:none],
               [:none],
               [:positive]
             ]
    end

    test "Codes are unweighted when no prior feedback", %{input_chunk: chunk} do
      results = Coding.process_chunk(chunk)

      assert Enum.map(results, & &1.code) == ["74685", "41412", "V717", "V812"]
      assert Enum.all?(results, &(&1.weighting == [:none]))
    end

    test "Code is ranked higher when prior positive feedback", %{input_chunk: chunk} do
      create_code_feedback!(@feedback_text, true, "V717")
      results = Coding.process_chunk(chunk)

      assert Enum.map(results, & &1.code) == ["V717", "74685", "41412", "V812"]
      assert Enum.map(results, & &1.weighting) == [[:positive], [:none], [:none], [:none]]
    end

    test "Code is ranked lower when prior negative feedback", %{input_chunk: chunk} do
      create_code_feedback!(@feedback_text, false, "74685")
      results = Coding.process_chunk(chunk)

      assert Enum.map(results, & &1.code) == ["41412", "V717", "V812", "74685"]
      assert Enum.map(results, & &1.weighting) == [[:none], [:none], [:none], [:negative]]
    end

    test "Code with low similarity score is removed from result when prior negative feedback", %{
      input_chunk: chunk
    } do
      create_code_feedback!(@feedback_text, false, "V717")
      results = Coding.process_chunk(chunk)

      assert Enum.map(results, & &1.code) == ["74685", "41412", "V812"]
      assert Enum.map(results, & &1.weighting) == [[:none], [:none], [:none]]
    end
  end
end