line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
#!/usr/bin/perl |
2
|
|
|
|
|
|
|
|
3
|
|
|
|
|
|
|
package PDL::IO::Dcm::Plugins::Primitive; |
4
|
1
|
|
|
1
|
|
819
|
use Exporter; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
32
|
|
5
|
1
|
|
|
1
|
|
3
|
use PDL; |
|
1
|
|
|
|
|
1
|
|
|
1
|
|
|
|
|
4
|
|
6
|
1
|
|
|
1
|
|
2231
|
use strict; |
|
1
|
|
|
|
|
1
|
|
|
1
|
|
|
|
|
15
|
|
7
|
1
|
|
|
1
|
|
3
|
use PDL::NiceSlice; |
|
1
|
|
|
|
|
5
|
|
|
1
|
|
|
|
|
4
|
|
8
|
|
|
|
|
|
|
#use 5.10.0; |
9
|
|
|
|
|
|
|
|
10
|
|
|
|
|
|
|
|
11
|
|
|
|
|
|
|
our @ISA=qw/Exporter/; |
12
|
|
|
|
|
|
|
our @EXPORT_OK=qw/populate_header setup_dcm/; |
13
|
|
|
|
|
|
|
|
14
|
|
|
|
|
|
|
sub setup_dcm { |
15
|
0
|
|
|
0
|
1
|
|
my $opt=shift; |
16
|
0
|
0
|
|
|
|
|
$opt={} unless (ref($opt) eq 'HASH'); # ensure hash context |
17
|
|
|
|
|
|
|
# split on series number by default |
18
|
0
|
|
|
|
|
|
$$opt{id}=\&PDL::IO::Dcm::sort_series; |
19
|
0
|
|
|
|
|
|
$$opt{dim_order}=[0,1]; |
20
|
0
|
|
|
|
|
|
$$opt{sort}=\&populate_header; |
21
|
0
|
|
|
|
|
|
$$opt{duplicates}=\&handle_duplicates; |
22
|
0
|
|
|
|
|
|
$$opt{delete_raw}=1; # deletes the raw_dicom structure after parsing |
23
|
0
|
|
|
|
|
|
$$opt{Dimensions}=[qw/x y InstanceNumber n/]; |
24
|
0
|
|
|
|
|
|
$opt; |
25
|
|
|
|
|
|
|
} |
26
|
|
|
|
|
|
|
|
27
|
|
|
|
|
|
|
sub populate_header { |
28
|
0
|
|
|
0
|
1
|
|
my $dicom =shift; |
29
|
0
|
|
|
|
|
|
my $piddle=shift; |
30
|
0
|
|
|
|
|
|
my $in=$dicom->getValue('InstanceNumber'); |
31
|
0
|
|
|
|
|
|
$piddle->hdr->{dcm_key}=$piddle->hdr->{dicom}->{'SOP Instance UID'}; |
32
|
0
|
|
|
|
|
|
my $pos=pdl(ushort,$in-1,0); |
33
|
0
|
|
|
|
|
|
$piddle->hdr->{dim_idx}=$pos; |
34
|
0
|
|
|
|
|
|
return $in; |
35
|
|
|
|
|
|
|
} |
36
|
|
|
|
|
|
|
|
37
|
|
|
|
|
|
|
sub handle_duplicates { |
38
|
0
|
|
|
0
|
1
|
|
my $stack=shift; |
39
|
0
|
|
|
|
|
|
my $dcm=shift; |
40
|
|
|
|
|
|
|
#my $str=',,'.$dcm->hdr->{dim_idx}->(0); |
41
|
|
|
|
|
|
|
#say "duplicate ",$dcm->hdr->{dim_idx}, $stack->info; |
42
|
0
|
|
|
|
|
|
my $idx=$dcm->hdr->{dim_idx}; |
43
|
0
|
|
|
|
|
|
my $n=$idx(1); |
44
|
|
|
|
|
|
|
#say "$n - idx: ",$idx->info; |
45
|
|
|
|
|
|
|
# increase the second index until we find an empty space |
46
|
|
|
|
|
|
|
# data flow should store |
47
|
0
|
|
|
|
|
|
do { |
48
|
|
|
|
|
|
|
#say "$idx ",$stack(list ($idx);-),"; "; |
49
|
|
|
|
|
|
|
#print "$idx n $n exists? ",$stack(list($idx);-),"\n"; |
50
|
|
|
|
|
|
|
#say $n," >= shape ",$stack->shape->(-1); |
51
|
0
|
|
|
|
|
|
$n++; |
52
|
0
|
0
|
|
|
|
|
if (sclr $stack->shape->(-1) <= ($n)) { |
53
|
|
|
|
|
|
|
#say "growing $n",$stack->shape->(-1); |
54
|
0
|
|
|
|
|
|
$stack=$stack->mv(-1,0)->append(0)->mv(0,-1); |
55
|
|
|
|
|
|
|
} |
56
|
0
|
0
|
|
|
|
|
barf "This is impossible $n, $idx, ",$stack($idx(0),;-) if $n>2; |
57
|
|
|
|
|
|
|
} while ($stack(list ($idx))); |
58
|
|
|
|
|
|
|
#say "new dim_dix ",$dcm->hdr->{dim_idx}, $stack->info; |
59
|
|
|
|
|
|
|
#$dcm->hdr->{dim_idx}= |
60
|
|
|
|
|
|
|
#$stack->(,,list($dcm->hdr->{dim_idx}),$n).=$dcm; |
61
|
|
|
|
|
|
|
#"This entry (". $dcm->hdr->{dim_idx}->($order). |
62
|
|
|
|
|
|
|
#max ($data{$pid}->(,,list $dcm->hdr->{dim_idx}->($order))). |
63
|
|
|
|
|
|
|
#") is already set! This should not happen, please file a bug report!\n"; |
64
|
0
|
|
|
|
|
|
$stack; |
65
|
|
|
|
|
|
|
} |
66
|
|
|
|
|
|
|
=head1 General |
67
|
|
|
|
|
|
|
|
68
|
|
|
|
|
|
|
This module provides simple splitting based on intance number and should be used |
69
|
|
|
|
|
|
|
as template when writing more specific plugin modules. |
70
|
|
|
|
|
|
|
|
71
|
|
|
|
|
|
|
The setup_dcm creates a template options hash. |
72
|
|
|
|
|
|
|
|
73
|
|
|
|
|
|
|
=head1 FUNCTIONS |
74
|
|
|
|
|
|
|
|
75
|
|
|
|
|
|
|
=head2 handle_duplicates |
76
|
|
|
|
|
|
|
|
77
|
|
|
|
|
|
|
If more data with the same series/instance number arrive -- can happen -- the second |
78
|
|
|
|
|
|
|
index is incremented until a free slot is found. It is up to the user to sort the mess, |
79
|
|
|
|
|
|
|
i.e. write/use a more sophisticated plugin. |
80
|
|
|
|
|
|
|
|
81
|
|
|
|
|
|
|
=head2 populate_header |
82
|
|
|
|
|
|
|
|
83
|
|
|
|
|
|
|
Here happens the vendor/modallity specific stuff like parsing private fields. |
84
|
|
|
|
|
|
|
It is required to set the IcePos and dcm_key fields in the piddle header. dcm_key |
85
|
|
|
|
|
|
|
serves mainly as a unique identifier, IcePos is an index piddle. |
86
|
|
|
|
|
|
|
|
87
|
|
|
|
|
|
|
=head2 setup_dcm |
88
|
|
|
|
|
|
|
|
89
|
|
|
|
|
|
|
sets useful options for this modality. Should accept a hash ref and return one. |
90
|
|
|
|
|
|
|
|
91
|
|
|
|
|
|
|
=head2 sort_protid |
92
|
|
|
|
|
|
|
|
93
|
|
|
|
|
|
|
alternative to split based on lProtID (matches raw data key) |
94
|
|
|
|
|
|
|
|
95
|
|
|
|
|
|
|
=cut |
96
|
|
|
|
|
|
|
|
97
|
|
|
|
|
|
|
1; |