// INTERNATIONAL AVS CENTRE - WARRANTY DISCLAIMER
// Please read the file DISCLAIMER for conditions associated with this file.
// avs@iavsc.org, www.iavsc.org

library ReadDICOMMacs {
   macro ReadDICOMPatientUI {
      int visible = 0;
      UIshell PatientShell {
	 visible => <-.visible;
	 height = 400;
	 showStatusBar = 0;
	 title = "Patient Information";
      };
      UIpanel panel {
	 x = 0;
	 y = 0;
	 width => parent.clientWidth;
	 height => parent.clientHeight;
	 parent => <-.PatientShell;
      };
      group &patient<NEportLevels={2,0}>;
      UIlabel Patient {
	 y = 10;
	 width => parent.clientWidth;
	 parent => <-.panel;
	 label = "Patient Information";
      };
      UItext Info {
	 parent => <-.panel;
	 width => parent.clientWidth;
	 height => parent.clientHeight;
	 text => str_format(
	    "Name : %s\nIDP : %s\nBirth Date : %s\nBirth Time : %s\nSex : %s\nReferenced Seq : %s\nOther ID : %s\nOther Names : %s\nEthnic Group : %s\nComments : %s",
	    switch(is_valid(<-.patient.PatientsNameP)+1,"",<-.patient.PatientsNameP),
	    switch(is_valid(<-.patient.PatientIDP)+1,"",<-.patient.PatientIDP),
	    switch(is_valid(<-.patient.PatientsBirthDateP)+1,"",<-.patient.PatientsBirthDateP),
	    switch(is_valid(<-.patient.PatientsBirthTimeP)+1,"",<-.patient.PatientsBirthTimeP),
	    switch(is_valid(<-.patient.PatientsSexP)+1,"",<-.patient.PatientsSexP),
	    switch(is_valid(<-.patient.ReferencedPatientSequenceP)+1,"",<-.patient.ReferencedPatientSequenceP),
	    switch(is_valid(<-.patient.OtherPatientID)+1,"",<-.patient.OtherPatientID),
	    switch(is_valid(<-.patient.OtherPatientNamesP)+1,"",<-.patient.OtherPatientNamesP),
	    switch(is_valid(<-.patient.EthnicGroupP)+1,"",<-.patient.EthnicGroupP),
	    switch(is_valid(<-.patient.PatientCommentsP)+1,"",<-.patient.PatientCommentsP)
	 );
	 outputOnly = 1;
      };
   };
   macro ReadDICOMStudyUI {
      int visible = 0;
      UIshell StudyShell {
	 visible => <-.visible;
	 height = 400;
	 showStatusBar = 0;
	 title = "Study Information";
      };
      UIpanel panel {
	 x = 0;
	 y = 0;
	 width => parent.clientWidth;
	 height => parent.clientHeight;
	 parent => <-.StudyShell;
      };
      group &generalStudy<NEportLevels={2,0}>;
      UIlabel GeneralStudy {
	 y = 10;
	 width => parent.clientWidth;
	 parent => <-.panel;
	 label = "Study Information";
      };
      UItext Info {
	 parent => <-.panel;
	 width => parent.clientWidth;
	 height => parent.clientHeight;
	 text => str_format(
	    "Instance UID : %s\nDate : %s\nTime : %s\nReferring Phys Name : %s\nID : %s\nAccession Number : %s\nDescription : %s\nReading Phys Name : %s\nReferenced Seq : %s",
	    switch(is_valid(<-.generalStudy.StudyInstanceUIDGS)+1,"",<-.generalStudy.StudyInstanceUIDGS),
	    switch(is_valid(<-.generalStudy.StudyDateGS)+1,"",<-.generalStudy.StudyDateGS),
	    switch(is_valid(<-.generalStudy.StudyTimeGS)+1,"",<-.generalStudy.StudyTimeGS),
	    switch(is_valid(<-.generalStudy.ReferringPhysiciansNameGS)+1,"",<-.generalStudy.ReferringPhysiciansNameGS),
	    switch(is_valid(<-.generalStudy.StudyIDGS)+1,"",<-.generalStudy.StudyIDGS),
	    switch(is_valid(<-.generalStudy.AccessionNumberGS)+1,"",<-.generalStudy.AccessionNumberGS),
	    switch(is_valid(<-.generalStudy.StudyDescriptionGS)+1,"",<-.generalStudy.StudyDescriptionGS),
	    switch(is_valid(<-.generalStudy.NameofPhysiciansReadingStudyGS)+1,"",<-.generalStudy.NameofPhysiciansReadingStudyGS),
	    switch(is_valid(<-.generalStudy.ReferencedStudySequenceGS)+1,"",<-.generalStudy.ReferencedStudySequenceGS)
	 );    
      };
   };
   
   macro ReadDICOMSeriesUI {
      int visible = 0;
      UIshell SeriesShell {
	 visible => <-.visible;
	 height = 400;
	 showStatusBar = 0;
	 title = "Series Information";
      };
      UIpanel panel {
	 x = 0;
	 y = 0;
	 width => parent.clientWidth;
	 height => parent.clientHeight;
	 parent => <-.SeriesShell;
      };
      group &generalSeries<NEportLevels={2,0}>;
      UIlabel GeneralSeries {
	 y = 10;
	 width => parent.clientWidth;
	 parent => <-.panel;
	 label = "Series Information";
      };
      UItext Info {
	 parent => <-.panel;
	 width => parent.clientWidth;
	 height => parent.clientHeight;
	 text => str_format(
	    "Modality : %s\nInstance UID : %s\nNumber : %s\nLaterality : %s\nDate : %s\nTime : %s\nPerf Phys Name : %s\nProtocol Name : %s\nDescription : %s\nOperator's Name : %s\nRef Study Comp Seq : %s\nBody Part Examined : %s\nPatient Position : %s\nSmallest Pixel Value : %s\nLargest Pixel Value : %s",
	    switch(is_valid(<-.generalSeries.ModalityGS)+1,"",<-.generalSeries.ModalityGS),
	    switch(is_valid(<-.generalSeries.SeriesInstanceUIDGS)+1,"",<-.generalSeries.SeriesInstanceUIDGS),
	    switch(is_valid(<-.generalSeries.SeriesNumberGS)+1,"",<-.generalSeries.SeriesNumberGS),
	    switch(is_valid(<-.generalSeries.Laterality)+1,"",<-.generalSeries.Laterality),
	    switch(is_valid(<-.generalSeries.SeriesDate)+1,"",<-.generalSeries.SeriesDate),
	    switch(is_valid(<-.generalSeries.SeriesTime)+1,"",<-.generalSeries.SeriesTime),
	    switch(is_valid(<-.generalSeries.PerformingPhysiciansNameGS)+1,"",<-.generalSeries.PerformingPhysiciansNameGS),
	    switch(is_valid(<-.generalSeries.ProtocolName)+1,"",<-.generalSeries.ProtocolName),
	    switch(is_valid(<-.generalSeries.SeriesDescription)+1,"",<-.generalSeries.SeriesDescription),
	    switch(is_valid(<-.generalSeries.OperatorsName)+1,"",<-.generalSeries.OperatorsName),
	    switch(is_valid(<-.generalSeries.ReferencedStudyComponentSequenceGS)+1,"",<-.generalSeries.ReferencedStudyComponentSequenceGS),
	    switch(is_valid(<-.generalSeries.BodyPartExaminedGS)+1,"",<-.generalSeries.BodyPartExaminedGS),
	    switch(is_valid(<-.generalSeries.PatientPosition)+1,"",<-.generalSeries.PatientPosition),
	    switch(is_valid(<-.generalSeries.SmallestPixelValueinSeries)+1,"",<-.generalSeries.SmallestPixelValueinSeries),
	    switch(is_valid(<-.generalSeries.LargestPixelValueinSeries)+1,"",<-.generalSeries.LargestPixelValueinSeries)
	 );
	 outputOnly = 1;
      };
   };
   macro ReadDICOMEquipmentUI {
      int visible = 0;
      UIshell EquipmentShell {
	 visible => <-.visible;
	 height = 400;
	 showStatusBar = 0;
	 title = "Equipment Information";
      };
      UIpanel panel {
	 x = 0;
	 y = 0;
	 width => parent.clientWidth;
	 height => parent.clientHeight;
	 parent => <-.EquipmentShell;
      };
      group &generalEquipment<NEportLevels={2,0}>;
      UIlabel GeneralEquipment {
	 y = 10;
	 width => parent.clientWidth;
	 parent => <-.panel;
	 label = "Equipment Information";
      };
      UItext Info {
	 parent => <-.panel;
	 width => parent.clientWidth;
	 height => parent.clientHeight;
	 text => str_format(
	    "Manufacturer : %s\nInstitution Name : %s\nInstitution Address : %s\nStation Name : %s\nInstitution Dept Name : %s\nManufacturer's Model : %s\nDevice SN : %s\nSoftware Versions : %s\nSpatial Resolution : %s\nLast Calibration Date : %s\nPixel Padding Value : %s",
	    switch(is_valid(<-.generalEquipment.ManufacturerGE)+1,"",<-.generalEquipment.ManufacturerGE),
	    switch(is_valid(<-.generalEquipment.InstitutionNameGE)+1,"",<-.generalEquipment.InstitutionNameGE),
	    switch(is_valid(<-.generalEquipment.InstitutionAddressGE)+1,"",<-.generalEquipment.InstitutionAddressGE),
	    switch(is_valid(<-.generalEquipment.StationName)+1,"",<-.generalEquipment.StationName),
	    switch(is_valid(<-.generalEquipment.InstitutionalDepartmentName)+1,"",<-.generalEquipment.InstitutionalDepartmentName),
	    switch(is_valid(<-.generalEquipment.ManufacturersModelName)+1,"",<-.generalEquipment.ManufacturersModelName),
	    switch(is_valid(<-.generalEquipment.DeviceSerialNumberGE)+1,"",<-.generalEquipment.DeviceSerialNumberGE),
	    switch(is_valid(<-.generalEquipment.SoftwareVersionsGE)+1,"",<-.generalEquipment.SoftwareVersionsGE),
	    switch(is_valid(<-.generalEquipment.SpatialResolution)+1,"",<-.generalEquipment.SpatialResolution),
	    switch(is_valid(<-.generalEquipment.DateofLastCalibration)+1,"",<-.generalEquipment.DateofLastCalibration),
	    switch(is_valid(<-.generalEquipment.TimeofLastCalibration)+1,"",<-.generalEquipment.TimeofLastCalibration),
	    switch(is_valid(<-.generalEquipment.PixelPaddingValue)+1,"",<-.generalEquipment.PixelPaddingValue)
	 );
	 outputOnly = 1;
      };
   };

   macro ReadDCMLISTUI {
      int visible = 0;
#ifdef MSDOS
      string searchPath<NEportLevels={2,1}> = "C:\\";
#else
      string searchPath<NEportLevels={2,1}> = ".";
#endif	 
      int rescan<NEportLevels={2,1}>;
      int vis<NEportLevels={2,1}>;
      macro UIpopWindow{
	 int vis => <-.visible;
	 UIshell shell {
	    x = 100;
	    y = 150;
	    width = 700;
	    height = 300;
	    visible => <-.vis;
	    title => "Choose DICOM series (" + <-.<-.UIdirectory.filename + ")";
	 };
	 UIpanel panel {
	    x = 0;
	    y = 0;
	    width => parent.clientWidth;
	    height=> parent.clientHeight;
	    parent => <-.shell;
	 };
      };
      IAC_PROJ.ReadDICOM.ReadDICOMMods.read_DCMLIST read_DCMLIST {
	 dirname => <-.UIdirectory.filename;
	 rescan => <-.UIrescan.do;
	 delete => <-.UIdelete.do;
	 selected_series => <-.i;
      };
      UIlist UIlist {
	 parent => <-.UIpopWindow.panel;
	 width => parent.clientWidth;
	 height => parent.clientHeight-UIrescan.height;
	 strings => <-.read_DCMLIST.series;
	 y = 0;
	 selectedItem<NEportLevels={0,2}>;
      };
      UIbutton UIread {
	 x = 4;
	 y => parent.clientHeight - height;
	 width => parent.clientWidth/4 - 6;
	 parent => <-.UIpopWindow.panel;
	 active => is_valid(<-.i);
	 label = "Read Series";
	 message = "Load the selected series into the application";
      };
      UIbutton UIrescan {
	 x => parent.clientWidth/4 + 2;
	 y => parent.clientHeight - height;
	 width => parent.clientWidth/4 - 2;
	 parent => <-.UIpopWindow.panel;
	 label = "Rescan Directory";
	 message = "Reload the DCMLIST file";
      };
      UIbutton UIchooseDir {
	 x => 2*parent.clientWidth/4 + 2;
	 y => parent.clientHeight - height;
	 width => parent.clientWidth/4 - 2;
	 parent => <-.UIpopWindow.panel;
	 label = "Change Directory";
	 message = "Change the directory in which the DICOM files are stored";
      };
      UIbutton UIdelete {
	 x => 3*parent.clientWidth/4 + 2;
	 y => parent.clientHeight - height;
	 width => parent.clientWidth/4 - 6;
	 parent => <-.UIpopWindow.panel;
	 label = "Delete Series";
	 message = "Delete the seleted series";
#ifdef MSDOS
	 active = 0; // eFilm does the work so you don't have to
#else	    
	 active => is_valid(<-.i);
#endif	    
      };
      UIdirectoryDialog UIdirectory {
	 visible => <-.UIchooseDir.do;
#ifdef MSDOS
	 searchPattern => str_format("%s\\*",<-.searchPath);
#else	    
	 searchPattern => str_format("%s/*",<-.searchPath);
#endif	    
      };
      GMOD.copy_on_change set_default_directory {
	 input => <-.searchPath;
	 output => <-.UIdirectory.filename;
      };
      int i<NEportLevels=1> => .UIlist.selectedItem;
      IAC_PROJ.StrArrSub.string_array_subset string_range {
	 in => <-.read_DCMLIST.filenames;
	 start => read_DCMLIST.series_st_en[i][0];
	 end => read_DCMLIST.series_st_en[i][1];
      };
      string dirname<NEportLevels={0,2}> => UIdirectory.filename;
      string series<NEportLevels={0,2}> => read_DCMLIST.series[i];
      int read<NEportLevels={0,2}> => UIread.do;
      olink filenames => string_range.out;
   };

   macro ReadDICOM {
      UImod_panel panel {
	 height = 1000;
	 message = "Read DICOM control panel.";
	 title => "Read DICOM";
      };
      UIbutton SelectSeriesUI {
	 width => parent.clientWidth;
	 parent => <-.panel;
	 label = "Select Patient Series ";
      };
      ReadDCMLISTUI ReadDCMLISTUI {
	 visible => <-.SelectSeriesUI.do;
      };
      IAC_PROJ.ReadDICOM.ReadDICOMMods.read_dicom_files read_dicom_files {
	 filenames => <-.ReadDCMLISTUI.filenames;
	 trigger => <-.ReadDCMLISTUI.read;
      };
      IAC_PROJ.ReadDICOM.ReadDICOMData.DICOM_Header &Header<NEportLevels={1,0}> => read_dicom_files.header;
      UItext UISeriesInfo {
	 parent => <-.panel;
	 width => parent.clientWidth;
	 height => 6 * UIdata.UIfonts[0].lineHeight;
	 text => switch(is_valid(<-.Header.imageSeries.Columns)+1, "", str_format("Patient: %s\nDate: %s\nDesc: %s\nModality: %s %s\nSize: %dx%dx%d(%.1fx%.1fx%.1f mm)",
	 <-.Header.patient.PatientsNameP,
	 <-.Header.generalSeries.SeriesDate,
	 <-.Header.generalSeries.SeriesDescription,
	 <-.Header.generalSeries.ModalityGS,
	 <-.Header.generalSeries.ProtocolName,
	 <-.Header.imageSeries.Columns, <-.Header.imageSeries.Rows,
	 <-.Header.imageSeries.Slices,
	 <-.Header.imageSeries.Columns * <-.Header.imageSeries.XSpacing,
	 <-.Header.imageSeries.Rows * <-.Header.imageSeries.YSpacing,
	 <-.Header.imageSeries.Slices * <-.Header.imageSeries.SliceSpacing));
	 outputOnly = 1;
      };
      UIbutton PatientButton {
	 width => parent.clientWidth;
	 parent => <-.panel;
	 label = "Patient Information";
      };
      UIbutton StudyButton {
	 width => parent.clientWidth;
	 parent => <-.panel;
	 label = "Study Information";
      };
      UIbutton SeriesButton {
	 width => parent.clientWidth;
	 parent => <-.panel;
	 label = " Series Information";
      };
      UIbutton EquipmentButton {
	 width => parent.clientWidth;
	 parent => <-.panel;
	 label = " Equipment Information";
      };
      ReadDICOMPatientUI PatientInfo {
	 visible => <-.PatientButton.do;
	 patient => <-.Header.patient;
      };
      ReadDICOMStudyUI StudyInfo {
	 visible => <-.StudyButton.do;
	 generalStudy => <-.Header.generalStudy;
      };
      ReadDICOMSeriesUI SeriesInfo {
	 visible => <-.SeriesButton.do;
	 generalSeries => <-.Header.generalSeries;
      };
      ReadDICOMEquipmentUI EquipmentInfo {
	 visible => <-.EquipmentButton.do;
	 generalEquipment => <-.Header.generalEquipment;
      };
      UIlabel Copyright {
	 width => parent.clientWidth;
	 height => UIdata.UIfonts[0].lineHeight * 8;
	 parent => <-.panel;
	 alignment = "center";
	 label = "Rewritten by James S. Perrin as part\nof the Sir Jules Thorn Charitable Trust\nfunded CAMARA project.\nBased on reader made by AVS.\nUses PAPYRUS toolkit v3.71\nCopyright (c) 2002 by\nUniversity Hospital of Geneva";
      };
      GDM.DataObject DICOMVolume {
	 in => <-.read_dicom_files.volume;
      };
      olink out => read_dicom_files.volume;
      olink obj => DICOMVolume.obj;
      olink header => Header;
   };
};

