|
|
@@ -74,6 +74,66 @@ namespace Models {
|
|
|
];
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * Get patient files existing data.
|
|
|
+ */
|
|
|
+ public function patientFilesExistingPost($User, $data) {
|
|
|
+ $ID_user = $User->ID;
|
|
|
+
|
|
|
+ $where = ' P.ID = V.fk_patient ';
|
|
|
+ if($User->type=='physician') {
|
|
|
+ $where .= ' AND P.fk_user = '.$User->ID;
|
|
|
+ }
|
|
|
+ else if($User->type=='reader') {
|
|
|
+ $where .= ' AND V.fk_reader = '.$User->ID.' AND V.completed IS NULL ';
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ $where .= ' AND P.fk_user = '.$User->ID;
|
|
|
+ }
|
|
|
+
|
|
|
+ $filter = '(P.lastname LIKE \'%'.$data['filter'].'%\' OR P.firstname LIKE \'%'.$data['filter'].'%\')';
|
|
|
+
|
|
|
+ $statement = $this->DataInterface->DatabaseConnection->prepare(
|
|
|
+ "SELECT JSON_EXTRACT(data, '$.patientListFields') AS data FROM settings"
|
|
|
+ );
|
|
|
+ if(!$statement->execute()) {
|
|
|
+ return ['result' => 'ERROR', 'reason' => 'internal_error', 'message' => 'Database error', 'data' => $statement->errorInfo()];
|
|
|
+ }
|
|
|
+ $settings = json_decode($statement->fetchAll(\PDO::FETCH_ASSOC)[0]['data']);
|
|
|
+ $patientListFields=[];
|
|
|
+ foreach($settings as $S) {
|
|
|
+ $patientListFields[str_replace(' ', '_', $S->name)] = $S->display;
|
|
|
+ }
|
|
|
+
|
|
|
+ $statement = $this->DataInterface->DatabaseConnection->prepare(
|
|
|
+ "SELECT
|
|
|
+ P.*,
|
|
|
+ (SELECT COUNT(visit.ID) FROM visit WHERE fk_patient = P.ID) as visitCount,
|
|
|
+ (SELECT GROUP_CONCAT(CONCAT(visit.ID, ',', visit.visitDate, ',', COALESCE(visit.area, '')) ORDER BY visit.visitDate DESC SEPARATOR ';') FROM visit WHERE fk_patient = P.ID) as visits,
|
|
|
+ (SELECT GROUP_CONCAT(CONCAT(visit.ID, ',', visit.number) ORDER BY visit.visitDate DESC SEPARATOR ';') FROM visit WHERE fk_patient = P.ID) as reader_visits,
|
|
|
+ (SELECT COUNT(media.ID) FROM media, visit WHERE JSON_VALUE(media.metrics, '$.fps') IS NULL AND media.fk_visit = visit.ID AND visit.fk_patient = P.ID) as imageCount,
|
|
|
+ (SELECT COUNT(media.ID) FROM media, visit WHERE media.fk_visit = visit.ID AND visit.fk_patient = P.ID) as mediaCount,
|
|
|
+ V.visitDate AS lastVisit,
|
|
|
+ V.number AS visitNumber,
|
|
|
+ V.ID AS visitID
|
|
|
+ FROM patient P, visit V
|
|
|
+ WHERE $where AND $filter
|
|
|
+ GROUP BY P.ID
|
|
|
+ ORDER BY V.visitDate DESC, V.ID DESC"
|
|
|
+ );
|
|
|
+ if(!$statement->execute()) {
|
|
|
+ return ['result' => 'ERROR', 'reason' => 'internal_error', 'message' => 'Database error', 'data' => $statement->errorInfo()];
|
|
|
+ }
|
|
|
+ $visits = $statement->fetchAll(\PDO::FETCH_ASSOC);
|
|
|
+
|
|
|
+ return [
|
|
|
+ 'result' => 'OK',
|
|
|
+ 'visits' => $visits,
|
|
|
+ 'user' => $User,
|
|
|
+ 'patientListFields' => $patientListFields
|
|
|
+ ];
|
|
|
+ }
|
|
|
+
|
|
|
/**
|
|
|
* Get patient files new data.
|
|
|
*/
|
|
|
@@ -679,9 +739,9 @@ namespace Models {
|
|
|
// create or select visit
|
|
|
$visitID = 0;
|
|
|
$statement = $this->DataInterface->DatabaseConnection->prepare(
|
|
|
- "SELECT visit.* FROM visit, patient WHERE patient.ID = visit.fk_patient AND visit.number = :visitID"
|
|
|
+ "SELECT visit.* FROM visit, patient WHERE patient.ID = visit.fk_patient AND visit.studyInstanceUID = :studyInstanceUID"
|
|
|
);
|
|
|
- $statement->bindParam(':visitID', $data['all']['StudyID']);
|
|
|
+ $statement->bindParam(':studyInstanceUID', $data['all']['StudyInstanceUID']);
|
|
|
if(!$statement->execute()) {
|
|
|
return ['result' => 'ERROR', 'reason' => 'internal_error', 'message' => 'Database error', 'data' => $statement->errorInfo()];
|
|
|
}
|
|
|
@@ -689,12 +749,13 @@ namespace Models {
|
|
|
// insert visit
|
|
|
if(count($visits)==0) {
|
|
|
$statement = $this->DataInterface->DatabaseConnection->prepare(
|
|
|
- "INSERT INTO visit(ID, number, visitDate, fk_patient) VALUES(0, :number, :visitDate, :fk_patient)"
|
|
|
+ "INSERT INTO visit(ID, number, visitDate, fk_patient, studyInstanceUID) VALUES(0, :number, :visitDate, :fk_patient, :studyInstanceUID)"
|
|
|
);
|
|
|
$sdate = substr($data['all']['StudyDate'],0,4).'-'.substr($data['all']['StudyDate'],4,2).'-'.substr($data['all']['StudyDate'],6,2);
|
|
|
$statement->bindParam(':number', $data['all']['StudyID']);
|
|
|
$statement->bindParam(':visitDate', $sdate);
|
|
|
$statement->bindParam(':fk_patient', $patientID);
|
|
|
+ $statement->bindParam(':studyInstanceUID', $data['all']['StudyInstanceUID']);
|
|
|
if(!$statement->execute()) {
|
|
|
return ['result' => 'ERROR', 'reason' => 'internal_error', 'message' => 'Database error', 'data' => $statement->errorInfo()];
|
|
|
}
|
|
|
@@ -759,36 +820,78 @@ namespace Models {
|
|
|
$newFiles++;
|
|
|
rename($F, "$F.dicom");
|
|
|
|
|
|
- // convert JPEG
|
|
|
- $cmdLine = "dcmj2pnm $F.dicom $F.jpeg +oj +Jq 100 +F 1 -v 2>&1";
|
|
|
+ // multiframe?
|
|
|
+ $cmdLine = 'dcmdump +P 0028,0008 "'.$F.'.dicom"';
|
|
|
$output=null;
|
|
|
$retval=null;
|
|
|
exec($cmdLine, $output, $retval);
|
|
|
- // error
|
|
|
- if($retval !== 0 || count($output)<1) {
|
|
|
- return [
|
|
|
- 'result' => 'ERROR',
|
|
|
- 'cmdLine' => $cmdLine,
|
|
|
- 'output' => $output,
|
|
|
- 'retval' => $retval
|
|
|
- ];
|
|
|
- }
|
|
|
-
|
|
|
- // image metrics
|
|
|
- $metrics = ['width' => 0, 'height' => 0, 'pxwidth' => 0, 'pxheight' => 0];
|
|
|
- list($metrics['width'], $metrics['height'], $type, $attr) = getimagesize("$F.jpeg");
|
|
|
+ // OK
|
|
|
+ if($retval === 0 && count($output)==1) {
|
|
|
+ $tab = explode(' ',trim($output[0]));
|
|
|
+ $frameCount = intval(str_replace(['[', ']'], '', $tab[2]));
|
|
|
+ // error
|
|
|
+ if($frameCount===0) {
|
|
|
+ return [
|
|
|
+ 'result' => 'ERROR',
|
|
|
+ 'output' => $output,
|
|
|
+ ];
|
|
|
+ }
|
|
|
|
|
|
- // dicom metrics
|
|
|
- $cmdLine = 'dcmdump -s +P 0018,602c +P 0018,602e +P 0028,0008 "'.$F.'.dicom"';
|
|
|
- $output=null;
|
|
|
- $retval=null;
|
|
|
- exec($cmdLine, $output, $retval);
|
|
|
- // error
|
|
|
- if($retval !== 0) {
|
|
|
- if(count($output)==0) {
|
|
|
- // no such calibration, likely not ULTRASOUND!
|
|
|
+ // make JPEG
|
|
|
+ $frames = [];
|
|
|
+ for($i=1; $i<=$frameCount; $i++) {
|
|
|
+ $src = "$F.dicom";
|
|
|
+ $pad = str_pad($i, 3, "0", STR_PAD_LEFT);
|
|
|
+ $dst = str_replace('.dicom', '-'.$pad.'.jpeg', $src);
|
|
|
+ $cmdLine = 'dcmj2pnm "'.$src.'" "'.$dst.'" +oj +Jq 100 +F '.$i.' -v 2>&1';
|
|
|
+
|
|
|
+ $output=null;
|
|
|
+ $retval=null;
|
|
|
+ exec($cmdLine, $output, $retval);
|
|
|
+ // error
|
|
|
+ if($retval !== 0 || count($output)<1) {
|
|
|
+ return [
|
|
|
+ 'result' => 'ERROR',
|
|
|
+ 'cmdLine' => $cmdLine,
|
|
|
+ 'output' => $output,
|
|
|
+ 'retval' => $retval
|
|
|
+ ];
|
|
|
+ }
|
|
|
+
|
|
|
+ $frames[] = $dst;
|
|
|
}
|
|
|
- else {
|
|
|
+
|
|
|
+ // make MP4
|
|
|
+ $src = "$F.dicom";
|
|
|
+ $dst = str_replace('.dicom', '-%03d.jpeg', $src);
|
|
|
+ $mp4 = str_replace('.dicom', '.mp4', $src);
|
|
|
+
|
|
|
+ $cmdLine = 'ffmpeg -f image2 -pattern_type sequence -r 11 -i '.$dst.' -y -c:v libx264 -pix_fmt yuv420p '.$mp4;
|
|
|
+ $output=null;
|
|
|
+ $retval=null;
|
|
|
+ exec($cmdLine, $output, $retval);
|
|
|
+ // error
|
|
|
+ if($retval !== 0) {
|
|
|
+ return [
|
|
|
+ 'result' => 'ERROR',
|
|
|
+ 'cmdLine' => $cmdLine,
|
|
|
+ 'output' => $output,
|
|
|
+ 'retval' => $retval
|
|
|
+ ];
|
|
|
+ }
|
|
|
+
|
|
|
+ // cleanup
|
|
|
+ for($i=0; $i<count($frames); $i++) {
|
|
|
+ unlink($frames[$i]);
|
|
|
+ }
|
|
|
+
|
|
|
+ // get metrics
|
|
|
+ $cmdLine = 'ffprobe -v error -show_entries stream=width,height,r_frame_rate -of csv=p=0 '.$mp4;
|
|
|
+ $output=null;
|
|
|
+ $retval=null;
|
|
|
+ exec($cmdLine, $output, $retval);
|
|
|
+ // error
|
|
|
+ if($retval !== 0 || count($output)!=1) {
|
|
|
return [
|
|
|
'result' => 'ERROR',
|
|
|
'cmdLine' => $cmdLine,
|
|
|
@@ -796,13 +899,75 @@ namespace Models {
|
|
|
'retval' => $retval
|
|
|
];
|
|
|
}
|
|
|
+
|
|
|
+ $tab = explode(',',trim($output[0]));
|
|
|
+ if(count($tab)!=3) {
|
|
|
+ return [
|
|
|
+ 'result' => 'ERROR',
|
|
|
+ 'cmdLine' => $cmdLine,
|
|
|
+ 'output' => $output,
|
|
|
+ 'retval' => $retval
|
|
|
+ ];
|
|
|
+ }
|
|
|
+
|
|
|
+ $metrics['width'] = intval($tab[0]);
|
|
|
+ $metrics['height'] = intval($tab[1]);
|
|
|
+
|
|
|
+ $fps = $tab[2];
|
|
|
+ $tab = explode('/', $fps);
|
|
|
+ if(count($tab) == 2) {
|
|
|
+ $fps = intval($tab[0]);
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ $fps = intval($fps);
|
|
|
+ }
|
|
|
+ $metrics['fps'] = $fps;
|
|
|
+ }
|
|
|
+ // singleframe
|
|
|
+ else {
|
|
|
+ $cmdLine = "dcmj2pnm $F.dicom $F.jpeg +oj +Jq 100 +F 1 -v 2>&1";
|
|
|
+ $output=null;
|
|
|
+ $retval=null;
|
|
|
+ exec($cmdLine, $output, $retval);
|
|
|
+ // error
|
|
|
+ if($retval !== 0 || count($output)<1) {
|
|
|
+ return [
|
|
|
+ 'result' => 'ERROR',
|
|
|
+ 'cmdLine' => $cmdLine,
|
|
|
+ 'output' => $output,
|
|
|
+ 'retval' => $retval
|
|
|
+ ];
|
|
|
+ }
|
|
|
+
|
|
|
+ // image metrics
|
|
|
+ $metrics = ['width' => 0, 'height' => 0, 'pxwidth' => 0, 'pxheight' => 0];
|
|
|
+ list($metrics['width'], $metrics['height'], $type, $attr) = getimagesize("$F.jpeg");
|
|
|
}
|
|
|
- if(count($output)) {
|
|
|
+
|
|
|
+ // dicom metrics
|
|
|
+ $cmdLine = 'dcmdump -s +P 0018,602c +P 0018,602e +P 0028,0008 "'.$F.'.dicom"';
|
|
|
+ $output=null;
|
|
|
+ $retval=null;
|
|
|
+ exec($cmdLine, $output, $retval);
|
|
|
+ // error
|
|
|
+ if($retval !== 0) {
|
|
|
+ return [
|
|
|
+ 'result' => 'ERROR',
|
|
|
+ 'cmdLine' => $cmdLine,
|
|
|
+ 'output' => $output,
|
|
|
+ 'retval' => $retval
|
|
|
+ ];
|
|
|
+ }
|
|
|
+ if(count($output)>=2) {
|
|
|
$tab = explode(' ',trim($output[0]));
|
|
|
$metrics['pxwidth'] = floatval($tab[2])*10.0;
|
|
|
$tab = explode(' ',trim($output[1]));
|
|
|
$metrics['pxheight'] = floatval($tab[2])*10.0;
|
|
|
}
|
|
|
+ if(count($output)==3) {
|
|
|
+ $tab = explode(' ',trim($output[2]));
|
|
|
+ $metrics['frameCount'] = intval(str_replace(['[', ']'], '', $tab[2]));
|
|
|
+ }
|
|
|
|
|
|
// insert new media
|
|
|
$statement = $this->DataInterface->DatabaseConnection->prepare(
|