fw4spl
SrcLib/patch/fwMDSemanticPatch/src/fwMDSemanticPatch/V1/V2/fwData/Composite.cpp
1 /* ***** BEGIN LICENSE BLOCK *****
2  * FW4SPL - Copyright (C) IRCAD, 2009-2018.
3  * Distributed under the terms of the GNU Lesser General Public License (LGPL) as
4  * published by the Free Software Foundation.
5  * ****** END LICENSE BLOCK ****** */
6 
7 #include "fwMDSemanticPatch/V1/V2/fwData/Composite.hpp"
8 
9 #include <fwAtoms/Blob.hpp>
10 #include <fwAtoms/Boolean.hpp>
11 #include <fwAtoms/Map.hpp>
12 #include <fwAtoms/Numeric.hpp>
13 #include <fwAtoms/Object.hpp>
14 #include <fwAtoms/Object.hxx>
15 #include <fwAtoms/Sequence.hpp>
16 #include <fwAtoms/String.hpp>
17 
18 #include <fwAtomsPatch/helper/functions.hpp>
19 #include <fwAtomsPatch/StructuralCreatorDB.hpp>
20 
21 #include <fwMedData/ActivitySeries.hpp>
22 
23 #include <fwMemory/BufferObject.hpp>
24 
25 #include <fwTools/UUID.hpp>
26 
27 #include <boost/algorithm/string.hpp>
28 
29 #include <string>
30 #include <vector>
31 
32 namespace fwMDSemanticPatch
33 {
34 namespace V1
35 {
36 namespace V2
37 {
38 namespace fwData
39 {
40 
41 typedef std::map< ::fwAtoms::Object::sptr, ::fwAtoms::Object::sptr > Image2ModelType;
42 
44  ::fwAtomsPatch::ISemanticPatch()
45 {
46  m_originClassname = "::fwData::Composite";
47  m_originVersion = "1";
48  this->addContext("MedicalData", "V1", "V2");
49 }
50 
51 // ----------------------------------------------------------------------------
52 
54 {
55 }
56 
57 // ----------------------------------------------------------------------------
58 
61 {
62 }
63 
64 // ----------------------------------------------------------------------------
65 
66 void processPlanning(
67  const ::fwAtoms::Map::sptr& oldCompositeMap,
68  const ::fwAtoms::Sequence::sptr& series,
69  const Image2ModelType& image2Model,
70  ::fwAtomsPatch::IPatch::NewVersionsType& newVersions)
71 {
72  ::fwAtoms::Object::sptr oldPlanningDB = ::fwAtoms::Object::dynamicCast( (*oldCompositeMap)["planningDB"] );
73  ::fwAtoms::Map::sptr oldPlannings = oldPlanningDB->getAttribute< ::fwAtoms::Map >("values");
74 
75  for( ::fwAtoms::Map::value_type oldPlanningAtom : oldPlannings->getValue() )
76  {
77  ::fwAtoms::Map::sptr oldPlanning
78  = ::fwAtoms::Object::dynamicCast(oldPlanningAtom.second)->getAttribute< ::fwAtoms::Map >("values");
79 
80  SLM_ASSERT("Didn't find 'acquisition' in planning",
81  oldPlanning->getValue().find("acquisition") != oldPlanning->getValue().end());
82  ::fwAtoms::Base::sptr acquisition = oldPlanning->getValue().find("acquisition")->second;
83  ::fwAtoms::Object::sptr acqObj = ::fwAtoms::Object::dynamicCast(acquisition);
84  SLM_ASSERT("Failed to cast acquisition to object", acqObj);
85 
86  Image2ModelType::const_iterator it = image2Model.find(newVersions[acqObj]);
87  SLM_ASSERT("Didn't find image series related to acquisition", it != image2Model.end());
88  ::fwAtoms::Object::sptr imageSeries = it->first;
89 
90  ::fwAtoms::Object::sptr resectionDB
91  = ::fwAtoms::Object::dynamicCast(oldPlanning->getValue().find("resectionDB")->second);
92 
93  // Retrieves expert who performed the resection
94  ::fwAtoms::Object::sptr expert
95  = ::fwAtoms::Object::dynamicCast(oldPlanning->getValue().find("expert")->second);
96 
97  ::fwAtoms::Sequence::sptr experts = ::fwAtoms::Sequence::New();
98  experts->push_back( ::fwAtoms::String::dynamicCast(expert->getAttribute< ::fwAtoms::String >("value")));
99 
100  // Retrieves resection information
101  ::fwAtoms::Object::sptr information
102  = ::fwAtoms::Object::dynamicCast(oldPlanning->getValue().find("information")->second);
103  ::fwAtoms::String::sptr informationStr
104  = ::fwAtoms::String::dynamicCast(information->getAttribute< ::fwAtoms::String >("value"));
105 
106  // Retrieves resection date and time
107  ::fwAtoms::Object::sptr dateTimeObj
108  = ::fwAtoms::Object::dynamicCast(oldPlanning->getValue().find("startDateTime")->second);
109  ::fwAtoms::String::sptr dateTimeStr
110  = ::fwAtoms::String::dynamicCast(dateTimeObj->getAttribute< ::fwAtoms::String >("value"));
111 
112  ::fwAtoms::String::sptr time = ::fwAtoms::String::New("");
113  ::fwAtoms::String::sptr date = ::fwAtoms::String::New("");
114 
115  std::string dateTimeStd = dateTimeStr->getString();
116  std::vector< std::string > strs;
117  ::boost::split(strs, dateTimeStd, ::boost::is_any_of(" "));
118 
119  if(strs.size() >= 2)
120  {
121  date->setValue(strs[0]);
122  time->setValue(strs[1]);
123  }
124 
125  ::fwAtomsPatch::StructuralCreatorDB::sptr creators = ::fwAtomsPatch::StructuralCreatorDB::getDefault();
126  ::fwAtoms::Object::sptr newActivitySeries = creators->create( "::fwMedData::ActivitySeries", "1");
127 
128  ::fwAtoms::Object::sptr imgComposite = ::fwAtoms::Object::New();
129  ::fwAtomsPatch::helper::setClassname(imgComposite, "::fwData::Composite");
130  ::fwAtomsPatch::helper::setVersion(imgComposite, "1");
131  ::fwAtomsPatch::helper::generateID(imgComposite);
132  ::fwAtomsPatch::helper::cleanFields(imgComposite);
133 
134  ::fwAtomsPatch::helper::Object imgCompositeHelper(imgComposite);
135  ::fwAtoms::Map::sptr compositeMap = ::fwAtoms::Map::New();
136  compositeMap->insert("OptionalInputImageKey", imageSeries->getAttribute< ::fwAtoms::Object >("image"));
137  imgCompositeHelper.addAttribute("values", compositeMap);
138 
139  ::fwAtoms::Map::sptr activityDataMap = ::fwAtoms::Map::New();
140  activityDataMap->insert("resectionDB", resectionDB);
141  activityDataMap->insert("modelSeries", it->second);
142  activityDataMap->insert("imageSeries", imgComposite);
143 
144  ::fwAtoms::Object::sptr mapObj = ::fwAtoms::Object::New();
145  ::fwAtomsPatch::helper::setClassname(mapObj, "::fwData::Composite");
146  ::fwAtomsPatch::helper::setVersion(mapObj, "1");
147  ::fwAtomsPatch::helper::generateID(mapObj);
148  ::fwAtomsPatch::helper::cleanFields(mapObj);
149 
150  ::fwAtomsPatch::helper::Object mapObjHelper(mapObj);
151  mapObjHelper.addAttribute("values", activityDataMap);
152 
153  ::fwAtomsPatch::helper::Object helperActivity(newActivitySeries);
154  helperActivity.replaceAttribute("activity_config_id", ::fwAtoms::String::New("Resection"));
155  helperActivity.replaceAttribute("data", mapObj);
156 
157  helperActivity.replaceAttribute("modality", ::fwAtoms::String::New("OT") );
158  helperActivity.replaceAttribute("instance_uid", ::fwAtoms::String::New(::fwTools::UUID::generateUUID()));
159  helperActivity.replaceAttribute("date", date);
160  helperActivity.replaceAttribute("time", time);
161  helperActivity.replaceAttribute("performing_physicians_name", experts);
162  helperActivity.replaceAttribute("description", informationStr);
163  helperActivity.replaceAttribute("patient", imageSeries->getAttribute< ::fwAtoms::Object >("patient"));
164  helperActivity.replaceAttribute("study", imageSeries->getAttribute< ::fwAtoms::Object >("study"));
165  helperActivity.replaceAttribute("equipment", imageSeries->getAttribute< ::fwAtoms::Object >("equipment"));
166 
167  series->push_back(newActivitySeries);
168  }
169 }
170 
171 // ----------------------------------------------------------------------------
172 
173 // Convert ProcessingDB Composite into ActivitySeries
174 void processProcessing(
175  const ::fwAtoms::Map::sptr& oldCompositeMap,
176  const ::fwAtoms::Sequence::sptr& series,
177  const Image2ModelType& image2Model,
178  ::fwAtomsPatch::IPatch::NewVersionsType& newVersions)
179 {
180  ::fwAtoms::Object::sptr oldProcessingDB = ::fwAtoms::Object::dynamicCast( (*oldCompositeMap)["processingDB"] );
181 
182  ::fwAtoms::Map::sptr oldProcessings = oldProcessingDB->getAttribute< ::fwAtoms::Map >("values");
183 
184  for( ::fwAtoms::Map::value_type oldProcessingAtom : oldProcessings->getValue() )
185  {
186  ::fwAtoms::Map::sptr oldProcessing
187  = ::fwAtoms::Object::dynamicCast(oldProcessingAtom.second)->getAttribute< ::fwAtoms::Map >("values");
188 
189  // Retrieves expert who performed the resection
190  ::fwAtoms::Object::sptr expert
191  = ::fwAtoms::Object::dynamicCast(oldProcessing->getValue().find("expert")->second);
192 
193  ::fwAtoms::Sequence::sptr experts = ::fwAtoms::Sequence::New();
194  experts->push_back( ::fwAtoms::String::dynamicCast(expert->getAttribute< ::fwAtoms::String >("value")));
195 
196  // Retrieves resection information
197  ::fwAtoms::Object::sptr information
198  = ::fwAtoms::Object::dynamicCast(oldProcessing->getValue().find("information")->second);
199  ::fwAtoms::String::sptr informationStr
200  = ::fwAtoms::String::dynamicCast(information->getAttribute< ::fwAtoms::String >("value"));
201 
202  // Retrieves resection date and time
203  ::fwAtoms::Object::sptr dateTimeObj
204  = ::fwAtoms::Object::dynamicCast(oldProcessing->getValue().find("startDateTime")->second);
205  ::fwAtoms::String::sptr dateTimeStr
206  = ::fwAtoms::String::dynamicCast(dateTimeObj->getAttribute< ::fwAtoms::String >("value"));
207 
208  ::fwAtoms::String::sptr time = ::fwAtoms::String::New("");
209  ::fwAtoms::String::sptr date = ::fwAtoms::String::New("");
210 
211  std::string dateTimeStd = dateTimeStr->getString();
212  std::vector< std::string > strs;
213  ::boost::split(strs, dateTimeStd, ::boost::is_any_of(" "));
214 
215  if(strs.size() >= 2)
216  {
217  date->setValue(strs[0]);
218  time->setValue(strs[1]);
219  }
220 
221  ::fwAtomsPatch::StructuralCreatorDB::sptr creators = ::fwAtomsPatch::StructuralCreatorDB::getDefault();
222  ::fwAtoms::Object::sptr newActivitySeries = creators->create( "::fwMedData::ActivitySeries", "1");
223 
224  ::fwAtoms::Map::sptr activityDataMap = ::fwAtoms::Map::New();
225  activityDataMap->insert("processing", oldProcessingAtom.second);
226 
227  ::fwAtoms::Object::sptr mapObj = ::fwAtoms::Object::New();
228  ::fwAtomsPatch::helper::setClassname(mapObj, "::fwData::Composite");
229  ::fwAtomsPatch::helper::setVersion(mapObj, "1");
230  ::fwAtomsPatch::helper::generateID(mapObj);
231  ::fwAtomsPatch::helper::cleanFields(mapObj);
232 
233  ::fwAtomsPatch::helper::Object mapObjHelper(mapObj);
234  mapObjHelper.addAttribute("values", activityDataMap);
235 
236  ::fwAtomsPatch::helper::Object helperActivity(newActivitySeries);
237  helperActivity.replaceAttribute("activity_config_id", ::fwAtoms::String::New("Processing"));
238  helperActivity.replaceAttribute("data", mapObj);
239 
240  helperActivity.replaceAttribute("modality", ::fwAtoms::String::New("OT") );
241  helperActivity.replaceAttribute("instance_uid", ::fwAtoms::String::New(::fwTools::UUID::generateUUID()));
242  helperActivity.replaceAttribute("date", date);
243  helperActivity.replaceAttribute("time", time);
244  helperActivity.replaceAttribute("performing_physicians_name", experts);
245  helperActivity.replaceAttribute("description", informationStr);
246 
247  // Check if the processing is associated to an acquisition
248  ::fwAtoms::Base::sptr acquisitionSelection = oldProcessing->getValue().find("acquisitionSelection")->second;
249  ::fwAtoms::Object::sptr acqSelectionObj = ::fwAtoms::Object::dynamicCast(acquisitionSelection);
250  SLM_ASSERT("Failed to cast acquisition composite to object", acqSelectionObj);
251 
252  ::fwAtoms::Map::sptr acqSelectionMap = acqSelectionObj->getAttribute< ::fwAtoms::Map >("values");
253 
254  ::fwAtoms::Map::const_iterator iter = acqSelectionMap->getValue().find("selectedAcquisition");
255  if (iter != acqSelectionMap->getValue().end() )
256  {
257  // get associated image
258  ::fwAtoms::Base::sptr acquisition = iter->second;
259  ::fwAtoms::Object::sptr acqObj = ::fwAtoms::Object::dynamicCast(acquisition);
260  SLM_ASSERT("Failed to cast acquisition to object", acqObj);
261 
262  Image2ModelType::const_iterator it = image2Model.find(newVersions[acqObj]);
263  if(it != image2Model.end())
264  {
265  ::fwAtoms::Object::sptr imageSeries = it->first;
266  helperActivity.replaceAttribute("patient", imageSeries->getAttribute< ::fwAtoms::Object >("patient"));
267  helperActivity.replaceAttribute("study", imageSeries->getAttribute< ::fwAtoms::Object >("study"));
268  helperActivity.replaceAttribute("equipment",
269  imageSeries->getAttribute< ::fwAtoms::Object >("equipment"));
270  }
271  }
272 
273  series->push_back(newActivitySeries);
274  }
275 
276 }
277 
278 // ----------------------------------------------------------------------------
279 
281  const ::fwAtoms::Object::sptr& previous,
282  const ::fwAtoms::Object::sptr& current,
283  ::fwAtomsPatch::IPatch::NewVersionsType& newVersions)
284 {
285  Image2ModelType image2Model;
286 
287  ISemanticPatch::apply(previous, current, newVersions);
288 
289  // Create helper
290  ::fwAtomsPatch::helper::Object helper(current);
291 
292  // If fwData::Composite is a MedicalWorkspace
293  if ( previous->getMetaInfo("compositeType") == "MedicalWorkspace" )
294  {
295  // Update type/version
296  ::fwAtomsPatch::helper::setClassname( current, "::fwMedData::SeriesDB" );
297  ::fwAtomsPatch::helper::setVersion( current, "1" );
298 
299  // Update Attributes
300  ::fwAtomsPatch::helper::cleanFields( current );
301  // Replace fwAtoms::Map by fwAtoms::Sequence ( have the same key )
302  ::fwAtoms::Sequence::sptr series = ::fwAtoms::Sequence::New();
303  helper.replaceAttribute( "values", series );
304 
305  // Add ImageSeries and create ModelSeries if they are necessary
306  ::fwAtoms::Map::sptr oldCompositeMap = previous->getAttribute< ::fwAtoms::Map >("values");
307  ::fwAtoms::Object::sptr oldPatientDB =
308  ::fwAtoms::Object::dynamicCast( (*oldCompositeMap)["patientDB"] );
309  ::fwAtoms::Sequence::sptr oldPatients = oldPatientDB->getAttribute< ::fwAtoms::Sequence >("patients");
310 
311  ::fwAtomsPatch::StructuralCreatorDB::sptr creators = ::fwAtomsPatch::StructuralCreatorDB::getDefault();
312 
313  for( ::fwAtoms::Base::sptr oldPatientAtom : oldPatients->getValue() )
314  {
315  ::fwAtoms::Object::sptr oldPatient = ::fwAtoms::Object::dynamicCast( oldPatientAtom );
316  ::fwAtoms::Object::sptr newPatient = newVersions[oldPatient];
317 
318  ::fwAtoms::Sequence::sptr oldStudies = oldPatient->getAttribute< ::fwAtoms::Sequence >("studies");
319 
320  for( ::fwAtoms::Base::sptr oldStudyAtom : oldStudies->getValue() )
321  {
322  ::fwAtoms::Object::sptr oldStudy = ::fwAtoms::Object::dynamicCast( oldStudyAtom );
323  ::fwAtoms::Object::sptr newStudy = newVersions[oldStudy];
324 
325  ::fwAtoms::Sequence::sptr oldAcquisitions =
326  oldStudy->getAttribute< ::fwAtoms::Sequence >("acquisitions");
327 
328  for( ::fwAtoms::Base::sptr oldAcqAtom : oldAcquisitions->getValue() )
329  {
330  ::fwAtoms::Object::sptr oldAcq = ::fwAtoms::Object::dynamicCast( oldAcqAtom );
331 
332  // finalize and push newImgSeries
333  ::fwAtoms::Object::sptr newImgSeries = newVersions[oldAcq];
334  ::fwAtomsPatch::helper::Object imgSeriesHelper(newImgSeries);
335  ::fwAtoms::Object::sptr clonedPatient = ::fwAtoms::Object::dynamicCast(newPatient->clone());
336  ::fwAtomsPatch::helper::changeUID(clonedPatient);
337 
338  imgSeriesHelper.replaceAttribute("patient", clonedPatient );
339  ::fwAtoms::Object::sptr clonedStudy = ::fwAtoms::Object::dynamicCast(newStudy->clone());
340  ::fwAtomsPatch::helper::changeUID(clonedStudy);
341 
342  imgSeriesHelper.replaceAttribute("study", clonedStudy );
343  imgSeriesHelper.replaceAttribute("modality", oldStudy->getAttribute("modality")->clone() );
344 
345  ::fwAtoms::String::sptr institution;
346  institution =
347  ::fwAtoms::String::dynamicCast( oldStudy->getAttribute("hospital")->clone() );
348  ::fwAtoms::Object::sptr equipment = newImgSeries->getAttribute< ::fwAtoms::Object >("equipment");
349  ::fwAtomsPatch::helper::Object equipmentHelper(equipment);
350  equipmentHelper.replaceAttribute("institution_name", institution);
351 
352  // Set study date and time if necessary
353  ::fwAtoms::String::sptr studyDate = newStudy->getAttribute< ::fwAtoms::String >("date");
354  ::fwAtomsPatch::helper::Object studyHelper(clonedStudy);
355 
356  if ( studyDate->getValue().empty() )
357  {
358  studyHelper.replaceAttribute("date", newImgSeries->getAttribute("date")->clone());
359  }
360 
361  ::fwAtoms::String::sptr studyTime = newStudy->getAttribute< ::fwAtoms::String >("time");
362  if ( studyTime->getValue().empty() )
363  {
364  studyHelper.replaceAttribute("time", newImgSeries->getAttribute("time")->clone());
365  }
366 
367  series->push_back( newImgSeries );
368 
369  // finalize and push newModelSeries
370  ::fwAtoms::Sequence::sptr oldReconstructions =
371  oldAcq->getAttribute< ::fwAtoms::Sequence >("reconstructions");
372 
373  if ( oldReconstructions->size() > 0 )
374  {
375  // Create new model series
376  ::fwAtoms::Object::sptr newModelSeries =
377  creators->create( "::fwMedData::ModelSeries", "1");
378 
379  ::fwAtomsPatch::helper::Object msHelper(newModelSeries);
380  ::fwAtoms::Object::sptr msPatient = ::fwAtoms::Object::dynamicCast(clonedPatient->clone());
381  ::fwAtomsPatch::helper::changeUID(msPatient);
382  msHelper.replaceAttribute("patient", msPatient );
383 
384  ::fwAtoms::Object::sptr msStudy = ::fwAtoms::Object::dynamicCast(clonedStudy->clone());
385  ::fwAtomsPatch::helper::changeUID(msStudy);
386  msHelper.replaceAttribute("study", msStudy );
387 
388  ::fwAtoms::Object::sptr msEquipment = ::fwAtoms::Object::dynamicCast(equipment->clone());
389  ::fwAtomsPatch::helper::changeUID(msEquipment);
390  msHelper.replaceAttribute("equipment", msEquipment );
391 
392  msHelper.replaceAttribute("modality", ::fwAtoms::String::New("OT") );
393  msHelper.replaceAttribute("instance_uid",
395  msHelper.replaceAttribute("date", newImgSeries->getAttribute("date")->clone() );
396  msHelper.replaceAttribute("time", newImgSeries->getAttribute("time")->clone() );
397  msHelper.replaceAttribute("performing_physicians_name",
398  newImgSeries->getAttribute("performing_physicians_name")->clone() );
399  msHelper.replaceAttribute("description", newImgSeries->getAttribute("description")->clone() );
400 
401  ::fwAtoms::Sequence::sptr newReconstructions =
402  newModelSeries->getAttribute< ::fwAtoms::Sequence >("reconstruction_db");
403  for( ::fwAtoms::Base::sptr oldRecAtom : oldReconstructions->getValue() )
404  {
405  ::fwAtoms::Object::sptr oldRec = ::fwAtoms::Object::dynamicCast( oldRecAtom );
406  newReconstructions->push_back(newVersions[oldRec]);
407  }
408 
409  image2Model[newImgSeries] = newModelSeries;
410  series->push_back( newModelSeries );
411  }
412  }
413  }
414  }
415 
416  processPlanning(oldCompositeMap, series, image2Model, newVersions);
417  processProcessing(oldCompositeMap, series, image2Model, newVersions);
418 
419  } // End "MedicalWorkspace"
420 }
421 
422 } // namespace fwData
423 } // namespace V2
424 } // namespace V1
425 } // namespace fwMDSemanticPatch
MapType::const_iterator const_iterator
Definition: Map.hpp:53
Patch the composite describing a &#39;Medical workspace&#39; from version &#39;V1&#39; to &#39;V2&#39; within &#39;MedicalData&#39; c...
virtual FWMDSEMANTICPATCH_API void apply(const ::fwAtoms::Object::sptr &previous, const ::fwAtoms::Object::sptr &current,::fwAtomsPatch::IPatch::NewVersionsType &newVersions) override
Applies patch.
Contains the semantic patches within the context "MedicalData".
static FWATOMS_API String::sptr New(std::string value)
Construct a new Object represented a string.
const MapType & getValue() const
returns atom&#39;s map
Definition: Map.hpp:145
Contains base functionalities used to transform objects from a version to another.
Definition: Abstract.hpp:16
Class represented a fwData::Object.
std::string m_originClassname
Origin classname of the object.
Definition: IPatch.hpp:64
virtual FWATOMSPATCH_API void addContext(const std::string &context, const std::string &originVersion, const std::string &targetVersion)
Add a context where the patch can be applied.
FWATOMSPATCH_API void replaceAttribute(const std::string &name,::fwAtoms::Base::sptr newValue, conditions::Abstract::sptr condition=conditions::Abstract::New())
Replaces an attribute.
Map is a container for mapping representation.
Definition: Map.hpp:31
std::string m_originVersion
Origin version of the object.
Definition: IPatch.hpp:67
FWATOMSPATCH_API ISemanticPatch()
Constructor.
#define SLM_ASSERT(message, cond)
work like &#39;assert&#39; from &#39;cassert&#39;, with in addition a message logged by spylog (with FATAL loglevel) ...
Definition: spyLog.hpp:308
FWATOMSPATCH_API void addAttribute(const std::string &name,::fwAtoms::Base::sptr value, conditions::Abstract::sptr condition=conditions::Abstract::New())
Adds a new attribute in the current object.
static StructuralCreatorDB::sptr getDefault()
Returns the default instance of StructuralCreatorDB.
Contains the representation of the data objects used in the framework.
MapType::value_type value_type
Definition: Map.hpp:51
Class represented a String.
Sequence represented a list of meta object.
Definition: Sequence.hpp:22
static FWTOOLS_API UUIDType generateUUID()
Return a new extended UUID;.
Definition: UUID.cpp:114