001/** 002 * Copyright (C) 2014 Universidade de Aveiro, DETI/IEETA, Bioinformatics Group - http://bioinformatics.ua.pt/ 003 * 004 * This file is part of Dicoogle/dicoogle. 005 * 006 * Dicoogle/dicoogle is free software: you can redistribute it and/or modify 007 * it under the terms of the GNU General Public License as published by 008 * the Free Software Foundation, either version 3 of the License, or 009 * (at your option) any later version. 010 * 011 * Dicoogle/dicoogle is distributed in the hope that it will be useful, 012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 014 * GNU General Public License for more details. 015 * 016 * You should have received a copy of the GNU General Public License 017 * along with Dicoogle. If not, see <http://www.gnu.org/licenses/>. 018 */ 019/** 020 * Class SearchResult is responsible to get results from Lucene indexer 021 * But no text results are returned instead we use names of DICOM file and 022 * instance a new DicomObject, so in theory this is an abstract to a list of 023 * DicomObject, neither list of *names* of DICOM file. 024 */ 025package pt.ua.dicoogle.server; 026 027import java.io.*; 028import java.net.URI; 029import java.net.URISyntaxException; 030 031import org.dcm4che2.data.*; 032import org.slf4j.Logger; 033import pt.ua.dicoogle.core.ServerSettings; 034 035import java.util.ArrayList; 036import java.util.Collection; 037import java.util.HashMap; 038import java.util.Iterator; 039import java.util.List; 040import java.util.concurrent.ExecutionException; 041import org.slf4j.LoggerFactory; 042 043import org.dcm4che2.io.DicomInputStream; 044 045 046import pt.ua.dicoogle.core.dim.*; 047import pt.ua.dicoogle.plugins.PluginController; 048import pt.ua.dicoogle.sdk.datastructs.SearchResult; 049import pt.ua.dicoogle.sdk.task.JointQueryTask; 050import pt.ua.dicoogle.sdk.task.Task; 051/** 052 * 053 * @author Luís A. Bastião Silva <bastiao@ua.pt> 054 * @since 17 Fev 2009 055 */ 056public class SearchDicomResult implements Iterator<DicomObject> 057{ 058 059 public enum QUERYLEVEL { PATIENT, STUDY, SERIE, IMAGE} 060 061 private final QUERYLEVEL queryLevel; 062 063 064 /** 065 * Get IndexCore 066 */ 067 068 Collection<SearchResult> list = null ; 069 List<Patient> patientList = new ArrayList<>(); 070 List<Study> studyList = new ArrayList<>(); 071 List<Serie> seriesList = new ArrayList<>(); 072 Iterator it = null ; 073 074 String currentFile ; 075 076 077 078 private static ConcatTags concatTags = null; 079 private static boolean concatTagsCheck = true; 080 081 082 private static final Logger logger = LoggerFactory.getLogger(SearchDicomResult.class); 083 084 public SearchDicomResult(String searchQuery, boolean isNetwork, 085 ArrayList<String> extrafields, QUERYLEVEL level) { 086 087 queryLevel = level; 088 089 /** 090 * Get the array list of resulst match searchQuery 091 */ 092 093 logger.info("QUERY: " + searchQuery); 094 logger.info("QUERYLEVEL: " + queryLevel); 095 096 if (concatTags==null&& concatTagsCheck) 097 { 098 concatTags = new ConcatTags(); 099 try { 100 concatTags.parseConfig(ConcatTags.FILENAME); 101 } catch (FileNotFoundException ex) { 102 logger.info("There is not file: " + ConcatTags.FILENAME); 103 concatTags = null; 104 concatTagsCheck = false; 105 } 106 } 107 108 HashMap<String, String> extraFields = new HashMap<String, String>(); 109 for (String s : extrafields) { 110 extraFields.put(s, s); 111 } 112 113 JointQueryTask holder = new JointQueryTask() { 114 115 @Override 116 public void onReceive(Task<Iterable<SearchResult>> e) { 117 // TODO Auto-generated method stub 118 119 } 120 121 @Override 122 public void onCompletion() { 123 // TODO Auto-generated method stub 124 125 } 126 }; 127 holder = PluginController.getInstance().queryAll(holder, searchQuery, 128 extraFields); 129 130 try { 131 it = holder.get().iterator(); 132 133 list = new ArrayList<SearchResult>(); 134 while (it.hasNext()) { 135 list.add((SearchResult) it.next()); 136 } 137 } catch (InterruptedException | ExecutionException e1) { 138 // TODO Auto-generated catch block 139 e1.printStackTrace(); 140 } 141 142 if(list != null) 143 it = list.iterator(); 144 145 if (level == QUERYLEVEL.PATIENT || level == QUERYLEVEL.STUDY) { 146 DIMGeneric dimModel = null; 147 try 148 { 149 if (concatTags==null) 150 dimModel = new DIMGeneric(list); 151 else 152 dimModel = new DIMGeneric(concatTags, list); 153 154 } catch (Exception ex) 155 { 156 ex.printStackTrace(); 157 } 158 159 ArrayList<Patient> listPatients = dimModel.getPatients(); 160 161 for (Patient p : listPatients) { 162 studyList.addAll(p.getStudies()); 163 } 164 165 it = studyList.iterator(); 166 167 } else if (level == QUERYLEVEL.SERIE) { 168 169 DIMGeneric dimModel = null; 170 try 171 { 172 if (concatTags==null) 173 dimModel = new DIMGeneric(list); 174 else 175 dimModel = new DIMGeneric(concatTags, list); 176 } catch (Exception ex) 177 { 178 } 179 180 181 ArrayList<Patient> listPatients = dimModel.getPatients(); 182 for (Patient p : listPatients) { 183 studyList.addAll(p.getStudies()); 184 for (Study s : p.getStudies()) { 185 seriesList.addAll(s.getSeries()); 186 } 187 } 188 it = seriesList.iterator(); 189 190 } 191 192 } 193 194 @Override 195 public boolean hasNext() 196 { 197 if (it!=null) 198 { 199 return it.hasNext(); 200 } 201 else 202 { 203 return false; 204 } 205 } 206 207 public String getCurrentFile() 208 { 209 return this.currentFile ; 210 } 211 212 @Override 213 public DicomObject next() 214 { 215 216 // TODO: this code need to be refactored 217 // C-FIND RSP should be builded based on Search Result, 218 // instead opening the file to build DicomObject. 219 220 /** 221 * Get the fullpath of images 222 */ 223 ServerSettings s = ServerSettings.getInstance(); 224 String path = s.getPath(); 225 226 //DebugManager.getInstance().debug("Path of DICOM: "+path); 227 228 229 if (it != null && it.hasNext()) 230 { 231 Object next = it.next(); 232 if (queryLevel==QUERYLEVEL.IMAGE ) 233 { 234 235 SearchResult sR = (SearchResult)next; 236 237 path = sR.getURI().toString(); 238 currentFile = path ; 239 //DebugManager.getInstance().debug("-> Next::: " + next.toString()); 240 DicomInputStream din = null; 241 /*try 242 { 243 if (path.endsWith(".gz")) 244 din = new DicomInputStream(new GZIPInputStream(new BufferedInputStream(new FileInputStream(new File(path)), 256))); 245 else 246 din = new DicomInputStream(new File(path)); 247 248 249 URI uri = new URI(path); 250 //System.out.println("Trying to find Plugin for: "+uri.toString()); 251 StorageInterface plug = PluginController.getInstance().getStorageForSchema(uri); 252 253 if(plug != null){ 254 //System.out.println("Found Plugin For: "+uri.toString()); 255 256 Iterable<StorageInputStream> stream = plug.at(uri); 257 for(StorageInputStream str : stream) 258 259 try { 260 din = new DicomInputStream(str.getInputStream()); 261 } catch (IOException ex) { 262 LoggerFactory.getLogger(SearchDicomResult.class).error(ex.getMessage(), ex); 263 } 264 } 265 266 //DebugManager.getInstance().debug("Imagem: "+path+"..."+next); 267 } catch (URISyntaxException ex) { 268 LoggerFactory.getLogger(SearchDicomResult.class).error(ex.getMessage(), ex); 269 } 270 */ 271 272 /** This code is refactored in a experimental branch 273 * Building a BasicDicomObject based on Indexing 274 * It will increase the performace 275 */ 276 BasicDicomObject result = new BasicDicomObject(); 277 278 // Fill fields of study now 279 280 281 //System.out.println("Serie : "+ serieTmp); 282 result.putString(Tag.InstitutionName, VR.CS,(String)sR.get("InstitutionName")); 283 284 result.putString(Tag.StudyInstanceUID, VR.UI, (String)sR.get("StudyInstanceUID")); 285 result.putString(Tag.SeriesInstanceUID, VR.UI, (String)sR.get("SeriesInstanceUID")); 286 result.putString(Tag.SOPInstanceUID, VR.UI, (String)sR.get("SOPInstanceUID")); 287 result.putString(Tag.SeriesDescription, VR.LO, (String)sR.get("SeriesDescription")); 288 result.putString(Tag.SeriesDate, VR.TM, (String)sR.get("SeriesDate")); 289 result.putString(Tag.SeriesTime, VR.TM, (String)sR.get("SeriesTime")); 290 result.putString(Tag.QueryRetrieveLevel, VR.LO, "IMAGE"); 291 292 result.putString(Tag.Modality, VR.CS,(String)sR.get("Modality")); 293 294 result.putString(Tag.SeriesNumber, VR.IS, "" + (String)sR.get("SeriesNumber")); 295 296 297 return result; 298 299 } 300 else if (queryLevel == QUERYLEVEL.STUDY||queryLevel == QUERYLEVEL.PATIENT) 301 { 302 303 Study studyTmp = (Study)next; 304 BasicDicomObject result = new BasicDicomObject(); 305 String patientName =studyTmp.getParent().getPatientName() ; 306 307 try { 308 patientName = new String(studyTmp.getParent().getPatientName().getBytes("ISO-8859-1"), "ISO-8859-1"); 309 } catch (Exception ex) { 310 LoggerFactory.getLogger(SearchDicomResult.class).error(ex.getMessage(), ex); 311 } 312 try { 313 result.putBytes(Tag.PatientName, VR.PN, patientName.getBytes("ISO-8859-1")); 314 } catch (Exception ex) { 315 LoggerFactory.getLogger(SearchDicomResult.class).error(ex.getMessage(), ex); 316 } 317 318 //System.out.println("PatientName:"+patientName); 319 result.putString(Tag.SpecificCharacterSet, VR.CS, "ISO_IR 100"); 320 result.putString(Tag.PatientSex, VR.LO, studyTmp.getParent().getPatientSex()); 321 result.putString(Tag.PatientID, VR.LO, studyTmp.getParent().getPatientID()); 322 result.putString(Tag.PatientBirthDate, VR.DA, studyTmp.getParent().getPatientBirthDate()); 323 result.putString(Tag.StudyDate, VR.DA, studyTmp.getStudyData()); 324 result.putString(Tag.StudyID, VR.SH, studyTmp.getStudyID()); 325 result.putString(Tag.StudyTime, VR.TM, studyTmp.getStudyTime()); 326 result.putString(Tag.AccessionNumber, VR.SH, studyTmp.getAccessionNumber()); 327 result.putString(Tag.StudyInstanceUID, VR.UI, studyTmp.getStudyInstanceUID()); 328 result.putString(Tag.StudyDescription, VR.LO, studyTmp.getStudyDescription()); 329 String modality = studyTmp.getSeries().get(0).getModality(); // Point of Failure, fix me 330 result.putString(Tag.ModalitiesInStudy, VR.CS,modality); 331 result.putString(Tag.Modality, VR.CS,modality); 332 result.putString(Tag.InstitutionName, VR.CS, studyTmp.getInstitutuionName()); 333 334 int instances = 0; 335 for (Serie serieTmp : studyTmp.getSeries()) 336 { 337 instances+=serieTmp.getImageList().size(); 338 } 339 340 result.putString(Tag.NumberOfStudyRelatedInstances, VR.IS,""+instances); 341 result.putString(Tag.NumberOfSeriesRelatedInstances, VR.IS,""+studyTmp.getSeries().size()); 342 343 344 return result; 345 346 } 347 else if (queryLevel == QUERYLEVEL.SERIE) 348 { 349 // Serie 350 351 Serie serieTmp = (Serie)next; 352 BasicDicomObject result = new BasicDicomObject(); 353 //System.out.println("Serie : "+ serieTmp); 354 result.putString(Tag.InstitutionName, VR.CS,serieTmp.getParent().getInstitutuionName()); 355 356 result.putString(Tag.StudyInstanceUID, VR.UI, serieTmp.getParent().getStudyInstanceUID()); 357 result.putString(Tag.SeriesInstanceUID, VR.UI, serieTmp.getSerieInstanceUID()); 358 result.putString(Tag.SeriesDescription, VR.LO, serieTmp.getSeriesDescription()); 359 result.putString(Tag.SeriesDate, VR.TM, serieTmp.getSeriesDate()); 360 result.putString(Tag.QueryRetrieveLevel, VR.LO, "SERIES"); 361 String modality = serieTmp.getModality(); // Point of Failure, fix me 362 result.putString(Tag.Modality, VR.CS,modality); 363 364 result.putString(Tag.SeriesNumber, VR.IS, "" + serieTmp.getSerieNumber()); 365 366 367 result.putString(Tag.Modality, VR.CS,modality); 368 if (serieTmp.getModality().equals("MG")||serieTmp.getModality().equals("CR")) 369 { 370 371 result.putString(Tag.ViewPosition, null, serieTmp.getViewPosition()); 372 result.putString(Tag.ImageLaterality, null, serieTmp.getImageLaterality()); 373 result.putString(Tag.AcquisitionDeviceProcessingDescription, VR.AE, serieTmp.getAcquisitionDeviceProcessingDescription()); 374 DicomElement viewCodeSequence = result.putSequence(Tag.ViewCodeSequence); 375 DicomObject viewCodeSequenceObj = new BasicDicomObject(); 376 viewCodeSequenceObj.setParent(result); 377 viewCodeSequenceObj.putString(Tag.CodeValue, null, serieTmp.getViewCodeSequence_CodeValue()); 378 viewCodeSequenceObj.putString(Tag.CodingSchemeDesignator, null, serieTmp.getViewCodeSequence_CodingSchemeDesignator()); 379 viewCodeSequenceObj.putString(Tag.CodingSchemeVersion, null, serieTmp.getViewCodeSequence_CodingSchemeVersion()); 380 viewCodeSequenceObj.putString(Tag.CodeMeaning, null, serieTmp.getViewCodeSequence_CodeMeaning()); 381 382 viewCodeSequence.addDicomObject(viewCodeSequenceObj); 383 result.putNestedDicomObject(Tag.ViewCodeSequence, viewCodeSequenceObj); 384 } 385 result.putString(Tag.NumberOfSeriesRelatedInstances, VR.IS,""+serieTmp.getImageList().size()); 386 387 388 result.putString(Tag.SeriesNumber, VR.IS, "" + serieTmp.getSerieNumber()); 389 result.putString(Tag.ProtocolName, VR.LO, "" + serieTmp.getProtocolName()); 390 result.putString(Tag.BodyPartThickness, VR.LO, "" + serieTmp.getBodyPartThickness()); 391 392 393 return result; 394 395 } 396 else 397 { 398 System.err.println("ERROR: WRONG QUERY LEVEL!"); 399 } 400 401 402 } 403 return null ; 404 } 405 406 @Override 407 public void remove() 408 { 409 throw new UnsupportedOperationException("Not supported. Nobody use it."); 410 } 411}