404
|
1 #!/usr/bin/python
|
|
2 # -*- coding: utf-8 -*-
|
|
3
|
|
4
|
|
5 URL = 'http://localhost:8042'
|
|
6 TARGET = 'sample'
|
|
7
|
|
8
|
|
9 #
|
|
10 # This sample code shows how to setup a simple, high-performance DICOM
|
|
11 # auto-routing. All the DICOM instances that arrive inside Orthanc
|
|
12 # will be sent to a remote modality. A producer-consumer pattern is
|
|
13 # used. The target modality is specified by the TARGET variable above:
|
|
14 # It must match an entry in the Orthanc configuration file inside the
|
|
15 # "DicomModalities" section.
|
|
16 #
|
|
17 # NOTE: This sample only works with Orthanc >= 0.5.2. Make sure that
|
|
18 # Orthanc was built with "-DCMAKE_BUILD_TYPE=Release" to get the best
|
|
19 # performance.
|
|
20 #
|
|
21
|
|
22 import Queue
|
|
23 import sys
|
|
24 import time
|
|
25 import threading
|
|
26
|
|
27 import RestToolbox
|
|
28
|
|
29
|
|
30 #
|
|
31 # Queue that is shared between the producer and the consumer
|
|
32 # threads. It holds the instances that are still to be sent.
|
|
33 #
|
|
34
|
|
35 queue = Queue.Queue()
|
|
36
|
|
37
|
|
38 #
|
|
39 # The producer thread. It monitors the arrival of new instances into
|
|
40 # Orthanc, and pushes their ID into the shared queue. This code is
|
|
41 # based upon the "ChangesLoop.py" sample code.
|
|
42 #
|
|
43
|
|
44 def Producer(queue):
|
|
45 current = 0
|
|
46
|
|
47 while True:
|
|
48 r = RestToolbox.DoGet(URL + '/changes', {
|
|
49 'since' : current,
|
|
50 'limit' : 4 # Retrieve at most 4 changes at once
|
|
51 })
|
|
52
|
|
53 for change in r['Changes']:
|
|
54 # We are only interested interested in the arrival of new instances
|
|
55 if change['ChangeType'] == 'NewInstance':
|
|
56 queue.put(change['ID'])
|
|
57
|
|
58 current = r['Last']
|
|
59
|
|
60 if r['Done']:
|
|
61 time.sleep(1)
|
|
62
|
|
63
|
|
64 #
|
|
65 # The consumer thread. It continuously reads the instances from the
|
|
66 # queue, and send them to the remote modality. Each time a packet of
|
|
67 # instances is sent, a single DICOM connexion is used, hence improving
|
|
68 # the performance.
|
|
69 #
|
|
70
|
|
71 def Consumer(queue):
|
|
72 TIMEOUT = 0.1
|
|
73
|
|
74 while True:
|
|
75 instances = []
|
|
76
|
|
77 while True:
|
|
78 try:
|
|
79 # Block for a while, waiting for the arrival of a new
|
|
80 # instance
|
|
81 instance = queue.get(True, TIMEOUT)
|
|
82
|
|
83 # A new instance has arrived: Record its ID
|
|
84 instances.append(instance)
|
|
85 queue.task_done()
|
|
86
|
|
87 except Queue.Empty:
|
|
88 # Timeout: No more data was received
|
|
89 break
|
|
90
|
|
91 if len(instances) > 0:
|
|
92 print 'Sending a packet of %d instances' % len(instances)
|
|
93 start = time.time()
|
|
94
|
|
95 # Send all the instances with a single DICOM connexion
|
|
96 RestToolbox.DoPost('%s/modalities/sample/store' % URL, instances)
|
|
97
|
|
98 # Remove all the instances from Orthanc
|
|
99 for instance in instances:
|
|
100 RestToolbox.DoDelete('%s/instances/%s' % (URL, instance))
|
|
101
|
|
102 end = time.time()
|
|
103 print 'The packet of %d instances has been sent in %d seconds' % (len(instances), end - start)
|
|
104
|
|
105
|
|
106 #
|
|
107 # Thread to display the progress
|
|
108 #
|
|
109
|
|
110 def PrintProgress(queue):
|
|
111 while True:
|
|
112 print 'Current queue size: %d' % (queue.qsize())
|
|
113 time.sleep(1)
|
|
114
|
|
115
|
|
116 #
|
|
117 # Start the various threads
|
|
118 #
|
|
119
|
|
120 progress = threading.Thread(None, PrintProgress, None, (queue, ))
|
|
121 progress.daemon = True
|
|
122 progress.start()
|
|
123
|
|
124 producer = threading.Thread(None, Producer, None, (queue, ))
|
|
125 producer.daemon = True
|
|
126 producer.start()
|
|
127
|
|
128 consumer = threading.Thread(None, Consumer, None, (queue, ))
|
|
129 consumer.daemon = True
|
|
130 consumer.start()
|
|
131
|
|
132
|
|
133 #
|
|
134 # Active waiting for Ctrl-C
|
|
135 #
|
|
136
|
|
137 while True:
|
|
138 time.sleep(0.1)
|