dicom 0.9.1 → 0.9.2
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.rdoc +17 -0
- data/README.rdoc +16 -3
- data/lib/dicom.rb +3 -1
- data/lib/dicom/anonymizer.rb +35 -54
- data/lib/dicom/d_client.rb +49 -64
- data/lib/dicom/d_object.rb +511 -416
- data/lib/dicom/d_read.rb +21 -34
- data/lib/dicom/d_server.rb +21 -61
- data/lib/dicom/d_write.rb +3 -6
- data/lib/dicom/element.rb +1 -1
- data/lib/dicom/file_handler.rb +14 -9
- data/lib/dicom/image_item.rb +7 -6
- data/lib/dicom/link.rb +42 -77
- data/lib/dicom/logging.rb +158 -0
- data/lib/dicom/parent.rb +9 -8
- data/lib/dicom/sequence.rb +1 -1
- data/lib/dicom/version.rb +1 -1
- metadata +5 -4
data/CHANGELOG.rdoc
CHANGED
@@ -1,9 +1,26 @@
|
|
1
|
+
= 0.9.2
|
2
|
+
|
3
|
+
=== (Not released yet)
|
4
|
+
|
5
|
+
* Enabled the use of lower case tag letters in methods which previously required the use of upper case letters.
|
6
|
+
* Added new DObject class methods to offload DObject#new:
|
7
|
+
* DObject#read is the new preferred method for reading a DICOM file.
|
8
|
+
* DObject#parse is the new preferred method for parsing an encoded DICOM string.
|
9
|
+
* The experimental feature of retrieving a DICOM file through http was moved to DObject#get.
|
10
|
+
* Calling DObject with a string argument was deprecated.
|
11
|
+
* Introduced proper logging capabilities which replaced the simple message printouts to STDOUT:
|
12
|
+
* Based on the Logger class of the Ruby Standard Library.
|
13
|
+
* Automatically integrates with the Rails logger in a Rails application.
|
14
|
+
* Supports information levels, logging to file, and more as available in the Ruby Logger.
|
15
|
+
|
16
|
+
|
1
17
|
= 0.9.1
|
2
18
|
|
3
19
|
=== 27th May, 2011
|
4
20
|
|
5
21
|
* Fixed a regression in 0.9 where ruby-dicom would cause a Rails application to crash.
|
6
22
|
|
23
|
+
|
7
24
|
= 0.9
|
8
25
|
|
9
26
|
=== 17th May, 2011
|
data/README.rdoc
CHANGED
@@ -23,7 +23,7 @@ communication modalities like querying, moving, sending and receiving files.
|
|
23
23
|
=== Read, modify and write
|
24
24
|
|
25
25
|
# Read file:
|
26
|
-
obj = DObject.
|
26
|
+
obj = DObject.read("some_file.dcm")
|
27
27
|
# Extract the Patient's Name value:
|
28
28
|
obj.patients_name.value
|
29
29
|
# Add or modify the Patient's Name element:
|
@@ -72,6 +72,18 @@ communication modalities like querying, moving, sending and receiving files.
|
|
72
72
|
s = DServer.new(104, :host_ae => "MY_DICOM_SERVER")
|
73
73
|
s.start_scp("C:/temp/")
|
74
74
|
|
75
|
+
=== Log settings
|
76
|
+
|
77
|
+
# Change the log level so that only error messages are displayed:
|
78
|
+
DICOM.logger.level = Logger::ERROR
|
79
|
+
# Setting up a simple file log:
|
80
|
+
l = Logger.new('my_logfile.log')
|
81
|
+
DICOM.logger = l
|
82
|
+
# Create a logger which ages logfile daily/monthly:
|
83
|
+
DICOM.logger = Logger.new('foo.log', 'daily')
|
84
|
+
DICOM.logger = Logger.new('foo.log', 'monthly')
|
85
|
+
|
86
|
+
|
75
87
|
=== IRB Tip
|
76
88
|
|
77
89
|
When working with Ruby DICOM in irb, you may be annoyed with all the information
|
@@ -120,7 +132,8 @@ Please don't hesitate to email me if you have any feedback related to this proje
|
|
120
132
|
|
121
133
|
* {Christoffer Lervåg}[https://github.com/dicom]
|
122
134
|
* {John Axel Eriksson}[https://github.com/johnae]
|
135
|
+
* {Kamil Bujniewicz}[https://github.com/icdark]
|
123
136
|
* {Donnie Millar}[https://github.com/dmillar]
|
124
|
-
* Björn Albers
|
137
|
+
* {Björn Albers}[https://github.com/bjoernalbers]
|
125
138
|
* {Lars Benner}[https://github.com/Maturin]
|
126
|
-
* {Steven Bedrick}[https://github.com/stevenbedrick]
|
139
|
+
* {Steven Bedrick}[https://github.com/stevenbedrick]
|
data/lib/dicom.rb
CHANGED
@@ -11,6 +11,8 @@
|
|
11
11
|
# The rest of the classes visible in the documentation generated by RDoc is in principle
|
12
12
|
# 'private' classes, which are mainly of interest to developers.
|
13
13
|
|
14
|
+
# Logging:
|
15
|
+
require 'dicom/logging'
|
14
16
|
# Core library:
|
15
17
|
# Super classes/modules:
|
16
18
|
require 'dicom/image_processor'
|
@@ -42,4 +44,4 @@ require 'dicom/image_processor_mini_magick'
|
|
42
44
|
require 'dicom/image_processor_r_magick'
|
43
45
|
|
44
46
|
# Extensions (non-core functionality):
|
45
|
-
require 'dicom/anonymizer'
|
47
|
+
require 'dicom/anonymizer'
|
data/lib/dicom/anonymizer.rb
CHANGED
@@ -1,4 +1,3 @@
|
|
1
|
-
|
2
1
|
module DICOM
|
3
2
|
|
4
3
|
# This is a convenience class for handling anonymization of DICOM files.
|
@@ -10,6 +9,7 @@ module DICOM
|
|
10
9
|
# (Clinical Trials De-identification Profiles, DICOM Standards Committee, Working Group 18)
|
11
10
|
#
|
12
11
|
class Anonymizer
|
12
|
+
include Logging
|
13
13
|
|
14
14
|
# A boolean that if set as true will cause all anonymized tags to be blank instead of get some generic value.
|
15
15
|
attr_accessor :blank
|
@@ -26,23 +26,17 @@ module DICOM
|
|
26
26
|
|
27
27
|
# Creates an Anonymizer instance.
|
28
28
|
#
|
29
|
-
# ===
|
30
|
-
#
|
31
|
-
# * <tt>options</tt> -- A hash of parameters.
|
32
|
-
#
|
33
|
-
# === Options
|
29
|
+
# === Notes
|
34
30
|
#
|
35
|
-
# *
|
31
|
+
# * To customize logging behaviour, refer to the Logging module documentation.
|
36
32
|
#
|
37
33
|
# === Examples
|
38
34
|
#
|
35
|
+
# # Create an Anonymizer instance and restrict the log output:
|
39
36
|
# a = Anonymizer.new
|
40
|
-
#
|
41
|
-
# a = Anonymizer.new(:verbose => false)
|
37
|
+
# a.logger.level = Logger::ERROR
|
42
38
|
#
|
43
|
-
def initialize
|
44
|
-
# Default verbosity is true if verbosity hasn't been specified (nil):
|
45
|
-
@verbose = (options[:verbose] == false ? false : true)
|
39
|
+
def initialize
|
46
40
|
# Default value of accessors:
|
47
41
|
@blank = false
|
48
42
|
@enumeration = false
|
@@ -120,7 +114,7 @@ module DICOM
|
|
120
114
|
if pos
|
121
115
|
return @enumerations[pos]
|
122
116
|
else
|
123
|
-
|
117
|
+
logger.warn("The specified tag (#{tag}) was not found in the list of tags to be anonymized.")
|
124
118
|
return nil
|
125
119
|
end
|
126
120
|
end
|
@@ -133,47 +127,45 @@ module DICOM
|
|
133
127
|
#
|
134
128
|
# * Only top level data elements are anonymized!
|
135
129
|
#
|
136
|
-
# === Parameters
|
137
|
-
#
|
138
|
-
# * <tt>verbose</tt> -- Boolean. If set as true, verbose behaviour will be set for the DObject instances that are anonymized. Defaults to false.
|
139
|
-
#
|
140
130
|
#--
|
141
131
|
# FIXME: This method has grown a bit lengthy. Perhaps it should be looked at one day.
|
142
132
|
#
|
143
|
-
def execute
|
133
|
+
def execute
|
144
134
|
# Search through the folders to gather all the files to be anonymized:
|
145
|
-
|
146
|
-
add_msg("Initiating anonymization process.")
|
135
|
+
logger.info("Initiating anonymization process.")
|
147
136
|
start_time = Time.now.to_f
|
148
|
-
|
137
|
+
logger.info("Searching for files...")
|
149
138
|
load_files
|
150
|
-
|
139
|
+
logger.info("Done.")
|
151
140
|
if @files.length > 0
|
152
141
|
if @tags.length > 0
|
153
|
-
|
142
|
+
logger.info(@files.length.to_s + " files have been identified in the specified folder(s).")
|
154
143
|
if @write_path
|
155
144
|
# Determine the write paths, as anonymized files will be written to a separate location:
|
156
|
-
|
145
|
+
logger.info("Processing write paths...")
|
157
146
|
process_write_paths
|
158
|
-
|
147
|
+
logger.info("Done")
|
159
148
|
else
|
160
149
|
# Overwriting old files:
|
161
|
-
|
150
|
+
logger.warn("Separate write folder not specified. Existing DICOM files will be overwritten.")
|
162
151
|
@write_paths = @files
|
163
152
|
end
|
164
153
|
# If the user wants enumeration, we need to prepare variables for storing
|
165
154
|
# existing information associated with each tag:
|
166
155
|
create_enum_hash if @enumeration
|
167
156
|
# Start the read/update/write process:
|
168
|
-
|
157
|
+
logger.info("Initiating read/update/write process. This may take some time...")
|
169
158
|
# Monitor whether every file read/write was successful:
|
170
159
|
all_read = true
|
171
160
|
all_write = true
|
172
161
|
files_written = 0
|
173
162
|
files_failed_read = 0
|
163
|
+
# Temporarily increase the log threshold to suppress messages from the DObject class:
|
164
|
+
anonymizer_level = logger.level
|
165
|
+
logger.level = Logger::FATAL
|
174
166
|
@files.each_index do |i|
|
175
167
|
# Read existing file to DICOM object:
|
176
|
-
obj = DICOM::DObject.
|
168
|
+
obj = DICOM::DObject.read(@files[i])
|
177
169
|
if obj.read_success
|
178
170
|
# Anonymize the desired tags:
|
179
171
|
@tags.each_index do |j|
|
@@ -212,34 +204,35 @@ module DICOM
|
|
212
204
|
files_failed_read += 1
|
213
205
|
end
|
214
206
|
end
|
215
|
-
# Finished anonymizing files.
|
207
|
+
# Finished anonymizing files. Reset the logg threshold:
|
208
|
+
logger.level = anonymizer_level
|
209
|
+
# Print elapsed time and status of anonymization:
|
216
210
|
end_time = Time.now.to_f
|
217
|
-
|
211
|
+
logger.info("Anonymization process completed!")
|
218
212
|
if all_read
|
219
|
-
|
213
|
+
logger.info("All files in the specified folder(s) were SUCCESSFULLY read to DICOM objects.")
|
220
214
|
else
|
221
|
-
|
215
|
+
logger.warn("Some files were NOT successfully read (#{files_failed_read} files). If some folder(s) contain non-DICOM files, this is expected.")
|
222
216
|
end
|
223
217
|
if all_write
|
224
|
-
|
218
|
+
logger.info("All DICOM objects were SUCCESSFULLY written as DICOM files (#{files_written} files).")
|
225
219
|
else
|
226
|
-
|
220
|
+
logger.warn("Some DICOM objects were NOT succesfully written to file. You are advised to investigate the result (#{files_written} files succesfully written).")
|
227
221
|
end
|
228
222
|
# Has user requested enumeration and specified an identity file in which to store the anonymized values?
|
229
223
|
if @enumeration and @identity_file
|
230
|
-
|
224
|
+
logger.info("Writing identity file.")
|
231
225
|
write_identity_file
|
232
|
-
|
226
|
+
logger.info("Done")
|
233
227
|
end
|
234
228
|
elapsed = (end_time-start_time).to_s
|
235
|
-
|
229
|
+
logger.info("Elapsed time: #{elapsed[0..elapsed.index(".")+1]} seconds")
|
236
230
|
else
|
237
|
-
|
231
|
+
logger.warn("No tags were selected for anonymization. Aborting.")
|
238
232
|
end
|
239
233
|
else
|
240
|
-
|
234
|
+
logger.warn("No files were found in specified folders. Aborting.")
|
241
235
|
end
|
242
|
-
add_msg("*******************************************************")
|
243
236
|
end
|
244
237
|
|
245
238
|
# Prints to screen a list of which tags are currently selected for anonymization along with
|
@@ -367,7 +360,7 @@ module DICOM
|
|
367
360
|
if pos
|
368
361
|
return @values[pos]
|
369
362
|
else
|
370
|
-
|
363
|
+
logger.warn("The specified tag (#{tag}) was not found in the list of tags to be anonymized.")
|
371
364
|
return nil
|
372
365
|
end
|
373
366
|
end
|
@@ -377,18 +370,6 @@ module DICOM
|
|
377
370
|
private
|
378
371
|
|
379
372
|
|
380
|
-
# Adds one or more status messages to the log instance array, and if the verbose
|
381
|
-
# instance variable is true, the status message is printed to the screen as well.
|
382
|
-
#
|
383
|
-
# === Parameters
|
384
|
-
#
|
385
|
-
# * <tt>msg</tt> -- Status message string.
|
386
|
-
#
|
387
|
-
def add_msg(msg)
|
388
|
-
puts msg if @verbose
|
389
|
-
@log << msg
|
390
|
-
end
|
391
|
-
|
392
373
|
# Finds the common path (if any) in the instance file path array, by performing a recursive search
|
393
374
|
# on the folders that make up the path of one such file.
|
394
375
|
# Returns the index of the last folder in the path of the selected file that is common for all file paths.
|
@@ -573,4 +554,4 @@ module DICOM
|
|
573
554
|
end
|
574
555
|
|
575
556
|
end
|
576
|
-
end
|
557
|
+
end
|
data/lib/dicom/d_client.rb
CHANGED
@@ -10,6 +10,7 @@ module DICOM
|
|
10
10
|
# FIXME: The code which waits for incoming network packets seems to be very CPU intensive. Perhaps there is a more elegant way to wait for incoming messages?
|
11
11
|
#
|
12
12
|
class DClient
|
13
|
+
include Logging
|
13
14
|
|
14
15
|
# The name of this client (application entity).
|
15
16
|
attr_accessor :ae
|
@@ -23,19 +24,17 @@ module DICOM
|
|
23
24
|
attr_accessor :port
|
24
25
|
# The maximum period the client will wait on an answer from a server before aborting the communication.
|
25
26
|
attr_accessor :timeout
|
26
|
-
# A boolean which defines if notices/warnings/errors will be printed to the screen (true) or not (false).
|
27
|
-
attr_accessor :verbose
|
28
27
|
# An array, where each index contains a hash with the data elements received in a command response (with tags as keys).
|
29
28
|
attr_reader :command_results
|
30
29
|
# An array, where each index contains a hash with the data elements received in a data response (with tags as keys).
|
31
30
|
attr_reader :data_results
|
32
|
-
# An array containing any error messages recorded.
|
33
|
-
attr_reader :errors
|
34
|
-
# An array containing any status messages recorded.
|
35
|
-
attr_reader :notices
|
36
31
|
|
37
32
|
# Creates a DClient instance.
|
38
33
|
#
|
34
|
+
# === Notes
|
35
|
+
#
|
36
|
+
# * To customize logging behaviour, refer to the Logging module documentation.
|
37
|
+
#
|
39
38
|
# === Parameters
|
40
39
|
#
|
41
40
|
# * <tt>host_ip</tt> -- String. The IP adress of the server which you are going to communicate with.
|
@@ -48,7 +47,6 @@ module DICOM
|
|
48
47
|
# * <tt>:host_ae</tt> -- String. The name of the server (application entity).
|
49
48
|
# * <tt>:max_package_size</tt> -- Fixnum. The maximum allowed size of network packages (in bytes).
|
50
49
|
# * <tt>:timeout</tt> -- Fixnum. The maximum period the server will wait on an answer from a client before aborting the communication.
|
51
|
-
# * <tt>:verbose</tt> -- Boolean. If set to false, the DClient instance will run silently and not output warnings and error messages to the screen. Defaults to true.
|
52
50
|
#
|
53
51
|
# === Examples
|
54
52
|
#
|
@@ -66,11 +64,6 @@ module DICOM
|
|
66
64
|
@max_package_size = options[:max_package_size] || 32768 # 16384
|
67
65
|
@timeout = options[:timeout] || 10 # seconds
|
68
66
|
@min_length = 12 # minimum number of bytes to expect in an incoming transmission
|
69
|
-
@verbose = options[:verbose]
|
70
|
-
@verbose = true if @verbose == nil # Default verbosity is 'on'.
|
71
|
-
# Other instance variables:
|
72
|
-
@errors = Array.new # errors and warnings are put in this array
|
73
|
-
@notices = Array.new # information on successful transmissions are put in this array
|
74
67
|
# Variables used for monitoring state of transmission:
|
75
68
|
@association = nil # DICOM Association status
|
76
69
|
@request_approved = nil # Status of our DICOM request
|
@@ -396,14 +389,14 @@ module DICOM
|
|
396
389
|
establish_release
|
397
390
|
else
|
398
391
|
# Failed when loading the specified parameter as DICOM file(s). Will not transmit.
|
399
|
-
|
392
|
+
logger.error(message)
|
400
393
|
end
|
401
394
|
end
|
402
395
|
|
403
396
|
# Tests the connection to the server in a very simple way by negotiating an association and then releasing it.
|
404
397
|
#
|
405
398
|
def test
|
406
|
-
|
399
|
+
logger.info("TESTING CONNECTION...")
|
407
400
|
success = false
|
408
401
|
# Verification SOP Class:
|
409
402
|
set_default_presentation_context(VERIFICATION_SOP)
|
@@ -417,9 +410,9 @@ module DICOM
|
|
417
410
|
establish_release
|
418
411
|
end
|
419
412
|
if success
|
420
|
-
|
413
|
+
logger.info("TEST SUCCSESFUL!")
|
421
414
|
else
|
422
|
-
|
415
|
+
logger.warn("TEST FAILED!")
|
423
416
|
end
|
424
417
|
return success
|
425
418
|
end
|
@@ -429,30 +422,6 @@ module DICOM
|
|
429
422
|
private
|
430
423
|
|
431
424
|
|
432
|
-
# Adds a warning or error message to the instance array holding messages,
|
433
|
-
# and prints the information to the screen if verbose is set.
|
434
|
-
#
|
435
|
-
# === Parameters
|
436
|
-
#
|
437
|
-
# * <tt>error</tt> -- A single error message or an array of error messages.
|
438
|
-
#
|
439
|
-
def add_error(error)
|
440
|
-
puts error if @verbose
|
441
|
-
@errors << error
|
442
|
-
end
|
443
|
-
|
444
|
-
# Adds a notice (information regarding progress or successful communications) to the instance array,
|
445
|
-
# and prints the information to the screen if verbose is set.
|
446
|
-
#
|
447
|
-
# === Parameters
|
448
|
-
#
|
449
|
-
# * <tt>notice</tt> -- A single status message or an array of status messages.
|
450
|
-
#
|
451
|
-
def add_notice(notice)
|
452
|
-
puts notice if @verbose
|
453
|
-
@notices << notice
|
454
|
-
end
|
455
|
-
|
456
425
|
# Returns an array of supported transfer syntaxes for the specified transfer syntax.
|
457
426
|
# For compressed transfer syntaxes, we currently do not support reencoding these to other syntaxes.
|
458
427
|
#
|
@@ -486,11 +455,11 @@ module DICOM
|
|
486
455
|
# Values of importance are extracted and put into instance variables:
|
487
456
|
@association = true
|
488
457
|
@max_pdu_length = info[:max_pdu_length]
|
489
|
-
|
458
|
+
logger.info("Association successfully negotiated with host #{@host_ae} (#{@host_ip}).")
|
490
459
|
# Check if all our presentation contexts was accepted by the host:
|
491
460
|
process_presentation_context_response(info[:pc])
|
492
461
|
else
|
493
|
-
|
462
|
+
logger.error("Association was denied from host #{@host_ae} (#{@host_ip})!")
|
494
463
|
end
|
495
464
|
end
|
496
465
|
end
|
@@ -501,7 +470,7 @@ module DICOM
|
|
501
470
|
@release = false
|
502
471
|
if @abort
|
503
472
|
@link.stop_session
|
504
|
-
|
473
|
+
logger.info("Association has been closed. (#{@host_ae}, #{@host_ip})")
|
505
474
|
else
|
506
475
|
unless @link.session.closed?
|
507
476
|
@link.build_release_request
|
@@ -509,12 +478,12 @@ module DICOM
|
|
509
478
|
info = @link.receive_single_transmission.first
|
510
479
|
@link.stop_session
|
511
480
|
if info[:pdu] == PDU_RELEASE_RESPONSE
|
512
|
-
|
481
|
+
logger.info("Association released properly from host #{@host_ae}.")
|
513
482
|
else
|
514
|
-
|
483
|
+
logger.error("Association released from host #{@host_ae}, but a release response was not registered.")
|
515
484
|
end
|
516
485
|
else
|
517
|
-
|
486
|
+
logger.error("Connection was closed by the host (for some unknown reason) before the association could be released properly.")
|
518
487
|
end
|
519
488
|
end
|
520
489
|
@abort = false
|
@@ -533,33 +502,38 @@ module DICOM
|
|
533
502
|
#
|
534
503
|
# === Parameters
|
535
504
|
#
|
536
|
-
# * <tt>
|
505
|
+
# * <tt>files_or_objects</tt> -- A single file path or an array of paths, or a DObject or an array of DObject instances.
|
537
506
|
#
|
538
|
-
def load_files(
|
507
|
+
def load_files(files_or_objects)
|
508
|
+
files_or_objects = [files_or_objects] unless files_or_objects.is_a?(Array)
|
539
509
|
status = true
|
540
510
|
message = ""
|
541
511
|
objects = Array.new
|
542
512
|
abstracts = Array.new
|
543
513
|
id = 1
|
544
514
|
@presentation_contexts = Hash.new
|
545
|
-
|
546
|
-
|
547
|
-
|
548
|
-
|
515
|
+
files_or_objects.each do |file_or_object|
|
516
|
+
if file_or_object.is_a?(String)
|
517
|
+
# Temporarily increase the log threshold to suppress messages from the DObject class:
|
518
|
+
client_level = logger.level
|
519
|
+
logger.level = Logger::FATAL
|
520
|
+
obj = DObject.read(file_or_object)
|
521
|
+
# Reset the logg threshold:
|
522
|
+
logger.level = client_level
|
549
523
|
if obj.read_success
|
550
524
|
# Load the DICOM object:
|
551
525
|
objects << obj
|
552
526
|
else
|
553
527
|
status = false
|
554
|
-
message = "Failed to
|
528
|
+
message = "Failed to read a DObject from this file: #{file_or_object}"
|
555
529
|
end
|
556
|
-
elsif
|
530
|
+
elsif file_or_object.is_a?(DObject)
|
557
531
|
# Load the DICOM object and its abstract syntax:
|
558
|
-
abstracts <<
|
559
|
-
objects <<
|
532
|
+
abstracts << file_or_object.value("0008,0016")
|
533
|
+
objects << file_or_object
|
560
534
|
else
|
561
535
|
status = false
|
562
|
-
message = "Array contains invalid object #{
|
536
|
+
message = "Array contains invalid object: #{file_or_object.class}."
|
563
537
|
end
|
564
538
|
end
|
565
539
|
# Extract available transfer syntaxes for the various sop classes found amongst these objects
|
@@ -732,7 +706,7 @@ module DICOM
|
|
732
706
|
process_returned_data(segments)
|
733
707
|
end
|
734
708
|
else
|
735
|
-
|
709
|
+
logger.error("Unable to extract SOP Class UID and/or SOP Instance UID for this DICOM object. File will not be sent to its destination.")
|
736
710
|
end
|
737
711
|
end
|
738
712
|
end
|
@@ -767,16 +741,27 @@ module DICOM
|
|
767
741
|
if rejected.length == 0
|
768
742
|
@request_approved = true
|
769
743
|
if @approved_syntaxes.length == 1 and presentation_contexts.length == 1
|
770
|
-
|
744
|
+
logger.info("The presentation context was accepted by host #{@host_ae}.")
|
771
745
|
else
|
772
|
-
|
746
|
+
logger.info("All #{presentation_contexts.length} presentation contexts were accepted by host #{@host_ae} (#{@host_ip}).")
|
773
747
|
end
|
774
748
|
else
|
775
749
|
# We still consider the request 'approved' if at least one context were accepted:
|
776
750
|
@request_approved = true if @approved_syntaxes.length > 0
|
777
|
-
|
778
|
-
|
779
|
-
|
751
|
+
|
752
|
+
logger.error("One or more of your presentation contexts were denied by host #{@host_ae}!")
|
753
|
+
|
754
|
+
@approved_syntaxes.each_pair do |key, value|
|
755
|
+
sntx_k = LIBRARY.get_syntax_description(key)
|
756
|
+
sntx_v = LIBRARY.get_syntax_description(value[1])
|
757
|
+
logger.info("APPROVED: #{sntx_k} (#{sntx_v})")
|
758
|
+
end
|
759
|
+
|
760
|
+
rejected.each_pair do |key, value|
|
761
|
+
sntx_k = LIBRARY.get_syntax_description(key)
|
762
|
+
sntx_v = LIBRARY.get_syntax_description(value[1])
|
763
|
+
logger.error("REJECTED: #{sntx_k} (#{sntx_v})")
|
764
|
+
end
|
780
765
|
end
|
781
766
|
end
|
782
767
|
|
@@ -958,4 +943,4 @@ module DICOM
|
|
958
943
|
end
|
959
944
|
|
960
945
|
end
|
961
|
-
end
|
946
|
+
end
|