function getZoomData($uisubject, $SubjectKey, $StudyEventOID, $StudyEventRepeatKey)
{
    require dirname(__FILE__) . "/../../../lib/nanodicom/nanodicom.php";
    $importPathAnon = $uisubject->m_tblConfig["IMPORT_BASE_PATH"] . "dicom/anonymizedDICOM/";
    $imageDir = $uisubject->m_tblConfig["PATH_TO_AJAXZOOM_PICT"];
    $files = array();
    //Populate $files array
    if ($handle = opendir($imageDir)) {
        while ($file = readdir($handle)) {
            if ($file != "." && $file != "..") {
                $fileinfo = explode("_", $file);
                $file_SubjectKey = $fileinfo[0];
                $file_StudyEventOID = $fileinfo[1];
                $file_StudyEventRepeatKey = $fileinfo[2];
                if ($file_SubjectKey == $SubjectKey && $file_StudyEventOID == $StudyEventOID && $file_StudyEventRepeatKey == $StudyEventRepeatKey) {
                    $files[$file] = $file;
                }
            }
        }
        closedir($handle);
    }
    ksort($files);
    $zoomData = array();
    $i = 1;
    foreach ($files as $file) {
        $zoomData[$i]['f'] = $file;
        // File
        $zoomData[$i]['p'] = "/pic/zoom/dicom/";
        // Path
        $i++;
    }
    $dicomFilename = $importPathAnon . substr($zoomData[1]['f'], 0, strpos($zoomData[1]['f'], "."));
    $dicom = Nanodicom::factory($dicomFilename, 'simple');
    $dicom->parse(array('PixelSpacing'));
    $pixArr = explode("\\", $dicom->PixelSpacing);
    $pixelSpacingH = $pixArr[0];
    $pixelSpacingV = $pixArr[1];
    //Turn the array $zoomData into a string that can be passed over query string in one variable
    $zoomData = strtr(base64_encode(addslashes(gzcompress(serialize($zoomData), 9))), '+/=', '-_,');
    $zoomDatas = array($zoomData, $i - 1, $pixelSpacingH, $pixelSpacingV);
    return $zoomDatas;
}
 /**
  */
 public function provider()
 {
     $samples_dir = realpath(dirname(__FILE__)) . DIRECTORY_SEPARATOR . 'samples' . DIRECTORY_SEPARATOR;
     $output_dir = realpath(dirname(__FILE__)) . DIRECTORY_SEPARATOR . 'tests' . DIRECTORY_SEPARATOR;
     $files = array();
     if ($handle = opendir($samples_dir)) {
         while (false !== ($file = readdir($handle))) {
             if ($file != "." && $file != ".." && is_file($samples_dir . $file)) {
                 $files[] = $file;
             }
         }
         closedir($handle);
     }
     $data = array();
     foreach ($files as $file) {
         $filename = $samples_dir . $file;
         $dicom = Nanodicom::factory($filename);
         $data[] = array($dicom->summary(), file_get_contents($output_dir . $file . '.summary.txt'));
         unset($dicom);
     }
     return $data;
 }
Example #3
0
 /**
  * Parses the object.
  *
  * If the list of elements has a tag name, dictionaries will be loaded. For performance
  * is better to pass only arrays of the form:
  *   array(group, element)  where group and element are numbers (hex or decimal equivalents or any other base).
  * @param   mixed    array for a list of elements tags to read. parsing stops when all found. Or TRUE to force
  *                   load dictionaries when parsing. This tool force the reading of dictionaries
  * @param   boolean  a flag to test if dicom file has DCM header only.
  * @return	this
  */
 public function parse($vr_reading_list = TRUE, $check_dicom_preamble = FALSE)
 {
     return parent::parse($vr_reading_list, $check_dicom_preamble);
 }
Example #4
0
	function DisplayCTSeries($id, $study_num, $uid, $audit, $fix) {

		/* get the subject information */
		$sqlstring = "select * from subjects a left join enrollment b on a.subject_id = b.subject_id left join studies c on b.enrollment_id = c.enrollment_id where c.study_id = $id";
		$result = MySQLQuery($sqlstring, __FILE__, __LINE__);
		if (mysql_num_rows($result) > 0) {
			$row = mysql_fetch_array($result, MYSQL_ASSOC);
			$dbsubjectname = $row['name'];
			$dbsubjectdob = $row['birthdate'];
			$dbsubjectsex = $row['gender'];
			$dbstudydatetime = $row['study_datetime'];
		}
		else {
			echo "$sqlstring<br>";
		}
	
		?>
		<!--<a href="studies.php?id=<?$id?>&action=addseries&modality=CT">Add Series</a>-->
		<style type="text/css">
            .edit_inline { background-color: lightyellow; padding-left: 2pt; padding-right: 2pt; }
            .edit_textarea { background-color: lightyellow; }
			textarea.inplace_field { background-color: white; font-family: courier new; font-size: 8pt; border: 1pt solid gray; width: 800px;  }
			input.inplace_field { background-color: white; font-size: 8pt; border: 1pt solid gray; width: 200px;  }
		</style>
		
		<span class="smallnote"><b>Upload file(s) by clicking the button or drag-and-drop (Firefox and Chrome only)</b><br>
		DICOM files will only be associated with the study under which they were originally run... If you upload files from a different study, they won't show up here.</span>
		<br><br>
		<div id="file-uploader-demo1">		
			<noscript>			
				<p>Please enable JavaScript to use file uploader.</p>
				<!-- or put a simple form for upload here -->
			</noscript>         
		</div>
		<br>
		<table class="smalldisplaytable" width="100%">
			<thead>
				<tr>
					<th>Series</th>
					<th>Desc</th>
					<th>Protocol</th>
					<th>Time</th>
					<th>Notes</th>
					<th>Contrast</th>
					<th>Body part</th>
					<th>Options</th>
					<th>KVP</th>
					<th>Collection Dia</th>
					<th>Contrast Route</th>
					<th>Rotation Dir</th>
					<th>Exposure</th>
					<th>Tube current</th>
					<th>Filter type</th>
					<th>Power</th>
					<th>Kernel</th>
					<th>Spacing</th>
					<th>Image size</th>
					<th># files</th>
					<th>Size</th>
				</tr>
			</thead>
			<tbody>
				<?
					$sqlstring = "select * from ct_series where study_id = $id order by series_num";
					$result = MySQLQuery($sqlstring, __FILE__, __LINE__);
					while ($row = mysql_fetch_array($result, MYSQL_ASSOC)) {
						$ctseries_id = $row['ctseries_id'];
						$series_datetime = date('g:ia',strtotime($row['series_datetime']));
						$series_desc = $row['series_desc'];
						$protocol = $row['series_protocol'];
						$sequence = $row['series_sequencename'];
						$series_num = $row['series_num'];
						$series_contrastbolusagent = $row['series_contrastbolusagent'];
						$series_bodypartexamined = $row['series_bodypartexamined'];
						$series_scanoptions = $row['series_scanoptions'];
						$series_kvp = $row['series_kvp'];
						$series_datacollectiondiameter = $row['series_datacollectiondiameter'];
						$series_contrastbolusroute = $row['series_contrastbolusroute'];
						$series_rotationdirection = $row['series_rotationdirection'];
						$series_exposuretime = $row['series_exposuretime'];
						$series_xraytubecurrent = $row['series_xraytubecurrent'];
						$series_filtertype = $row['series_filtertype'];
						$series_generatorpower = $row['series_generatorpower'];
						$series_convolutionkernel = $row['series_convolutionkernel'];
						$series_spacingx = $row['series_spacingx'];
						$series_spacingy = $row['series_spacingy'];
						$series_spacingz = $row['series_spacingz'];
						$img_rows = $row['series_imgrows'];
						$img_cols = $row['series_imgcols'];
						$img_slices = $row['series_imgslices'];
						$numfiles = $row['numfiles'];
						$series_size = $row['series_size'];
						$series_status = $row['series_status'];
						$series_notes = $row['series_notes'];
						$data_type = $row['data_type'];
						$lastupdate = $row['lastupdate'];
						
						if ( (preg_match("/epfid2d1/i",$sequence)) && ($numfiles_beh < 1)) { $behcolor = "red"; } else { $behcolor = ""; }
						if ($numfiles_beh < 1) { $numfiles_beh = "-"; }

						$thumbpath = $GLOBALS['cfg']['archivedir'] . "/$uid/$study_num/$series_num/thumb.png";
						$realignpath = $GLOBALS['cfg']['archivedir'] . "/$uid/$study_num/$series_num/MotionCorrection.txt";

						/* --- audit the dicom files --- */
						if ($audit) {
							$dicoms = glob($GLOBALS['cfg']['archivedir'] . "/$uid/$study_num/$series_num/dicom/*.dcm");
							//print_r($dicoms);
							$dcmcount = count($dicoms);
							$dupes = null;
							if ($dcmcount > 0) {
								//$filename = $dicoms[0];
								$mergeddcms = null;
								foreach ($dicoms as $dcmfile) {
									$dicom = Nanodicom::factory($dcmfile, 'simple');
									$dicom->parse(array(array(0x0010, 0x0010), array(0x0010, 0x0030), array(0x0010, 0x0040), array(0x0018, 0x1030), array(0x0008, 0x103E), array(0x0010, 0x0020), array(0x0020, 0x0012), array(0x0020, 0x0013), array(0x0008, 0x0020), array(0x0008, 0x0030), array(0x0008, 0x0032)));
									$dicom->profiler_diff('parse');
									$filesubjectname = trim($dicom->value(0x0010, 0x0010));
									$filesubjectdob = trim($dicom->value(0x0010, 0x0030));
									$filesubjectsex = trim($dicom->value(0x0010, 0x0040));
									$fileprotocol = trim($dicom->value(0x0018, 0x1030));
									$fileseriesdesc = trim($dicom->value(0x0008, 0x103E));
									$fileseriesnum = trim($dicom->value(0x0020, 0x0011));
									$filescanid = trim($dicom->value(0x0010, 0x0020));
									$fileinstancenumber = trim($dicom->value(0x0020, 0x0013));
									$fileslicenumber = trim($dicom->value(0x0020, 0x0012));
									$fileacquisitiontime = trim($dicom->value(0x0008, 0x0032));
									$filestudydate = trim($dicom->value(0x0008, 0x0020));
									$filestudytime = trim($dicom->value(0x0008, 0x0030));
									unset($dicom);
									
									//echo "<pre>$fileprotocol, $protocol -- $fileslicenumber, $fileinstancenumber - [$filestudydate $filestudytime] - [$dbstudydatetime]</pre><br>";
									$filestudydatetime = $filestudydate . substr($filestudytime,0,6);
									$dbstudydatetime = str_replace(array(":","-"," "),"",$dbstudydatetime);
									$dbsubjectdob = str_replace(array(":","-"," "),"",$dbsubjectdob);
									if (
										($fileprotocol != $protocol) ||
										($dbsubjectname != $filesubjectname) ||
										($dbsubjectdob != $filesubjectdob) ||
										($dbsubjectsex != $filesubjectsex) ||
										($series_num != $fileseriesnum) ||
										($filestudydatetime != $dbstudydatetime)
										)
										{
										
										if ($fileprotocol != $protocol) {
											//echo "Protocol does not match (File: $fileprotocol DB: $protocol)<br>";
											//echo "files don't match DB<br>";
											$errantdcms[]{'filename'} = $dcmfile;
											$errantdcms[]{'error'} = "Protocol does not match (File: $fileprotocol DB: $protocol)";
										}
										if (strcasecmp($dbsubjectname,$filesubjectname) != 0) {
											if (($dbsubjectname == "") && ($filesubjectname) != "") {
												//echo "Patient name does not match (File: $filesubjectname DB: $dbsubjectname)<br>";
												$errantdcms[]{'filename'} = $dcmfile;
												$errantdcms[]{'error'} = "Patient name does not match (File: $filesubjectname DB: $dbsubjectname)";
											}
											elseif (($filesubjectname == "") && ($dbsubjectname) != "") {
												//echo "Patient name does not match (File: $filesubjectname DB: $dbsubjectname)<br>";
												$errantdcms[]{'filename'} = $dcmfile;
												$errantdcms[]{'error'} = "Patient name does not match (File: $filesubjectname DB: $dbsubjectname)";
											}
											else {
												if ((stristr($dbsubjectname, $filesubjectname) === false) && (stristr($filesubjectname, $dbsubjectname) === false)) {
													//echo "Patient name does not match (File: $filesubjectname DB: $dbsubjectname)<br>";
													$errantdcms[]{'filename'} = $dcmfile;
													$errantdcms[]{'error'} = "Patient name does not match (File: $filesubjectname DB: $dbsubjectname)";
												}
											}
										}
										
										if ($dbsubjectdob != $filesubjectdob) {
											//echo "Patient DOB does not match (File: $filesubjectdob DB: $dbsubjectdob)<br>";
											$errantdcms[]{'filename'} = $dcmfile;
											$errantdcms[]{'error'} = "Patient DOB does not match (File: $filesubjectdob DB: $dbsubjectdob)";
										}
										if ($dbsubjectsex != $filesubjectsex) {
											//echo "Patient sex does not match (File: $filesubjectsex DB: $dbsubjectsex)<br>";
											$errantdcms[]{'filename'} = $dcmfile;
											$errantdcms[]{'error'} = "Patient sex does not match (File: $filesubjectsex DB: $dbsubjectsex)";
										}
										if ($series_num != $fileseriesnum) {
											//echo "Series number does not match (File: $fileseriesnum DB: $series_num)<br>";
											$errantdcms[]{'filename'} = $dcmfile;
											$errantdcms[]{'error'} = "Series number does not match (File: $fileseriesnum DB: $series_num)";
										}
										if ($filestudydatetime != $dbstudydatetime) {
											//echo "Study datetime does not match (File: $filestudydatetime DB: $dbstudydatetime)<br>";
											$errantdcms[]{'filename'} = $dcmfile;
											$errantdcms[]{'error'} = "Study datetime does not match (File: $filestudydatetime DB: $dbstudydatetime)";
										}
										
									}
									//$mergeddcms{$filesubjectname}{$filesubjectdob}{$filesubjectsex}{$filestudydate}{$filestudytime}{$fileseriesnum}{$fileslicenumber}{$fileinstancenumber} = $dcmfile;
									$mergeddcms{$filesubjectname}{$filesubjectdob}{$filesubjectsex}{$filestudydate}{$filestudytime}{$fileseriesnum}{$fileslicenumber}{$fileinstancenumber}{$fileacquisitiontime}++;
									if ($mergeddcms{$filesubjectname}{$filesubjectdob}{$filesubjectsex}{$filestudydate}{$filestudytime}{$fileseriesnum}{$fileslicenumber}{$fileinstancenumber}{$fileacquisitiontime} > 1) {
										/* check the MD5 hash to see if the files really are the same */
										//$hash1 = md5_file(
										echo "Series $fileseriesnum contains duplicate files<br>";
										$dupes[$series_num] = 1;
										
										if ($fix) {
											/* move the duplicate file to the dicom/extra directory */
											if (!file_exists($GLOBALS['cfg']['archivedir'] . "/$uid/$study_num/$series_num/dicom/duplicates")) {
												mkdir($GLOBALS['cfg']['archivedir'] . "/$uid/$study_num/$series_num/dicom/duplicates");
											}
											echo "Moving [$dcmfile] -> [" . $GLOBALS['cfg']['archivedir'] . "/$uid/$study_num/$series_num/dicom/duplicates/" . GenerateRandomString(20) . ".dcm]<br>";
											rename($dcmfile, $GLOBALS['cfg']['archivedir'] . "/$uid/$study_num/$series_num/dicom/duplicates/" . GenerateRandomString(20) . ".dcm");
										}
									}
								}
							}
							echo "<pre>";
							//print_r($mergeddcms);
							print_r($errantdcms);
							echo "</pre>";
							
							/* move the errant files */
							if ($fix) {
								for($i=0;$i<count($errantdcms);$i++) {
									echo "Moving [$errantdcms[$i]{'filename'}] -> [" . $GLOBALS['dicomincomingpath'] . "/" . GenerateRandomString(20) . ".dcm]<br>";
									rename($errantdcms[$i]{'filename'},$GLOBALS['dicomincomingpath'] . "/" . GenerateRandomString(20) . ".dcm");
								}
							
								/* rename the files in the directory */
								$dicoms = glob($GLOBALS['cfg']['archivedir'] . "/$uid/$study_num/$series_num/dicom/*.dcm");
								//print_r($dicoms);
								$dcmcount = count($dicoms);
								if ($dcmcount > 0) {
									$dcmsize = 0;
									foreach ($dicoms as $dcmfile) {
										$dicom = Nanodicom::factory($dcmfile, 'simple');
										$dicom->parse(array(array(0x0010, 0x0010), array(0x0010, 0x0030), array(0x0010, 0x0040), array(0x0018, 0x1030), array(0x0008, 0x103E), array(0x0010, 0x0020), array(0x0020, 0x0012), array(0x0020, 0x0013), array(0x0008, 0x0020), array(0x0008, 0x0030), array(0x0008, 0x0032)));
										$dicom->profiler_diff('parse');
										$fileseriesnum = trim($dicom->value(0x0020, 0x0011));
										$fileinstancenumber = trim($dicom->value(0x0020, 0x0013));
										$fileslicenumber = trim($dicom->value(0x0020, 0x0012));
										$fileacquisitiontime = trim($dicom->value(0x0008, 0x0032));
										unset($dicom);
										
										$dcmsize += filesize($dcmfile);
										
										$newdcmfile = $GLOBALS['cfg']['archivedir'] . "/$uid/$study_num/$series_num/dicom/$uid" . "_$study_num" . "_$series_num" . "_" . sprintf("%05d",$fileslicenumber) . "_" . sprintf("%05d",$fileinstancenumber) . "_$fileacquisitiontime.dcm";
										//if (file_exists($newdcmfile)) {
											/* some DTI files are weird, so we'll append the aquisition time */
										//}
										echo "$dcmfile --> $newdcmfile<br>";
										rename($dcmfile, $newdcmfile);
									}
									
									/* update the database with the new info */
									$sqlstring5 = "update ct_series set series_size = $dcmsize, numfiles = $dcmcount where ctseries_id = $ctseries_id";
									$result5 = MySQLQuery($sqlstring5, __FILE__, __LINE__);
								}
							}
						}
						
						?>
						<script type="text/javascript">
							$(document).ready(function(){
								$(".edit_inline<? echo $ctseries_id; ?>").editInPlace({
									url: "series_inlineupdate.php",
									params: "action=editinplace&modality=CT&id=<? echo $ctseries_id; ?>",
									default_text: "<i style='color:#AAAAAA'>Add notes...</i>",
									bg_over: "white",
									bg_out: "lightyellow",
								});
							});
						</script>
						<tr>
							<td><?php 
echo $series_num;
?>
							<?
								if ($dupes[$series_num] == 1) {
									?><span style="color: white; background-color: red; padding: 1px 5px; font-weight: bold; font-size: 8pt">Contains duplicates</span> <?
								}
							?>
							</td>
							<td><?php 
echo $series_desc;
?>
</td>
							<td><?php 
echo $protocol;
?>
 <a href="preview.php?image=<?php 
echo $thumbpath;
?>
" class="preview"><img src="images/preview.gif" border="0"></a></td>
							<td><?php 
echo $series_datetime;
?>
</td>
							<td><span id="series_notes" class="edit_inline<? echo $ctseries_id; ?>" style="background-color: lightyellow; padding: 1px 3px; font-size: 8pt;"><? echo $series_notes; ?></span></td>
							<td><?php 
echo $series_contrastbolusagent;
?>
</td>
							<td><?php 
echo $series_bodypartexamined;
?>
</td>
							<td><?php 
echo $series_scanoptions;
?>
</td>
							<td><?php 
echo $series_kvp;
?>
<span class="tiny">V</span></td>
							<td><?php 
echo $series_datacollectiondiameter;
?>
<span class="tiny">mm</span></td>
							<td><?php 
echo $series_contrastbolusroute;
?>
</td>
							<td><?php 
echo $series_rotationdirection;
?>
</td>
							<td><?php 
echo $series_exposuretime;
?>
<span class="tiny">ms</span></td>
							<td><?php 
echo $series_xraytubecurrent;
?>
<span class="tiny">mA</span></td>
							<td><?php 
echo $series_filtertype;
?>
</td>
							<td><?php 
echo $series_generatorpower;
?>
<span class="tiny">V</span></td>
							<td><?php 
echo $series_convolutionkernel;
?>
</td>
							<td><?php 
echo number_format($series_spacingx, 1);
?>
 &times; <?php 
echo number_format($series_spacingy, 1);
?>
 &times; <?php 
echo number_format($series_spacingz, 1);
?>
</td>
							<td><?php 
echo $img_cols;
?>
 &times; <?php 
echo $img_rows;
?>
 &times; <?php 
echo $img_slices;
?>
</td>
							<td>
								<?php 
echo $numfiles;
?>
								<? if (($dcmcount != $numfiles) && ($audit)) { ?><span style="color: white; background-color: red; padding: 1px 5px; font-weight: bold"><?php 
echo $dcmcount;
?>
</span> <? } ?>
							</td>
							<td nowrap><?php 
echo HumanReadableFilesize($series_size);
?>
 <a href="download.php?modality=ct&type=dicom&seriesid=<?php 
echo $ctseries_id;
?>
" border="0"><img src="images/download16.png" title="Download <?php 
echo $data_type;
?>
 data"></a></td>
						</tr>
						<?
					}
				?>
			</tbody>
		</table>
		<?
	}
Example #5
0
 /**
  * Public method to get the summary of the given file.
  *
  * @param   string   how the output is returned. Either as string (ready to be echoed) or array
  * @return  mixed|false	Either a string, array or FALSE (when file is not DICOM)
  */
 public function summary($output = 'string')
 {
     // Parse the file
     $this->parse();
     $transfer_syntax = trim($this->get(0x2, 0x10, 'UN'));
     $transfer_syntax .= ($transfer_syntax == 'UN' or !array_key_exists($transfer_syntax, Nanodicom_Dictionary::$transfer_syntaxes)) ? ' - Unknow' : ' - Parsed using: ' . Nanodicom_Dictionary::$transfer_syntaxes[$transfer_syntax][0];
     //.'. Parsed using: '.Nanodicom_Dictionary::$transfer_syntaxes[$this->_transfer_syntax][0];
     if ($transfer_syntax == 'UN - Unknow') {
         $transfer_syntax .= ' [Parsed Using: ' . $this->_transfer_syntax . ' - ' . Nanodicom_Dictionary::$transfer_syntaxes[$this->_transfer_syntax][0] . ']';
     }
     // Checking for "rows" since that value should be set for images.
     $has_images = $this->get(0x28, 0x10, 'N/A') != 'N/A' ? 'YES' : 'NO';
     $statuses = array('Not parsed yet', 'Partially parsed. Some tags were found', 'Successfully parsed!', 'Failed');
     $values = array('Filename:          ' => basename($this->_location), 'Transfer Syntax:   ' => $transfer_syntax, 'DICOM file?        ' => $statuses[$this->status], 'Has DCM preamble?  ' => $this->has_dicom_preamble === TRUE ? 'YES' : 'NO', 'Has Metadata?      ' => $this->get(0x2, 0x0, FALSE) ? 'YES' : 'NO', 'Modality:          ' => $this->get(0x8, 0x60, 'UN'), 'Patient Name:      ' => $this->get(0x10, 0x10, 'N/A'), 'Images?            ' => $has_images);
     $pixel_representation = array('0' => 'Unsigned Integer. Only positive values allowed.', '1' => '2\'s complement. Negative and positive allowed.', 'N/A' => 'Not available');
     $planar_configuration = array('0' => 'Color-by-pixel: RGB, RGB, RGB..', '1' => 'Color-by-plane: RRR..., GGG..., BBB...', 'N/A' => 'Not available');
     if ($has_images == 'YES') {
         $values = $values + array('Rows:              ' => $this->get(0x28, 0x10, 'N/A'), 'Cols:              ' => $this->get(0x28, 0x11, 'N/A'), 'Samples per pixel: ' => $this->get(0x28, 0x2, 'N/A'), 'Bits Allocated:    ' => $this->get(0x28, 0x100, 'N/A'), 'Bits Stored:       ' => $this->get(0x28, 0x101, 'N/A'), 'High bit:          ' => $this->get(0x28, 0x102, 'N/A'), 'Dose scaling:      ' => $this->get(0x3004, 0xe, 'N/A'), 'Window Width:      ' => $this->get(0x28, 0x1051, 'N/A'), 'Window Center:     ' => $this->get(0x28, 0x1050, 'N/A'), 'Rescale intercept: ' => $this->get(0x28, 0x1052, 'N/A'), 'Rescale slope:     ' => $this->get(0x28, 0x1053, 'N/A'), 'Number of Frames:  ' => $this->get(0x28, 0x8, 'N/A'), 'Photometric Inter: ' => $this->get(0x28, 0x4, 'N/A'), 'Px Representation: ' => $this->get(0x28, 0x103, 'N/A') . ' - ' . Nanodicom::array_get($pixel_representation, $this->get(0x28, 0x103, 'N/A'), 'Wrong'), 'Planar Config:     ' => $this->get(0x28, 0x6, 'N/A') . ' - ' . Nanodicom::array_get($planar_configuration, $this->get(0x28, 0x6, 'N/A'), 'Wrong'));
     }
     if ($output == 'string') {
         $output = '';
         foreach ($values as $index => $value) {
             $output .= $index . "\t" . $value . "\n";
         }
         // Set the output back to values
         $values = $output;
     }
     return $values;
 }
Example #6
0
 $result = mysql_query($sqlstring) or die("Query failed: " . mysql_error() . "<br><i>{$sqlstring}</i><br>");
 $row = mysql_fetch_array($result, MYSQL_ASSOC);
 if (mysql_num_rows($result) > 0) {
     $found = 1;
     $seriesid = $row['ppiseries_id'];
 }
 if ($found) {
     /* check the dicom files */
     $dicoms = glob("{$archivedir}/{$subject}/{$study}/{$series}/dicom/*.dcm");
     //print_r($dicoms);
     $dcmcount = count($dicoms);
     if ($dcmcount > 0) {
         $filename = $dicoms[0];
         //echo "$filename\n";
         /* open the dicom file, check the 3 important tags */
         $dicom = Nanodicom::factory($filename, 'simple');
         $dicom->parse(array(array(0x10, 0x10), array(0x10, 0x30), array(0x10, 0x40)));
         /* patient  name,dob,sex */
         // Only a small subset of the dictionary entries were loaded
         $dicom->profiler_diff('parse');
         //echo 'Patient name if exists: '.$dicom->value(0x0010, 0x0010)."\n"; // Patient Name if exists
         // This will return nothing because dictionaries were not loaded
         //echo 'Patient name should be empty here: '.$dicom->PatientName."\n";
         $filesubjectname = trim($dicom->value(0x10, 0x10));
         $filesubjectdob = trim($dicom->value(0x10, 0x30));
         $filesubjectsex = trim($dicom->value(0x10, 0x40));
         $fileprotocol = trim($dicom->value(0x18, 0x1030));
         $fileseriesdesc = trim($dicom->value(0x8, 0x103e));
         $filescanid = trim($dicom->value(0x10, 0x20));
         //print_r($dicom);
         if (strcasecmp($subjectname, $filesubjectname) != 0) {
Example #7
0
 /**
  * Public method to get the images from the dicom object
  *
  * @param integer  a default window width
  * @param integer  a default window center
  * @return mixed false if something is missing or not image data found, otherwise an
  * array of GD objects
  */
 public function get_images($width = NULL, $center = NULL)
 {
     // Parse the object if not parsed yet
     $this->parse();
     // Set the profiler
     $this->profiler['pixel']['start'] = microtime(TRUE);
     $return = $this->_check_driver();
     // If FALSE, driver not found
     if (!$return) {
         return FALSE;
     }
     // Supported transfer syntaxes
     if (!array_key_exists(trim($this->_transfer_syntax), self::$reading_image_transfer_syntaxes)) {
         // Not supported transfer syntax found
         throw new Nanodicom_Exception('Transfer syntax ":syntax" not supported', array(':syntax' => $this->_transfer_syntax), 300);
     }
     // Let's read some values from DICOM file
     $rows = $this->get(0x28, 0x10);
     $cols = $this->get(0x28, 0x11);
     if ($rows == NULL or $cols === NULL) {
         // There is no rows, no samples per pixel, no pixel data or malformed dicom file
         throw new Nanodicom_Exception('There is no rows, no samples per pixel, no pixel data or malformed dicom file', NULL, 301);
     }
     $samples_per_pixel = $this->get(0x28, 0x2, 1);
     $bits_allocated = $this->get(0x28, 0x100);
     $bits_stored = $this->get(0x28, 0x101);
     $high_bit = $this->get(0x28, 0x102);
     $dose_scaling = $this->get(0x3004, 0xe, 1);
     $window_width = $width == NULL ? $this->get(0x28, 0x1051, 0) : $width;
     $window_center = $center == NULL ? $this->get(0x28, 0x1050, 0) : $center;
     $rescale_intercept = $this->get(0x28, 0x1052, 0);
     $rescale_slope = $this->get(0x28, 0x1053, 1);
     $number_of_frames = (int) $this->get(0x28, 0x8, 1);
     $pixel_representation = $this->get(0x28, 0x103);
     $photometric_interpretation = trim($this->get(0x28, 0x4, 'NONE'));
     $planar_configuration = $this->get(0x28, 0x6, 0);
     $transfer_syntax_uid = trim($this->get(0x2, 0x10));
     $blob = $this->get(0x7fe0, 0x10);
     // Save some values for internal use
     // TODO: improve this, probably using $this->pixeler[]?
     $this->_rows = $rows;
     $this->_cols = $cols;
     $this->_dose_scaling = $dose_scaling;
     $this->_rescale_slope = $rescale_slope;
     $this->_rescale_intercept = $rescale_intercept;
     $this->_samples_per_pixel = $samples_per_pixel;
     $this->_pixel_representation = $pixel_representation;
     // Window Center and Width can have multiple values. By now, just reading the first one.
     // It assumes the delimiter is the "\"
     if (!(strpos($window_center, "\\") === FALSE)) {
         $temp = explode("\\", $window_center);
         $window_center = (int) $temp[0];
     }
     if (!(strpos($window_width, "\\") === FALSE)) {
         $temp = explode("\\", $window_width);
         $window_width = (int) $temp[0];
     }
     // Setting some values
     $images = array();
     $max = array();
     $min = array();
     $current_position = $starting_position = 0;
     $current_image = 0;
     $bytes_to_read = (int) $bits_allocated / 8;
     $image_size = $cols * $rows * $samples_per_pixel * $bytes_to_read;
     list($vr_mode, $endian) = Nanodicom::decode_transfer_syntax($transfer_syntax_uid);
     $this->_vr_mode = $vr_mode;
     $this->_endian = $endian;
     if ($transfer_syntax_uid == '1.2.840.10008.1.2.4.50') {
         // This is jpeg lossy 8-bits. Just get the data.
         $images = array();
         $counter = 0;
         foreach ($blob as $group => $elements) {
             foreach ($elements as $element => $indexes) {
                 if ($element == Nanodicom::SEQUENCE_DELIMITER) {
                     continue;
                 }
                 foreach ($indexes as $values) {
                     $data = $values;
                     if ($counter == 0) {
                         // Read Basic Offset Table
                     } else {
                         // It is a real Item
                         if (!isset($data['done'])) {
                             // Read value if not read yet
                             $this->_read_value_from_blob($data, $group, $element);
                         }
                         $images[] = $this->_read_image_blob($data['val']);
                     }
                     $counter++;
                 }
             }
         }
         return $images;
     }
     if ($transfer_syntax_uid == '1.2.840.10008.1.2.5') {
         // It is "RLE - Run Length Encoding, Lossless"
         $counter = 0;
         $temp = array();
         foreach ($blob as $group => $elements) {
             foreach ($elements as $element => $indexes) {
                 if ($element == Nanodicom::SEQUENCE_DELIMITER) {
                     continue;
                 }
                 foreach ($indexes as $values) {
                     $data = $values;
                     $data['g'] = $group;
                     $data['e'] = $element;
                     if ($counter == 0) {
                         // Read Basic Offset Table
                     } else {
                         // It is a real Item
                         $dir = realpath(dirname($this->_location)) . DIRECTORY_SEPARATOR;
                         $file = basename($this->_location);
                         if (!isset($data['done'])) {
                             // Read value if not read yet
                             $this->_read_value_from_blob($data, $group, $element);
                         }
                         // This is the item data
                         $item = $data['val'];
                         // Save the header
                         $header = array();
                         // 16 Unsigned Long values
                         for ($i = 0; $i <= 16; $i++) {
                             $chunk = substr($item, 4 * $i, 4);
                             $header[] = $this->{Nanodicom::$_read_int}(4, Nanodicom::LITTLE_ENDIAN, 4, Nanodicom::UNSIGNED, $chunk);
                         }
                         $total_segments = array_shift($header);
                         $segment_index = 0;
                         foreach ($header as $starting_byte_of_segment) {
                             // This is a segment, do the uncompression
                             if ($starting_byte_of_segment == 0) {
                                 // Only process if the segment has a positive starting value
                                 break;
                             }
                             $size_of_segment = $header[$segment_index + 1] == 0 ? strlen($item) - $starting_byte_of_segment : $header[$segment_index + 1] - $starting_byte_of_segment;
                             $temp[$counter - 1][$segment_index] = '';
                             $expected_segment_size = $cols * $rows * $bytes_to_read / $total_segments;
                             $bytes_count = $current_segment_size = 0;
                             while ($bytes_count < $size_of_segment) {
                                 $tmp = $starting_byte_of_segment + $bytes_count;
                                 // Read "n"
                                 $n = substr($item, $starting_byte_of_segment + $bytes_count, 1);
                                 $n = $this->{Nanodicom::$_read_int}(1, Nanodicom::LITTLE_ENDIAN, 1, Nanodicom::SIGNED, $n);
                                 // Add 1
                                 $bytes_count++;
                                 if ($n >= 0 and $n <= 127) {
                                     $temp[$counter - 1][$segment_index] .= substr($item, $starting_byte_of_segment + $bytes_count, $n + 1);
                                     $bytes_count = $bytes_count + $n + 1;
                                     $current_segment_size = $current_segment_size + $n + 1;
                                 } elseif ($n <= -1 and $n >= -127) {
                                     $byte = substr($item, $starting_byte_of_segment + $bytes_count, 1);
                                     $temp[$counter - 1][$segment_index] .= str_repeat($byte, -$n + 1);
                                     $bytes_count++;
                                     $current_segment_size = $current_segment_size - $n + 1;
                                 } else {
                                     // Do nothing
                                 }
                             }
                             $segment_index++;
                         }
                     }
                     // Increment counter
                     $counter++;
                 }
             }
         }
         $counter--;
         $blob = '';
         for ($count = 0; $count < $counter; $count++) {
             if ($photometric_interpretation == 'RGB') {
                 if ($planar_configuration == 1) {
                     // Color-by-plane: RRR..., GGG..., BBB...
                     $blob .= implode('', $temp[$count]);
                 } else {
                     // Color-by-pixel: RGB, RGB, RGB..
                 }
             } else {
                 $dimension = $cols * $rows;
                 for ($i = 0; $i < $dimension; $i++) {
                     $part = '';
                     foreach ($temp[$count] as $segment) {
                         $part = substr($segment, $i, 1) . $part;
                     }
                     $blob .= $part;
                 }
             }
         }
     }
     // Blob here has "uncompressed" data (from raw or RLE)
     if ($photometric_interpretation == 'PALETTE COLOR') {
         $this->_samples_per_pixel = 3;
         $palettes = array();
         $palettes['R'] = array($this->get(0x28, 0x1101), $this->get(0x28, 0x1201));
         $palettes['G'] = array($this->get(0x28, 0x1102), $this->get(0x28, 0x1202));
         $palettes['B'] = array($this->get(0x28, 0x1103), $this->get(0x28, 0x1203));
         $palettes['A'] = array($this->get(0x28, 0x1104), $this->get(0x28, 0x1204));
         $entries = (int) $palettes['R'][0]['val1'];
         $entries = $entries == 0 ? pow(2, 16) : $entries;
         $first = $palettes['R'][0]['val2'];
         $size = $palettes['R'][0]['val3'];
         $palette_byte_size = (int) $size / 8;
         $offset = 8;
         $current_position = 0;
         $colors = array('R', 'G', 'B');
         // Now let's create the right values for the images
         for ($index = 0; $index < $number_of_frames; $index++) {
             // Create the image object
             $image = self::create_image($cols, $rows);
             for ($y = 0; $y < $rows; $y++) {
                 for ($x = 0; $x < $cols; $x++) {
                     $rgb = array();
                     $value = $this->_read_gray($blob, $current_position, $bytes_to_read);
                     $palette_index = $value <= $first ? $first : ($value > $first + $entries ? $first + $entries - 1 : $value);
                     $current_position += $bytes_to_read;
                     for ($sample = 0; $sample < 3; $sample++) {
                         $tmp = $this->_read_gray($palettes[$colors[$sample]][1], $palette_byte_size * $palette_index, $palette_byte_size);
                         $rgb[$sample] = $tmp >> 8;
                     }
                     // Set the color
                     $color = $this->_allocate_color_rgb($image, $rgb);
                     $rgb = NULL;
                     // Set the pixel value
                     $this->_set_pixel($image, $x, $y, $color);
                     $color = NULL;
                 }
             }
             // Append the current image
             $images[] = $image;
             $image = NULL;
         }
         return $images;
     } else {
         // Do this if no window center and window width are set and when samples per pixel is 1 (gray images).
         if (($window_center == 0 or $window_width == 0) and $samples_per_pixel == 1) {
             $length = strlen($blob);
             // This is costly performance wise! :(
             while ($current_position < $starting_position + $length) {
                 if ($current_position == $starting_position + $current_image * $image_size) {
                     // A new image has been found
                     $x = 0;
                     $y = 0;
                     $max[$current_image] = -200000;
                     // Small enough so it will be properly calculated
                     $min[$current_image] = 200000;
                     // Large enough so it wil be properly calculated
                     $current_image++;
                 }
                 $gray = $this->_read_gray($blob, $current_position, $bytes_to_read);
                 $current_position += $bytes_to_read;
                 // Getting the max
                 if ($gray > $max[$current_image - 1]) {
                     // max
                     $max[$current_image - 1] = $gray;
                 }
                 // Getting the min
                 if ($gray < $min[$current_image - 1]) {
                     // min
                     $min[$current_image - 1] = $gray;
                 }
                 $y++;
                 if ($y == $cols) {
                     // Next row
                     $x++;
                     $y = 0;
                 }
             }
         }
     }
     $current_position = $starting_position = 0;
     // Now let's create the right values for the images
     for ($index = 0; $index < $number_of_frames; $index++) {
         if ($samples_per_pixel == 1) {
             // Real max and min according to window center & width (if set)
             $maximum = ($window_center != 0 and $window_width != 0) ? round($window_center + $window_width / 2) : $max[$index];
             $minimum = ($window_center != 0 and $window_width != 0) ? round($window_center - $window_width / 2) : $min[$index];
             // Check if window and level are sent
             $maximum = (!empty($window) and !empty($level)) ? round($level + $window / 2) : $maximum;
             $minimum = (!empty($window) and !empty($level)) ? round($level - $window / 2) : $minimum;
             if ($maximum == $minimum) {
                 // Something wrong. Avoid having a zero division
                 throw new Nanodicom_Exception('Division by zero', NULL, 302);
             }
         }
         // Create the image object
         $image = self::create_image($cols, $rows);
         $pixels = array();
         for ($y = 0; $y < $rows; $y++) {
             for ($x = 0; $x < $cols; $x++) {
                 switch ($samples_per_pixel) {
                     case 1:
                         $gray = $this->_read_gray($blob, $current_position, $bytes_to_read);
                         $current_position += $bytes_to_read;
                         // truncating pixel values over max and below min
                         $gray = $gray > $maximum ? $maximum : $gray;
                         $gray = $gray < $minimum ? $minimum : $gray;
                         // Converting to gray value
                         $gray = ($gray - $minimum) / ($maximum - $minimum) * 255;
                         // For MONOCHROME1 we have to invert the pixel values.
                         if ($photometric_interpretation == 'MONOCHROME1') {
                             $gray = 255 - $gray;
                         }
                         // Set the (gray) color
                         $color = $this->_allocate_color_gray($image, $gray);
                         $gray = NULL;
                         break;
                     case 3:
                         // It has 3 colors
                         $rgb = array();
                         for ($sample = 0; $sample < $samples_per_pixel; $sample++) {
                             $current_position = $planar_configuration == 0 ? $current_position : $sample * ($rows * $cols) + ($y * $cols + $x);
                             $rgb[$sample] = $this->_read_gray($blob, $current_position, $bytes_to_read);
                             $current_position += $bytes_to_read;
                         }
                         // Set the color
                         $color = $this->_allocate_color_rgb($image, $rgb);
                         $rgb = NULL;
                         break;
                     default:
                         break;
                 }
                 // Set the pixel value
                 $this->_set_pixel($image, $x, $y, $color);
                 $color = NULL;
             }
         }
         // Append the current image
         $images[] = $image;
         $image = NULL;
     }
     // Collect the ending time for the profiler
     $this->profiler['pixel']['end'] = microtime(TRUE);
     return $images;
 }
Example #8
0
function DisplayAllScanParamaters($filename)
{
    $urllist['Home'] = "index.php";
    $urllist['Scan Params'] = "series.php";
    NavigationBar("MR Scan Parameters", $urllist);
    $dicom = Nanodicom::factory($filename, 'dumper');
    $tags = $dicom->dump();
    //print_r($tags);
    $lines = explode("\n", $tags);
    ?>
		<div align="center">
		<table style="font-size: 10pt; border: 1px solid #DDDDDD" cellspacing="0" cellpadding="2">
			<tr>
				<td colspan="3" style="font-weight: bold; font-size: 14pt; text-align: center; padding:10px; border-bottom: 2px solid #666666">MR Sequence Parameters <span style="color:darkred">(CONTAINS PHI - DO NOT SHARE)</span></td>
			</tr>
		<?php 
    $lasttag1 = '';
    foreach ($lines as $line) {
        preg_match('/.*(\\w{4}):(\\w{4})\\s+(\\w+)\\s+([A-Z]{2})\\s+(\\d+)\\s+\\[(.*)\\].*/', $line, $matches);
        //print_r($matches);
        $tag1 = $matches[1];
        $tag2 = $matches[2];
        $name = $matches[3];
        $value = $matches[6];
        if (trim($tag1) == "") {
            continue;
        }
        preg_match_all('/((?:^|[A-Z])[a-z]+)/', $name, $matches2);
        $pieces = $matches2[0];
        $name = implode(' ', $pieces);
        if ($tag1 == "0018") {
            switch ($tag2) {
                case '0050':
                    $units = 'mm';
                    break;
                case '0080':
                    $units = 'ms';
                    break;
                case '0081':
                    $units = 'ms';
                    break;
                case '0082':
                    $units = 'ms';
                    break;
                case '0084':
                    $units = 'Hz';
                    break;
                case '0087':
                    $units = 'T';
                    break;
                case '0093':
                    $units = '%';
                    break;
                case '0094':
                    $units = '%';
                    break;
                case '1314':
                    $units = '&deg;';
                    break;
                default:
                    $units = '';
            }
        }
        if ($lasttag1 != $tag1) {
            $style = "border-top: solid 2px #666666";
        } else {
            $style = "border-top: solid 1px #CCCCCC";
        }
        ?>
			<tr>
				<td style="color:darkblue; <?php 
        echo $style;
        ?>
"><?php 
        echo $tag1;
        ?>
:<?php 
        echo $tag2;
        ?>
</td>
				<td style="<?php 
        echo $style;
        ?>
"><?php 
        echo $name;
        ?>
</td>
				<td style="<?php 
        echo $style;
        ?>
"><?php 
        echo $value;
        ?>
 <span class="tiny"><?php 
        echo $units;
        ?>
</span></td>
			</tr>
			<?php 
        $lasttag1 = $tag1;
    }
    ?>
			<tr>
				<td colspan="3" style="font-size:8pt; border-top: solid 2px #666666; padding:8px">Generated by NiDB <?php 
    echo date("D M j, Y g:i a T");
    ?>
. Tags extracted using <a href="http://www.nanodicom.org">Nanodicom</a>
				<br>Based on DICOM file [<?php 
    echo $filename;
    ?>
]</td>
			</tr>
		</table>
		</div>
		<?php 
    unset($dicom);
}
 /**
  *Extract image from DICOM file and save it as PNG
  *Saved image are stored in the data directory, dicom_images folder
  *Naming convention $SubjectKey_$StudyEventOID_$StudyEventRepeatKey_$FormOID_$FormRepeatKey_$imageSuffix_UID.png
  *       allow the identification of the image     
  *@author wlt        
  **/
 public function saveImage($file, $SubjectKey, $StudyEventOID, $StudyEventRepeatKey, $FormOID = "", $FormRepeatKey = "", $imageSuffix = "")
 {
     $this->addLog(__METHOD__ . "({$file},{$SubjectKey},{$StudyEventOID},{$StudyEventRepeatKey},{$FormOID},{$FormRepeatKey},{$imageSuffix})", TRACE);
     $importPath = $this->m_tblConfig["IMPORT_BASE_PATH"] . "dicom";
     $exportPath = $this->m_tblConfig["PATH_TO_AJAXZOOM_PICT"];
     $filename = $importPath . "/" . $file;
     //Checking filename parameter
     if (!file_exists($filename)) {
         $this->addLog(__METHOD__ . " File {$filename} does not exists", FATAL);
     }
     //We need at least a StudyEventOID and a StudyEventRepeatKey
     if ($StudyEventOID == "" || $StudyEventRepeatKey == "") {
         $this->addLog(__METHOD__ . " StudyEventOID and StudyEventRepeatKey must be set", FATAL);
     }
     //Handle of Exception must be done at the upper level, to be added to the import report
     $dicom = Nanodicom::factory($filename, 'pixeler');
     $imageFilename = $SubjectKey . "_" . $StudyEventOID . "_" . $StudyEventRepeatKey . "_" . $FormOID . "_" . $FormRepeatKey . "_" . $imageSuffix . "_" . $file;
     if (!file_exists($imageFilename . '.0.jpg')) {
         $images = $dicom->get_images();
         if ($images !== FALSE) {
             foreach ($images as $index => $image) {
                 $dicom->write_image($image, $exportPath . "/" . $imageFilename . '.' . $index);
             }
         } else {
             throw new Exception("For file {$filename} there are no DICOM images or transfer syntax not supported yet");
         }
         $images = NULL;
         $dicom = Nanodicom::factory($filename, 'anonymizer');
         file_put_contents(dirname($filename) . "/anonymizedDICOM/{$imageFilename}", $dicom->anonymize());
         unset($dicom);
     } else {
         throw new Exception("File {$imageFilename}.0.jpg is already here");
     }
     unset($dicom);
 }
Example #10
0
            // If using another library, for example, imagemagick, the following should be done:
            // $images = $dicom->set_driver('imagick')->get_images();
            if ($images !== FALSE) {
                foreach ($images as $index => $image) {
                    // Defaults to jpg
                    $dicom->write_image($image, $dir . $file . '.' . $index);
                    // To write another format, pass the format in second parameter.
                    // This will write a png image instead
                    // $dicom->write_image($image, $dir.$file.'.'.$index, 'png');
                }
            } else {
                echo "There are no DICOM images or transfer syntax not supported yet.\n";
            }
            $images = NULL;
        } else {
            echo "Image already exists\n";
        }
        unset($dicom);
    } catch (Nanodicom_Exception $e) {
        echo 'File failed. ' . $e->getMessage() . "\n";
    }
    // 21) Prints summary report
    try {
        echo "21) Prints summary report\n";
        $dicom = Nanodicom::factory($filename);
        echo $dicom->summary();
        unset($dicom);
    } catch (Nanodicom_Exception $e) {
        echo 'File failed. ' . $e->getMessage() . "\n";
    }
}