]> Creatis software - creaImageIO.git/blob - src/creaImageIOTreeDescriptor.cpp
#3185 creaImageIO Feature New Normal - Clean code
[creaImageIO.git] / src / creaImageIOTreeDescriptor.cpp
1 /*
2 # ---------------------------------------------------------------------
3 #
4 # Copyright (c) CREATIS (Centre de Recherche en Acquisition et Traitement de l'Image 
5 #                        pour la Santé)
6 # Authors : Eduardo Davila, Frederic Cervenansky, Claire Mouton
7 # Previous Authors : Laurent Guigues, Jean-Pierre Roux
8 # CreaTools website : www.creatis.insa-lyon.fr/site/fr/creatools_accueil
9 #
10 #  This software is governed by the CeCILL-B license under French law and 
11 #  abiding by the rules of distribution of free software. You can  use, 
12 #  modify and/ or redistribute the software under the terms of the CeCILL-B 
13 #  license as circulated by CEA, CNRS and INRIA at the following URL 
14 #  http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html 
15 #  or in the file LICENSE.txt.
16 #
17 #  As a counterpart to the access to the source code and  rights to copy,
18 #  modify and redistribute granted by the license, users are provided only
19 #  with a limited warranty  and the software's author,  the holder of the
20 #  economic rights,  and the successive licensors  have only  limited
21 #  liability. 
22 #
23 #  The fact that you are presently reading this means that you have had
24 #  knowledge of the CeCILL-B license and that you accept its terms.
25 # ------------------------------------------------------------------------
26 */
27
28
29 #include <creaImageIOTreeDescriptor.h>
30 #include <boost/algorithm/string/split.hpp>
31 #include <boost/algorithm/string/replace.hpp>
32 #include <creaImageIOSystem.h>
33 #include <boost/filesystem.hpp>
34
35
36 #include <fstream>
37
38
39 namespace creaImageIO
40 {
41
42   namespace tree
43   {
44
45     //==================================================================
46     /// The attribute is hidden (not visible to user)
47     const unsigned int AttributeDescriptor::PRIVATE = 1;
48     /// The attribute enters in unique identifier constitution 
49     const unsigned int AttributeDescriptor::IDENTIFIER = 2;
50     /// The attribute can be edited
51     const unsigned int AttributeDescriptor::EDITABLE = 3;
52     /// the attribute describes the node
53     const unsigned int AttributeDescriptor::LABEL = 4;
54     //==================================================================
55
56     //==================================================================
57     Descriptor::Descriptor()
58     {
59       CreateLevel0Descriptor();
60     }
61     //==================================================================
62
63    //==================================================================
64     Descriptor::~Descriptor()
65     {
66     }
67     //==================================================================
68
69     //==================================================================
70     void Descriptor::CreateLevel0Descriptor()
71     {
72       Add(LevelDescriptor("Root"));
73     }
74     //==================================================================
75     
76     //==================================================================
77     /// Creates the default descriptor
78     void Descriptor::CreateDefault()
79     {
80       // clears the existing one
81       Clear();
82       
83       // Creates the level 0 descriptor 
84       CreateLevel0Descriptor();
85       // Creates the attribute "Name"
86       Add(AttributeDescriptor("Name","Name",
87                               AttributeDescriptor::LABEL),0);
88       
89       // Patient level
90       Add(LevelDescriptor("Patient"));
91       Add(AttributeDescriptor("NumberOfChildren","#Series",0),1);   // Number of Series
92       Add(AttributeDescriptor(0x0010,0x0010,   // Patient name
93                               AttributeDescriptor::LABEL),1);
94       Add(AttributeDescriptor(0x0010,0x0040),1); // Patient sex
95       Add(AttributeDescriptor(0x0010,0x0030),1); // Patient birthday
96       Add(AttributeDescriptor(0x0010,0x0020,   // Patient ID
97                               AttributeDescriptor::IDENTIFIER),1);
98
99       // Study-series level
100       Add(LevelDescriptor("Series"));
101       Add(AttributeDescriptor("NumberOfChildren","#Images",0),2);   // Number of images
102       Add(AttributeDescriptor(0x0008,0x0060,    // Modality
103                               AttributeDescriptor::LABEL),2);
104       Add(AttributeDescriptor(0x0008,0x1030),2); // Study Description
105       Add(AttributeDescriptor(0x0008,0x103E),2); // Description
106       Add(AttributeDescriptor(0x0008,0x0080),2); // Institution Name
107       Add(AttributeDescriptor(0x0008,0x0081),2); // Institution Adress
108       Add(AttributeDescriptor(0x0008,0x1010),2); // Station Name
109       Add(AttributeDescriptor(0x0008,0x1048),2); // Physician of Record
110       Add(AttributeDescriptor(0x0008,0x1050),2); // Performing Physician's Name
111       Add(AttributeDescriptor(0x0018,0x1030),2); // Protocol Name
112
113       Add(AttributeDescriptor(0x0020,0x0010),2); // Study ID
114       Add(AttributeDescriptor(0x0008,0x0020),2); // Study Date
115       Add(AttributeDescriptor(0x0008,0x0030),2); // Study Time
116       Add(AttributeDescriptor(0x0008,0x0050),2); // Study Accession Number
117       Add(AttributeDescriptor(0x0008,0x0005),2); // Specific character set
118       Add(AttributeDescriptor(0x0008,0x0021),2); // Series Date
119       Add(AttributeDescriptor(0x0008,0x0031),2); // Series time
120
121       Add(AttributeDescriptor(0x0020,0x000D   // Study Instance UID  
122                                                     ),2);//AttributeDescriptor::IDENTIFIER),2);
123       Add(AttributeDescriptor(0x0020,0x000E,   // Series Instance UID  
124                                 AttributeDescriptor::IDENTIFIER),2);
125       // |
126       //                        AttributeDescriptor::LABEL),2);
127      
128
129       // Image level
130       Add(LevelDescriptor("Image"));
131
132       Add(AttributeDescriptor(0x0020,0x0013),3); // Image Number
133
134       Add(AttributeDescriptor(0x0028,0x0010),3); // Rows
135       Add(AttributeDescriptor(0x0028,0x0011),3); // Columns
136       Add(AttributeDescriptor(0x0028,0x0012),3); // Planes
137       Add(AttributeDescriptor(0x0028,0x0002),3); // Sample per pixels
138       Add(AttributeDescriptor(0x0028,0x0008),3); // Number of Frames 
139       Add(AttributeDescriptor(0x0028,0x0004),3); // Photometric Interpretation
140       Add(AttributeDescriptor(0x0028,0x0103),3); // Pixel Representation
141
142       Add(AttributeDescriptor(0x0020,0x0032),3); // Image Position Patient
143       Add(AttributeDescriptor(0x0020,0x0037),3); // Image Orientation Patient
144       Add(AttributeDescriptor(0x0020,0x1041),3); // Slice Location
145       Add(AttributeDescriptor(0x0028,0x0006),3); // Planar Configuration
146
147       Add(AttributeDescriptor(0x0028,0x0030),3); // Pixel Spacing
148       Add(AttributeDescriptor(0x0028,0x0100),3); // AlocatedBits
149       Add(AttributeDescriptor(0x0028,0x0101),3); // StoredBits
150
151       Add(AttributeDescriptor(0x0008,0x0008),3); // Image Type
152       Add(AttributeDescriptor(0x0008,0x0023),3); // Content Date
153       Add(AttributeDescriptor(0x0008,0x0033),3); // Content Time
154
155       Add(AttributeDescriptor(0x0020,0x4000),3); // Image Comments
156
157       Add(AttributeDescriptor(0x0004,0x1500,   // File Name
158                                 AttributeDescriptor::LABEL),3);
159       Add(AttributeDescriptor(0x0028,0x1052),3); // Rescale Intercept
160       Add(AttributeDescriptor(0x0028,0x1053),3); // Rescale Slope
161
162       Add(AttributeDescriptor(0x0050,0x0004),3); // Calibration Image
163
164       Add(AttributeDescriptor(0x0020,0x0052   // Frame Reference UID
165                                            ),3);
166       Add(AttributeDescriptor(0x0008,0x0016),3); // SOP Class UID
167       Add(AttributeDescriptor("FullFileName",  // Full file name
168                                 "Full file name",
169                                 AttributeDescriptor::IDENTIFIER),3); 
170
171     }
172
173         //////////////////////////////////////////////////////////////
174         // create a descriptor (name, attributes...) from a file)       //
175         // @param : file path                                           //
176         // return : -                                                   //
177         //////////////////////////////////////////////////////////////
178         void Descriptor::createDescriptorfromFile(const std::string &i_name)
179         {
180                 Clear();
181                 
182                 // read file and put in buffer
183                 std::ifstream i_file(i_name.c_str());
184                 std::stringstream buffer;
185                 buffer << i_file.rdbuf();
186                 std::string line;
187                 bool bname;
188                 int ilevel = -1;
189
190                 
191                 while(std::getline(buffer, line))
192                 {
193                         if(line =="<level>")
194                         {       //increment levels.
195                                 ilevel++;
196                                 bname = true;
197                         }
198                         else if(bname)
199                         {
200                                 // For each level, a name to describe it
201                                 Add(LevelDescriptor(line));
202                                 bname = false;
203                         }
204                         else if(line.empty()) // to avoid end line
205                         {
206                                 return;
207                         }
208                         else
209                         { 
210                                 // split line to find all tags
211                                 std::vector<std::string> descriptors;
212                                 std::string separator = " ";
213                                 std::string::size_type last_pos = line.find_first_not_of(separator);
214                                 //find first separator
215                                 std::string::size_type pos = line.find_first_of(separator, last_pos);
216                                 while(std::string::npos != pos || std::string::npos != last_pos)
217                                 {
218                                         descriptors.push_back(line.substr(last_pos, pos - last_pos));
219                                         last_pos = line.find_first_not_of(separator, pos);
220                                         pos = line.find_first_of(separator, last_pos);
221                                 }
222                                 
223                                 // By default, the last tag is at zero and not recorded but if take in count
224                                 unsigned int flag = 0;
225                                 if(descriptors.size() == 4)
226                                 {
227                                         std::stringstream val;
228                                         val << std::dec << descriptors[3];
229                                         val>> flag;
230                                 }
231
232                                 // if Dicom tag, use "group" and "element" descriptor
233                                 if(descriptors[0] == "D")
234                                 {       std::stringstream val, val2;
235                                         unsigned short group;
236                                         unsigned short element;
237                                         val <<   std::dec << descriptors[1] ;
238                                         val >> std::hex >> group;
239                                         val2 << std::dec <<  descriptors[2];
240                                         val2 >> std::hex >> element;
241                                         Add(AttributeDescriptor( group,element,flag), ilevel);
242                                 }
243
244                                 else if(descriptors[0].find("#") != -1)
245                                 {
246                                         // commented line continue to next line
247                                 }
248                                 else
249                                 {       boost::algorithm::replace_all(descriptors[2],"_"," ");
250                                         Add(AttributeDescriptor( descriptors[1].c_str(),descriptors[2].c_str(),flag), ilevel);
251                                 }
252                         }
253                 }
254         }
255
256     //==================================================================
257
258     //==================================================================
259     /// Adds a LevelDescriptor at the end of the list
260     void Descriptor::Add(const LevelDescriptor& d)
261     {
262       mLevelDescriptorList.push_back(d);
263     }
264     //==================================================================
265     
266     //==================================================================  
267     /// Adds an AttributeDescriptor to level l
268     void Descriptor::Add(const AttributeDescriptor& d, int l)
269     {
270       mLevelDescriptorList[l].Add(d);
271       // TO DO : update DicomTagToName and NameToDicomTag map
272     }
273     //==================================================================
274
275     //==================================================================
276     /// Clears the Descriptor
277     void Descriptor::Clear()
278     {
279       mLevelDescriptorList.clear();
280     }
281
282     //==================================================================
283
284     //==================================================================
285     /// Builds the key to value map of all the attributes of the tree
286     void Descriptor::BuildAttributeMap( std::map<std::string,std::string>& map ) const
287     {
288       map.clear();
289       LevelDescriptorListType::const_iterator l;
290       for (l = GetLevelDescriptorList().begin();
291            l!= GetLevelDescriptorList().end();
292            ++l)
293         {
294           LevelDescriptor::AttributeDescriptorListType::const_iterator a;
295           for (a = l->GetAttributeDescriptorList().begin();
296                a!= l->GetAttributeDescriptorList().end();
297                ++a)
298             {
299               map[a->GetKey()]="";
300             }
301         }
302     }
303
304         
305     //==================================================================
306         // test if an attribute is present in DescriptionList
307         // return level's name
308         const std::string Descriptor::isExist(const std::string i_attr)
309         {
310                 std::string name = "";
311                 LevelDescriptorListType::const_iterator l = GetLevelDescriptorList().begin();
312                 for (;     l!= GetLevelDescriptorList().end(); ++l)
313                 {
314                         LevelDescriptor::AttributeDescriptorListType::const_iterator a = l->GetAttributeDescriptorList().begin();
315                 for(;a!= l->GetAttributeDescriptorList().end(); ++a)
316                         {
317                                 if (a->GetKey() == i_attr)
318                                 {
319                                         name = l->GetName();
320                                         break;
321                                 }
322                         }
323                 }
324                 return name.c_str();
325         }
326   }
327 }