From b34fdef58e58b5f1c823772b8e5e12b007f48e35 Mon Sep 17 00:00:00 2001 From: Simon Pelletier Date: Mon, 9 Nov 2020 13:27:07 -0500 Subject: [PATCH] [API] Added features for dicoms : PatientName and images: isPhantom (#6899) Patientname is added to dicoms endpoint view and IsPhantom is added to images endpoint view. --- modules/api/docs/LorisRESTAPI_v0.0.4-dev.md | 3 + .../candidate/visit/dicoms.class.inc | 18 ++- .../electrophysiology/channels.class.inc | 2 +- .../electrophysiology/metadata.class.inc | 2 +- .../electrophysiology/recording.class.inc | 2 +- .../candidate/visit/images.class.inc | 18 ++- .../endpoints/project/recordings.class.inc | 2 +- .../views/visit/dicoms_0_0_4_dev.class.inc | 112 ++++++++++++++++++ .../views/visit/images_0_0_4_dev.class.inc | 72 +++++++++++ raisinbread/test/api/LorisApiDicomsTest.php | 16 +++ raisinbread/test/api/LorisApiImagesTest.php | 5 + 11 files changed, 239 insertions(+), 13 deletions(-) create mode 100644 modules/api/php/views/visit/dicoms_0_0_4_dev.class.inc create mode 100644 modules/api/php/views/visit/images_0_0_4_dev.class.inc diff --git a/modules/api/docs/LorisRESTAPI_v0.0.4-dev.md b/modules/api/docs/LorisRESTAPI_v0.0.4-dev.md index c6064002864..a03be523543 100644 --- a/modules/api/docs/LorisRESTAPI_v0.0.4-dev.md +++ b/modules/api/docs/LorisRESTAPI_v0.0.4-dev.md @@ -553,6 +553,7 @@ the form: "OutputType" : "native", "Filename" : "abc.mnc", "AcquisitionType" : "t1w/t2w/etc", + "IsPhantom" : "true|false", }, /* More files */] } ``` @@ -810,6 +811,7 @@ object of the form: [ { "Tarname" : "DCM_yyyy-mm-dd_ImagingUpload-hh-mm-abc123.tar", + "Patientname" : "DCM123_123456_V1", "SeriesInfo" : [{ "SeriesDescription" : "MPRAGE_ipat2", @@ -834,6 +836,7 @@ object of the form: }, { "Tarname" : "DCM_yyyy-mm-dd_ImagingUpload-hh-mm-def456.tar", + "Patientname" : "DCM456_654321_V1", "SeriesInfo" : [{ "SeriesDescription" : "MPRAGE_ipat2", diff --git a/modules/api/php/endpoints/candidate/visit/dicoms.class.inc b/modules/api/php/endpoints/candidate/visit/dicoms.class.inc index 31b623a0da6..463ac023425 100644 --- a/modules/api/php/endpoints/candidate/visit/dicoms.class.inc +++ b/modules/api/php/endpoints/candidate/visit/dicoms.class.inc @@ -133,11 +133,19 @@ class Dicoms extends Endpoint implements \LORIS\Middleware\ETagCalculator $request->getAttribute('user') ); - $view = (new \LORIS\api\Views\Visit\Dicoms( - $this->_visit, - ...$dicomtars - ))->toArray(); - + $version = $request->getAttribute('LORIS-API-Version'); + switch($version) { + case "v0.0.3": + $view = (new \LORIS\api\Views\Visit\Dicoms( + $this->_visit, + ...$dicomtars + ))->toArray(); + default: + $view = (new \LORIS\api\Views\Visit\Dicoms_0_0_4_Dev( + $this->_visit, + ...$dicomtars + ))->toArray(); + } $this->_cache = new \LORIS\Http\Response\JsonResponse($view); return $this->_cache; diff --git a/modules/api/php/endpoints/candidate/visit/electrophysiology/channels.class.inc b/modules/api/php/endpoints/candidate/visit/electrophysiology/channels.class.inc index a5cb0c1b662..26373d39514 100644 --- a/modules/api/php/endpoints/candidate/visit/electrophysiology/channels.class.inc +++ b/modules/api/php/endpoints/candidate/visit/electrophysiology/channels.class.inc @@ -143,4 +143,4 @@ class Channels extends Endpoint implements \LORIS\Middleware\ETagCalculator { return md5(json_encode($this->_handleGET($request)->getBody())); } -} \ No newline at end of file +} diff --git a/modules/api/php/endpoints/candidate/visit/electrophysiology/metadata.class.inc b/modules/api/php/endpoints/candidate/visit/electrophysiology/metadata.class.inc index e5ed4781146..3055f815b5a 100644 --- a/modules/api/php/endpoints/candidate/visit/electrophysiology/metadata.class.inc +++ b/modules/api/php/endpoints/candidate/visit/electrophysiology/metadata.class.inc @@ -156,4 +156,4 @@ class Metadata extends Endpoint implements \LORIS\Middleware\ETagCalculator { return md5(json_encode($this->_handleGET($request)->getBody())); } -} \ No newline at end of file +} diff --git a/modules/api/php/endpoints/candidate/visit/electrophysiology/recording.class.inc b/modules/api/php/endpoints/candidate/visit/electrophysiology/recording.class.inc index 9019931a810..b45308ebb99 100644 --- a/modules/api/php/endpoints/candidate/visit/electrophysiology/recording.class.inc +++ b/modules/api/php/endpoints/candidate/visit/electrophysiology/recording.class.inc @@ -218,4 +218,4 @@ class Recording extends Endpoint implements \LORIS\Middleware\ETagCalculator return md5(json_encode($signature)); } -} \ No newline at end of file +} diff --git a/modules/api/php/endpoints/candidate/visit/images.class.inc b/modules/api/php/endpoints/candidate/visit/images.class.inc index 01668291f8e..d8c5e03ff84 100644 --- a/modules/api/php/endpoints/candidate/visit/images.class.inc +++ b/modules/api/php/endpoints/candidate/visit/images.class.inc @@ -133,10 +133,20 @@ class Images extends Endpoint implements \LORIS\Middleware\ETagCalculator $request->getAttribute('user') ); - $view = (new \LORIS\api\Views\Visit\Images( - $this->_visit, - ...$images - ))->toArray(); + $version = $request->getAttribute('LORIS-API-Version'); + switch($version) { + case 'v0.0.3': + $view = (new \LORIS\api\Views\Visit\Images( + $this->_visit, + ...$images + ))->toArray(); + + default: + $view = (new \LORIS\api\Views\Visit\Images_0_0_4_Dev( + $this->_visit, + ...$images + ))->toArray(); + } $this->_cache = new \LORIS\Http\Response\JsonResponse($view); diff --git a/modules/api/php/endpoints/project/recordings.class.inc b/modules/api/php/endpoints/project/recordings.class.inc index 5d45a89e4ba..597d87e224b 100644 --- a/modules/api/php/endpoints/project/recordings.class.inc +++ b/modules/api/php/endpoints/project/recordings.class.inc @@ -181,4 +181,4 @@ class Recordings extends Endpoint implements \LORIS\Middleware\ETagCalculator { return md5(json_encode($this->_handleGET($request)->getBody())); } -} \ No newline at end of file +} diff --git a/modules/api/php/views/visit/dicoms_0_0_4_dev.class.inc b/modules/api/php/views/visit/dicoms_0_0_4_dev.class.inc new file mode 100644 index 00000000000..4450c23bb0c --- /dev/null +++ b/modules/api/php/views/visit/dicoms_0_0_4_dev.class.inc @@ -0,0 +1,112 @@ + + * @license http://www.gnu.org/licenses/gpl-3.0.txt GPLv3 + * @link https://www.github.com/aces/Loris/ + */ + +namespace LORIS\api\Views\Visit; + +use \LORIS\Data\Models\DicomTarDTO; +use \LORIS\Data\Models\DicomSeriesDTO; +/** + * Creates a representation of a visit dicoms following the api response + * specifications. + * + * @category ApiViews + * @package Loris + * @author Xavier Lecours Boucher + * @license http://www.gnu.org/licenses/gpl-3.0.txt GPLv3 + * @link https://www.github.com/aces/Loris/ + */ + +class Dicoms_0_0_4_Dev +{ + private $_timepoint; + private $_dicoms; + + /** + * Constructor which sets the instance variables based on the provided timepoint + * + * @param \Timepoint $timepoint The timepoint to represent + * @param DicomTarDTO ...$dicoms An array of dicomtars + */ + public function __construct(\Timepoint $timepoint, DicomTarDTO ...$dicoms) + { + $this->_timepoint = $timepoint; + $this->_dicoms = $dicoms; + } + + /** + * This is a mapper function that formats a dicomtar following the + * API specifications. + * + * @param DicomTarDTO $dicom The dicomtar to format. + * + * @return array + */ + private static function _formatDicomTars(DicomTarDTO $dicom): array + { + return [ + 'Tarname' => $dicom->getTarname(), + 'Patientname' => $dicom->getPatientname(), + 'SeriesInfo' => array_map( + [ + 'self', + '_formatSeries' + ], + $dicom->getSeries() + ), + ]; + } + + /** + * This is a mapper function that formats a dicom series following the + * API specifications. + * + * @param DicomSeriesDTO $series The series to format. + * + * @return array + */ + private static function _formatSeries(DicomSeriesDTO $series): array + { + return [ + 'SeriesDescription' => $series->getSeriesDescription(), + 'SeriesNumber' => $series->getSeriesNumber(), + 'EchoTime' => $series->getEchotime(), + 'RepetitionTime' => $series->getRepetitiontime(), + 'InversionTime' => $series->getInversiontime(), + 'SliceThickness' => $series->getSlicethickness(), + 'Modality' => $series->getModality(), + 'SeriesUID' => $series->getSeriesuid(), + ]; + } + + /** + * Creates an serializable array of this object's data + * + * @return array + */ + public function toArray(): array + { + $meta = [ + 'CandID' => $this->_timepoint->getCandID(), + 'Visit' => $this->_timepoint->getVisitLabel(), + ]; + + $dicomtars = array_map( + 'self::_formatDicomTars', + $this->_dicoms + ); + + return [ + 'Meta' => $meta, + 'DicomTars' => $dicomtars, + ]; + } +} + diff --git a/modules/api/php/views/visit/images_0_0_4_dev.class.inc b/modules/api/php/views/visit/images_0_0_4_dev.class.inc new file mode 100644 index 00000000000..8d29f463834 --- /dev/null +++ b/modules/api/php/views/visit/images_0_0_4_dev.class.inc @@ -0,0 +1,72 @@ + + * @license http://www.gnu.org/licenses/gpl-3.0.txt GPLv3 + * @link https://www.github.com/aces/Loris/ + */ + +namespace LORIS\api\Views\Visit; + +use \LORIS\Data\Models\ImageDTO; +/** + * Creates a representation of a visit images following the api response + * specifications. + * + * @category ApiViews + * @package Loris + * @author Xavier Lecours Boucher + * @license http://www.gnu.org/licenses/gpl-3.0.txt GPLv3 + * @link https://www.github.com/aces/Loris/ + */ + +class Images_0_0_4_Dev +{ + private $_timepoint; + private $_images; + + /** + * Constructor which sets the instance variables based on the provided timepoint + * + * @param \Timepoint $timepoint The timepoint to represent + * @param ImageDTO ...$images An array of images + */ + public function __construct(\Timepoint $timepoint, ImageDTO ...$images) + { + $this->_timepoint = $timepoint; + $this->_images = $images; + } + + /** + * Creates an serializable array of this object's data + * + * @return array + */ + public function toArray(): array + { + $meta = [ + 'CandID' => $this->_timepoint->getCandID(), + 'Visit' => $this->_timepoint->getVisitLabel(), + ]; + + $imagesdata = array_map( + function ($image) { + return [ + 'OutputType' => $image->getOutputType(), + 'Filename' => $image->getFilename(), + 'AcquisitionType' => $image->getAcquisitionprotocol(), + 'IsPhantom' => $image->isPhantom(), + ]; + }, + $this->_images + ); + + return [ + 'Meta' => $meta, + 'Files' => $imagesdata, + ]; + } +} diff --git a/raisinbread/test/api/LorisApiDicomsTest.php b/raisinbread/test/api/LorisApiDicomsTest.php index a45cbcbf45e..bacf8ef0524 100644 --- a/raisinbread/test/api/LorisApiDicomsTest.php +++ b/raisinbread/test/api/LorisApiDicomsTest.php @@ -73,6 +73,18 @@ public function testGetCandidatesCandidVisitDicoms(): void ), 'array' ); + $this->assertSame( + gettype( + $dicomArray['DicomTars']['0']['Tarname'] + ), + 'string' + ); + $this->assertSame( + gettype( + $dicomArray['DicomTars']['0']['Patientname'] + ), + 'string' + ); $this->assertSame( gettype( $dicomArray['DicomTars']['0']['SeriesInfo']['0'] @@ -150,6 +162,10 @@ public function testGetCandidatesCandidVisitDicoms(): void 'Tarname', $dicomArray['DicomTars']['0'] ); + $this->assertArrayHasKey( + 'Patientname', + $dicomArray['DicomTars']['0'] + ); $this->assertArrayHasKey( 'SeriesInfo', diff --git a/raisinbread/test/api/LorisApiImagesTest.php b/raisinbread/test/api/LorisApiImagesTest.php index 7ccf6a0e4a0..d784a9329bc 100644 --- a/raisinbread/test/api/LorisApiImagesTest.php +++ b/raisinbread/test/api/LorisApiImagesTest.php @@ -67,6 +67,10 @@ public function testGetCandidatesCandidVisitImages(): void gettype($imagesArray['Files']['0']['AcquisitionType']), 'string' ); + $this->assertSame( + gettype($imagesArray['Files']['0']['IsPhantom']), + 'boolean' + ); $this->assertArrayHasKey('Meta', $imagesArray); $this->assertArrayHasKey('CandID', $imagesArray['Meta']); @@ -75,6 +79,7 @@ public function testGetCandidatesCandidVisitImages(): void $this->assertArrayHasKey('OutputType', $imagesArray['Files']['0']); $this->assertArrayHasKey('Filename', $imagesArray['Files']['0']); $this->assertArrayHasKey('AcquisitionType', $imagesArray['Files']['0']); + $this->assertArrayHasKey('IsPhantom', $imagesArray['Files']['0']); } /**