dicom 0.9.2 → 0.9.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGELOG.rdoc +20 -1
- data/README.rdoc +26 -17
- data/lib/dicom.rb +32 -28
- data/lib/dicom/anonymizer.rb +187 -49
- data/lib/dicom/audit_trail.rb +117 -0
- data/lib/dicom/constants.rb +1 -2
- data/lib/dicom/d_client.rb +13 -13
- data/lib/dicom/d_object.rb +50 -22
- data/lib/dicom/d_read.rb +9 -9
- data/lib/dicom/d_server.rb +14 -10
- data/lib/dicom/d_write.rb +6 -6
- data/lib/dicom/deprecated.rb +73 -0
- data/lib/dicom/element.rb +37 -5
- data/lib/dicom/elemental.rb +4 -4
- data/lib/dicom/file_handler.rb +10 -10
- data/lib/dicom/image_item.rb +28 -12
- data/lib/dicom/item.rb +36 -4
- data/lib/dicom/link.rb +1 -1
- data/lib/dicom/logging.rb +0 -0
- data/lib/dicom/parent.rb +41 -41
- data/lib/dicom/ruby_extensions.rb +6 -4
- data/lib/dicom/sequence.rb +34 -2
- data/lib/dicom/stream.rb +9 -2
- data/lib/dicom/variables.rb +19 -0
- data/lib/dicom/version.rb +1 -1
- metadata +30 -17
@@ -0,0 +1,117 @@
|
|
1
|
+
module DICOM
|
2
|
+
|
3
|
+
# The AuditTrail class handles key/value storage for the Anonymizer.
|
4
|
+
# When using the advanced Anonymization options such as enumeration
|
5
|
+
# and UID replacement, the AuditTrail class keeps track of key/value
|
6
|
+
# pairs and dumps this information to a text file using the json format.
|
7
|
+
# This enables us to ensure a unique relationship between the anonymized
|
8
|
+
# values and the original values, as well as preserving this relationship
|
9
|
+
# for later restoration of original values.
|
10
|
+
#
|
11
|
+
class AuditTrail
|
12
|
+
|
13
|
+
# The hash used for storing the key/value pairs of this instace.
|
14
|
+
attr_reader :dictionary
|
15
|
+
|
16
|
+
# Creates a new AuditTrail instance by loading the information stored
|
17
|
+
# in the specified file.
|
18
|
+
#
|
19
|
+
# === Parameters
|
20
|
+
#
|
21
|
+
# * <tt>file_name</tt> -- The path to a file containing a previously stored audit trail.
|
22
|
+
#
|
23
|
+
def self.read(file_name)
|
24
|
+
audit_trail = AuditTrail.new
|
25
|
+
audit_trail.load(file_name)
|
26
|
+
return audit_trail
|
27
|
+
end
|
28
|
+
|
29
|
+
# Creates a new AuditTrail instance.
|
30
|
+
#
|
31
|
+
def initialize
|
32
|
+
# The AuditTrail requires JSON for serialization:
|
33
|
+
require 'json'
|
34
|
+
# Define the key/value hash used for tag records:
|
35
|
+
@dictionary = Hash.new
|
36
|
+
end
|
37
|
+
|
38
|
+
# Adds a tag record to the log.
|
39
|
+
#
|
40
|
+
# === Parameters
|
41
|
+
#
|
42
|
+
# * <tt>tag</tt> -- The tag string (e.q. "0010,0010").
|
43
|
+
# * <tt>original</tt> -- The original value (e.q. "John Doe").
|
44
|
+
# * <tt>replacement</tt> -- The replacement value (e.q. "Patient1").
|
45
|
+
#
|
46
|
+
def add_record(tag, original, replacement)
|
47
|
+
@dictionary[tag] = Hash.new unless @dictionary.key?(tag)
|
48
|
+
@dictionary[tag][original] = replacement
|
49
|
+
end
|
50
|
+
|
51
|
+
# Loads the key/value dictionary hash from a specified file.
|
52
|
+
#
|
53
|
+
# === Parameters
|
54
|
+
#
|
55
|
+
# * <tt>file_name</tt> -- The path to a file containing a previously stored audit trail.
|
56
|
+
#
|
57
|
+
def load(file_name)
|
58
|
+
@dictionary = JSON.load(File.new(file_name, "r"))
|
59
|
+
end
|
60
|
+
|
61
|
+
# Retrieves the replacement value used for the given tag and its original value.
|
62
|
+
#
|
63
|
+
# === Parameters
|
64
|
+
#
|
65
|
+
# * <tt>tag</tt> -- The tag string (e.q. "0010,0010").
|
66
|
+
# * <tt>replacement</tt> -- The replacement value (e.q. "Patient1").
|
67
|
+
#
|
68
|
+
def original(tag, replacement)
|
69
|
+
original = nil
|
70
|
+
if @dictionary.key?(tag)
|
71
|
+
original = @dictionary[tag].key(replacement)
|
72
|
+
end
|
73
|
+
return original
|
74
|
+
end
|
75
|
+
|
76
|
+
# Returns the key/value pairs for a specific tag.
|
77
|
+
#
|
78
|
+
# === Parameters
|
79
|
+
#
|
80
|
+
# * <tt>tag</tt> -- The tag string (e.q. "0010,0010").
|
81
|
+
#
|
82
|
+
def records(tag)
|
83
|
+
if @dictionary.key?(tag)
|
84
|
+
return @dictionary[tag]
|
85
|
+
else
|
86
|
+
return Hash.new
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
# Retrieves the replacement value used for the given tag and its original value.
|
91
|
+
#
|
92
|
+
# === Parameters
|
93
|
+
#
|
94
|
+
# * <tt>tag</tt> -- The tag string (e.q. "0010,0010").
|
95
|
+
# * <tt>original</tt> -- The original value (e.q. "John Doe").
|
96
|
+
#
|
97
|
+
def replacement(tag, original)
|
98
|
+
replacement = nil
|
99
|
+
replacement = @dictionary[tag][original] if @dictionary.key?(tag)
|
100
|
+
return replacement
|
101
|
+
end
|
102
|
+
|
103
|
+
# Dumps the key/value pairs to a json string which is written to
|
104
|
+
# file as specified by the @file_name attribute of this instance.
|
105
|
+
#
|
106
|
+
#
|
107
|
+
# === Parameters
|
108
|
+
#
|
109
|
+
# * <tt>file_name</tt> -- The file name string to be used for storing & retrieving key/value pairs on disk.
|
110
|
+
#
|
111
|
+
def write(file_name)
|
112
|
+
str = JSON.pretty_generate(@dictionary)
|
113
|
+
File.open(file_name, 'w') {|f| f.write(str) }
|
114
|
+
end
|
115
|
+
|
116
|
+
end
|
117
|
+
end
|
data/lib/dicom/constants.rb
CHANGED
data/lib/dicom/d_client.rb
CHANGED
@@ -517,12 +517,12 @@ module DICOM
|
|
517
517
|
# Temporarily increase the log threshold to suppress messages from the DObject class:
|
518
518
|
client_level = logger.level
|
519
519
|
logger.level = Logger::FATAL
|
520
|
-
|
520
|
+
dcm = DObject.read(file_or_object)
|
521
521
|
# Reset the logg threshold:
|
522
522
|
logger.level = client_level
|
523
|
-
if
|
523
|
+
if dcm.read_success
|
524
524
|
# Load the DICOM object:
|
525
|
-
objects <<
|
525
|
+
objects << dcm
|
526
526
|
else
|
527
527
|
status = false
|
528
528
|
message = "Failed to read a DObject from this file: #{file_or_object}"
|
@@ -538,10 +538,10 @@ module DICOM
|
|
538
538
|
end
|
539
539
|
# Extract available transfer syntaxes for the various sop classes found amongst these objects
|
540
540
|
syntaxes = Hash.new
|
541
|
-
objects.each do |
|
542
|
-
sop_class =
|
541
|
+
objects.each do |dcm|
|
542
|
+
sop_class = dcm.value("0008,0016")
|
543
543
|
if sop_class
|
544
|
-
transfer_syntaxes = available_transfer_syntaxes(
|
544
|
+
transfer_syntaxes = available_transfer_syntaxes(dcm.transfer_syntax)
|
545
545
|
if syntaxes[sop_class]
|
546
546
|
syntaxes[sop_class] << transfer_syntaxes
|
547
547
|
else
|
@@ -670,10 +670,10 @@ module DICOM
|
|
670
670
|
# conveys the information from the selected DICOM file.
|
671
671
|
#
|
672
672
|
def perform_send(objects)
|
673
|
-
objects.each_with_index do |
|
673
|
+
objects.each_with_index do |dcm, index|
|
674
674
|
# Gather necessary information from the object (SOP Class & Instance UID):
|
675
|
-
sop_class =
|
676
|
-
sop_instance =
|
675
|
+
sop_class = dcm.value("0008,0016")
|
676
|
+
sop_instance = dcm.value("0008,0018")
|
677
677
|
if sop_class and sop_instance
|
678
678
|
# Only send the image if its sop_class has been accepted by the receiver:
|
679
679
|
if @approved_syntaxes[sop_class]
|
@@ -685,11 +685,11 @@ module DICOM
|
|
685
685
|
selected_transfer_syntax = @approved_syntaxes[sop_class][1]
|
686
686
|
# Encode our DICOM object to a binary string which is split up in pieces, sufficiently small to fit within the specified maximum pdu length:
|
687
687
|
# Set the transfer syntax of the DICOM object equal to the one accepted by the SCP:
|
688
|
-
|
688
|
+
dcm.transfer_syntax = selected_transfer_syntax
|
689
689
|
# Remove the Meta group, since it doesn't belong in a DICOM file transfer:
|
690
|
-
|
690
|
+
dcm.delete_group(META_GROUP)
|
691
691
|
max_header_length = 14
|
692
|
-
data_packages =
|
692
|
+
data_packages = dcm.encode_segments(@max_pdu_length - max_header_length, selected_transfer_syntax)
|
693
693
|
@link.build_command_fragment(PDU_DATA, presentation_context_id, COMMAND_LAST_FRAGMENT, @command_elements)
|
694
694
|
@link.transmit
|
695
695
|
# Transmit all but the last data strings:
|
@@ -728,7 +728,7 @@ module DICOM
|
|
728
728
|
presentation_contexts.each do |pc|
|
729
729
|
# Determine what abstract syntax this particular presentation context's id corresponds to:
|
730
730
|
id = pc[:presentation_context_id]
|
731
|
-
raise "Error! Even presentation context ID received in the association response. This is not allowed according to the DICOM standard!" if id
|
731
|
+
raise "Error! Even presentation context ID received in the association response. This is not allowed according to the DICOM standard!" if id.even?
|
732
732
|
abstract_syntax = find_abstract_syntax(id)
|
733
733
|
if pc[:result] == 0
|
734
734
|
accepted_pc += 1
|
data/lib/dicom/d_object.rb
CHANGED
@@ -1,18 +1,18 @@
|
|
1
1
|
# === TODO:
|
2
2
|
#
|
3
|
-
# * The retrieve file network functionality (get_image
|
3
|
+
# * The retrieve file network functionality (#get_image in DClient class) has not been tested.
|
4
4
|
# * Make the networking code more intelligent in its handling of unexpected network communication.
|
5
5
|
# * Full support for compressed image data.
|
6
6
|
# * Read/Write 12 bit image data.
|
7
|
-
# * Full color support (RGB and PALETTE COLOR with
|
8
|
-
# * Support for extraction of multiple encapsulated pixel data frames in
|
7
|
+
# * Full color support (RGB and PALETTE COLOR with #image already implemented).
|
8
|
+
# * Support for extraction of multiple encapsulated pixel data frames in #pixels and #narray.
|
9
9
|
# * Image handling currently ignores DICOM tags like Pixel Aspect Ratio, Image Orientation and (to some degree) Photometric Interpretation.
|
10
10
|
# * More robust and flexible options for reorienting extracted pixel arrays?
|
11
11
|
# * A curious observation: Creating a DLibrary instance is exceptionally slow on Ruby 1.9.1: 0.4 seconds versus ~0.01 seconds on Ruby 1.8.7!
|
12
12
|
# * Add these as github issues and remove this list!
|
13
13
|
|
14
14
|
|
15
|
-
# Copyright 2008-
|
15
|
+
# Copyright 2008-2012 Christoffer Lervag
|
16
16
|
#
|
17
17
|
# This program is free software: you can redistribute it and/or modify
|
18
18
|
# it under the terms of the GNU General Public License as published by
|
@@ -77,12 +77,12 @@ module DICOM
|
|
77
77
|
bin = File.open(file, "rb") { |f| f.read }
|
78
78
|
# Parse the file contents and create the DICOM object:
|
79
79
|
if bin
|
80
|
-
|
80
|
+
dcm = self.parse(bin)
|
81
81
|
else
|
82
|
-
|
83
|
-
|
82
|
+
dcm = self.new
|
83
|
+
dcm.read_success = false
|
84
84
|
end
|
85
|
-
return
|
85
|
+
return dcm
|
86
86
|
end
|
87
87
|
|
88
88
|
# Creates a DObject instance by parsing an encoded binary DICOM string.
|
@@ -102,9 +102,9 @@ module DICOM
|
|
102
102
|
no_header = options[:no_meta]
|
103
103
|
raise ArgumentError, "Invalid argument 'string'. Expected String, got #{string.class}." unless string.is_a?(String)
|
104
104
|
raise ArgumentError, "Invalid option :syntax. Expected String, got #{syntax.class}." if syntax && !syntax.is_a?(String)
|
105
|
-
|
106
|
-
|
107
|
-
return
|
105
|
+
dcm = self.new
|
106
|
+
dcm.read(string, :bin => true, :no_meta => no_header, :syntax => syntax)
|
107
|
+
return dcm
|
108
108
|
end
|
109
109
|
|
110
110
|
# Creates a DObject instance by reading and parsing a DICOM file.
|
@@ -136,12 +136,12 @@ module DICOM
|
|
136
136
|
end
|
137
137
|
# Parse the file contents and create the DICOM object:
|
138
138
|
if bin
|
139
|
-
|
139
|
+
dcm = self.parse(bin)
|
140
140
|
else
|
141
|
-
|
142
|
-
|
141
|
+
dcm = self.new
|
142
|
+
dcm.read_success = false
|
143
143
|
end
|
144
|
-
return
|
144
|
+
return dcm
|
145
145
|
end
|
146
146
|
|
147
147
|
# A boolean set as false. This attribute is included to provide consistency with other object types for the internal methods which use it.
|
@@ -180,12 +180,12 @@ module DICOM
|
|
180
180
|
#
|
181
181
|
# # Load a DICOM file (Deprecated: please use DObject.read() instead):
|
182
182
|
# require 'dicom'
|
183
|
-
#
|
183
|
+
# dcm = DICOM::DObject.new("test.dcm")
|
184
184
|
# # Read a DICOM file that has already been loaded into memory in a binary string (with a known transfer syntax):
|
185
185
|
# # (Deprecated: please use DObject.parse() instead)
|
186
|
-
#
|
186
|
+
# dcm = DICOM::DObject.new(binary_string, :bin => true, :syntax => string_transfer_syntax)
|
187
187
|
# # Create an empty DICOM object
|
188
|
-
#
|
188
|
+
# dcm = DICOM::DObject.new
|
189
189
|
# # Increasing the log message threshold (default level is INFO):
|
190
190
|
# DICOM.logger.level = Logger::WARN
|
191
191
|
#
|
@@ -214,6 +214,16 @@ module DICOM
|
|
214
214
|
end
|
215
215
|
end
|
216
216
|
|
217
|
+
# Returns true if the argument is an instance with attributes equal to self.
|
218
|
+
#
|
219
|
+
def ==(other)
|
220
|
+
if other.respond_to?(:to_dcm)
|
221
|
+
other.send(:state) == state
|
222
|
+
end
|
223
|
+
end
|
224
|
+
|
225
|
+
alias_method :eql?, :==
|
226
|
+
|
217
227
|
# Encodes the DICOM object into a series of binary string segments with a specified maximum length.
|
218
228
|
#
|
219
229
|
# Returns the encoded binary strings in an array.
|
@@ -225,7 +235,7 @@ module DICOM
|
|
225
235
|
#
|
226
236
|
# === Examples
|
227
237
|
#
|
228
|
-
# encoded_strings =
|
238
|
+
# encoded_strings = dcm.encode_segments(16384)
|
229
239
|
#
|
230
240
|
def encode_segments(max_size, transfer_syntax=transfer_syntax)
|
231
241
|
raise ArgumentError, "Invalid argument. Expected an Integer, got #{max_size.class}." unless max_size.is_a?(Integer)
|
@@ -238,6 +248,12 @@ module DICOM
|
|
238
248
|
return w.segments
|
239
249
|
end
|
240
250
|
|
251
|
+
# Generates a Fixnum hash value for this instance.
|
252
|
+
#
|
253
|
+
def hash
|
254
|
+
state.hash
|
255
|
+
end
|
256
|
+
|
241
257
|
# Prints information of interest related to the DICOM object.
|
242
258
|
# Calls the print() method of Parent as well as the information() method of DObject.
|
243
259
|
#
|
@@ -396,6 +412,12 @@ module DICOM
|
|
396
412
|
return info
|
397
413
|
end
|
398
414
|
|
415
|
+
# Returns self.
|
416
|
+
#
|
417
|
+
def to_dcm
|
418
|
+
self
|
419
|
+
end
|
420
|
+
|
399
421
|
# Returns the transfer syntax string of the DObject.
|
400
422
|
#
|
401
423
|
# If a transfer syntax has not been defined in the DObject, a default tansfer syntax is assumed and returned.
|
@@ -447,7 +469,7 @@ module DICOM
|
|
447
469
|
#
|
448
470
|
# === Examples
|
449
471
|
#
|
450
|
-
#
|
472
|
+
# dcm.write(path + "test.dcm")
|
451
473
|
#
|
452
474
|
def write(file_name, options={})
|
453
475
|
raise ArgumentError, "Invalid file_name. Expected String, got #{file_name.class}." unless file_name.is_a?(String)
|
@@ -483,8 +505,8 @@ module DICOM
|
|
483
505
|
end
|
484
506
|
# Source Application Entity Title:
|
485
507
|
Element.new("0002,0016", DICOM.source_app_title, :parent => self) unless exists?("0002,0016")
|
486
|
-
# Group Length:
|
487
|
-
|
508
|
+
# Group Length: Delete the old one (if it exists) before creating a new one.
|
509
|
+
delete("0002,0000")
|
488
510
|
Element.new("0002,0000", meta_group_length, :parent => self)
|
489
511
|
end
|
490
512
|
|
@@ -507,5 +529,11 @@ module DICOM
|
|
507
529
|
return group_length
|
508
530
|
end
|
509
531
|
|
532
|
+
# Returns the attributes (children) of this instance (for comparison purposes).
|
533
|
+
#
|
534
|
+
def state
|
535
|
+
@tags
|
536
|
+
end
|
537
|
+
|
510
538
|
end
|
511
539
|
end
|
data/lib/dicom/d_read.rb
CHANGED
@@ -19,7 +19,7 @@ module DICOM
|
|
19
19
|
# An array which records any status messages that are generated while parsing the DICOM string.
|
20
20
|
attr_reader :msg
|
21
21
|
# A DObject instance which the parsed data elements will be connected to.
|
22
|
-
attr_reader :
|
22
|
+
attr_reader :dcm
|
23
23
|
# A boolean which records whether the DICOM string contained the proper DICOM header signature of 128 bytes + 'DICM'.
|
24
24
|
attr_reader :signature
|
25
25
|
# A boolean which reports whether the DICOM string was parsed successfully (true) or not (false).
|
@@ -30,7 +30,7 @@ module DICOM
|
|
30
30
|
#
|
31
31
|
# === Parameters
|
32
32
|
#
|
33
|
-
# * <tt>
|
33
|
+
# * <tt>dcm</tt> -- A DObject instance which the parsed data elements will be connected to.
|
34
34
|
# * <tt>string</tt> -- A string which specifies either the path of a DICOM file to be loaded, or a binary DICOM string to be parsed.
|
35
35
|
# * <tt>options</tt> -- A hash of parameters.
|
36
36
|
#
|
@@ -40,13 +40,13 @@ module DICOM
|
|
40
40
|
# * <tt>:no_meta</tt> -- Boolean. If true, the parsing algorithm is instructed that the binary DICOM string contains no meta header.
|
41
41
|
# * <tt>:syntax</tt> -- String. If specified, the decoding of the DICOM string will be forced to use this transfer syntax.
|
42
42
|
#
|
43
|
-
def initialize(
|
43
|
+
def initialize(dcm, string=nil, options={})
|
44
44
|
# Set the DICOM object as an instance variable:
|
45
|
-
@
|
45
|
+
@dcm = dcm
|
46
46
|
# If a transfer syntax has been specified as an option for a DICOM object, make sure that it makes it into the object:
|
47
47
|
if options[:syntax]
|
48
48
|
@transfer_syntax = options[:syntax]
|
49
|
-
|
49
|
+
dcm.add(Element.new("0002,0010", options[:syntax])) if dcm.is_a?(DObject)
|
50
50
|
end
|
51
51
|
# Initiate the variables that are used during file reading:
|
52
52
|
init_variables
|
@@ -292,7 +292,7 @@ module DICOM
|
|
292
292
|
length = @stream.decode(bytes, "SL") # (4)
|
293
293
|
end
|
294
294
|
# Check that length is valid (according to the DICOM standard, it must be even):
|
295
|
-
raise "Encountered a Data Element (#{tag}) with an invalid (odd) value length." if length
|
295
|
+
raise "Encountered a Data Element (#{tag}) with an invalid (odd) value length." if length.odd? and length > 0
|
296
296
|
return vr, length
|
297
297
|
end
|
298
298
|
|
@@ -366,7 +366,7 @@ module DICOM
|
|
366
366
|
def switch_syntax
|
367
367
|
# Get the transfer syntax string, unless it has already been provided by keyword:
|
368
368
|
unless @transfer_syntax
|
369
|
-
ts_element = @
|
369
|
+
ts_element = @dcm["0002,0010"]
|
370
370
|
if ts_element
|
371
371
|
@transfer_syntax = ts_element.value
|
372
372
|
else
|
@@ -411,9 +411,9 @@ module DICOM
|
|
411
411
|
# When the file switch from group 0002 to a later group we will update encoding values, and this switch will keep track of that:
|
412
412
|
@switched = false
|
413
413
|
# Keeping track of the data element parent status while parsing the DICOM string:
|
414
|
-
@current_parent = @
|
414
|
+
@current_parent = @dcm
|
415
415
|
# Keeping track of what is the current data element:
|
416
|
-
@current_element = @
|
416
|
+
@current_element = @dcm
|
417
417
|
# Items contained under the pixel data element may contain data directly, so we need a variable to keep track of this:
|
418
418
|
@enc_image = false
|
419
419
|
# Assume header size is zero bytes until otherwise is determined:
|
data/lib/dicom/d_server.rb
CHANGED
@@ -33,6 +33,8 @@ module DICOM
|
|
33
33
|
|
34
34
|
# A customized FileHandler class to use instead of the default FileHandler included with Ruby DICOM.
|
35
35
|
attr_accessor :file_handler
|
36
|
+
# The hostname that the TCPServer binds to.
|
37
|
+
attr_accessor :host
|
36
38
|
# The name of the server (application entity).
|
37
39
|
attr_accessor :host_ae
|
38
40
|
# The maximum allowed size of network packages (in bytes).
|
@@ -61,6 +63,7 @@ module DICOM
|
|
61
63
|
# === Options
|
62
64
|
#
|
63
65
|
# * <tt>:file_handler</tt> -- A customized FileHandler class to use instead of the default FileHandler.
|
66
|
+
# * <tt>:host</tt> -- String. The hostname that the TCPServer binds to. Defaults to '127.0.0.1'.
|
64
67
|
# * <tt>:host_ae</tt> -- String. The name of the server (application entity).
|
65
68
|
# * <tt>:max_package_size</tt> -- Fixnum. The maximum allowed size of network packages (in bytes).
|
66
69
|
# * <tt>:timeout</tt> -- Fixnum. The maximum period the server will wait on an answer from a client before aborting the communication.
|
@@ -79,6 +82,7 @@ module DICOM
|
|
79
82
|
@port = port
|
80
83
|
# Optional parameters (and default values):
|
81
84
|
@file_handler = options[:file_handler] || FileHandler
|
85
|
+
@host = options[:host] || '127.0.0.1'
|
82
86
|
@host_ae = options[:host_ae] || "RUBY_DICOM"
|
83
87
|
@max_package_size = options[:max_package_size] || 32768 # 16384
|
84
88
|
@timeout = options[:timeout] || 10 # seconds
|
@@ -144,14 +148,14 @@ module DICOM
|
|
144
148
|
end
|
145
149
|
end
|
146
150
|
|
147
|
-
#
|
151
|
+
# Deletes a specific abstract syntax from the list of abstract syntaxes that the server will accept.
|
148
152
|
#
|
149
153
|
#
|
150
154
|
# === Parameters
|
151
155
|
#
|
152
156
|
# * <tt>uid</tt> -- An abstract syntax UID string.
|
153
157
|
#
|
154
|
-
def
|
158
|
+
def delete_abstract_syntax(uid)
|
155
159
|
if uid.is_a?(String)
|
156
160
|
@accepted_abstract_syntaxes.delete(uid)
|
157
161
|
else
|
@@ -159,13 +163,13 @@ module DICOM
|
|
159
163
|
end
|
160
164
|
end
|
161
165
|
|
162
|
-
#
|
166
|
+
# Deletes a specific transfer syntax from the list of transfer syntaxes that the server will accept.
|
163
167
|
#
|
164
168
|
# === Parameters
|
165
169
|
#
|
166
170
|
# * <tt>uid</tt> -- A transfer syntax UID string.
|
167
171
|
#
|
168
|
-
def
|
172
|
+
def delete_transfer_syntax(uid)
|
169
173
|
if uid.is_a?(String)
|
170
174
|
@accepted_transfer_syntaxes.delete(uid)
|
171
175
|
else
|
@@ -177,9 +181,9 @@ module DICOM
|
|
177
181
|
#
|
178
182
|
# === Notes
|
179
183
|
#
|
180
|
-
# * Following such a
|
184
|
+
# * Following such a clearance, the user must ensure to add the specific abstract syntaxes that are to be accepted by the server.
|
181
185
|
#
|
182
|
-
def
|
186
|
+
def clear_abstract_syntaxes
|
183
187
|
@accepted_abstract_syntaxes = Hash.new
|
184
188
|
end
|
185
189
|
|
@@ -187,9 +191,9 @@ module DICOM
|
|
187
191
|
#
|
188
192
|
# === Notes
|
189
193
|
#
|
190
|
-
# * Following such a
|
194
|
+
# * Following such a clearance, the user must ensure to add the specific transfer syntaxes that are to be accepted by the server.
|
191
195
|
#
|
192
|
-
def
|
196
|
+
def clear_transfer_syntaxes
|
193
197
|
@accepted_transfer_syntaxes = Hash.new
|
194
198
|
end
|
195
199
|
|
@@ -209,7 +213,7 @@ module DICOM
|
|
209
213
|
logger.info("Started DICOM SCP server on port #{@port}.")
|
210
214
|
logger.info("Waiting for incoming transmissions...\n\n")
|
211
215
|
# Initiate server:
|
212
|
-
@scp = TCPServer.new(@port)
|
216
|
+
@scp = TCPServer.new(@host, @port)
|
213
217
|
# Use a loop to listen for incoming messages:
|
214
218
|
loop do
|
215
219
|
Thread.start(@scp.accept) do |session|
|
@@ -279,7 +283,7 @@ module DICOM
|
|
279
283
|
#
|
280
284
|
# === Notes
|
281
285
|
#
|
282
|
-
# Other things can
|
286
|
+
# Other things can potentially be checked here too, if we want to make the server more strict with regards to what information is received:
|
283
287
|
# * Application context name, calling AE title, called AE title
|
284
288
|
# * Description of error codes are given in the DICOM Standard, PS 3.8, Chapter 9.3.4 (Table 9-21).
|
285
289
|
#
|