Skip to content

Commit cb67330

Browse files
authored
[Imaging Browser] Fix caveat bug not showing when there are pipeline protocol violations (#8661)
This fixes a bug where the Caveat link was not showing when a file has protocol violations logged automatically by the pipeline in the MRI violation module. It also fixes the link to the MRI violation module with the new react links.
1 parent 226d880 commit cb67330

File tree

4 files changed

+121
-92
lines changed

4 files changed

+121
-92
lines changed

modules/imaging_browser/jsx/ImagePanel.js

Lines changed: 17 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -320,7 +320,7 @@ class ImageQCDropdown extends Component {
320320
} else {
321321
dropdown = (
322322
<div className="col-xs-12">
323-
{this.props.defaultValue}
323+
{this.props.options[this.props.defaultValue]}
324324
</div>
325325
);
326326
}
@@ -491,24 +491,18 @@ class ImagePanelQCCaveatSelector extends Component {
491491
render() {
492492
// Link caveat to MRI Violations if set true
493493
let mriViolationsLink = null;
494-
if (this.props.SeriesUID && this.props.Caveat === '1') {
495-
// If there is a manual caveat that was set, the link
496-
// will take you to it, even though there might also
497-
// be a caveat that was set by the MRI piepline (i.e
498-
// not manual). Note that manual caveat are always
499-
// resolved
500-
if (this.props.CaveatViolationsResolvedID) {
501-
mriViolationsLink = '/mri_violations/resolved_violations/?' +
502-
'SeriesUID=' + this.props.SeriesUID + '&filter=true';
503-
}
494+
if (this.props.FullName && this.props.Caveat === '1') {
495+
mriViolationsLink = '/mri_violations/?' +
496+
'mincFile=' + this.props.FullName +
497+
'&seriesUID=' + this.props.SeriesUID;
504498
}
505499

506500
return (
507501
<ImageQCDropdown
508502
Label="Caveat"
509503
FormName="caveat"
510504
FileID={this.props.FileID}
511-
editable={this.props.HasQCPerm}
505+
editable={this.props.HasQCPerm && this.props.EditableCaveat}
512506
options={
513507
{
514508
'': '',
@@ -527,7 +521,8 @@ ImagePanelQCCaveatSelector.propTypes = {
527521
HasQCPerm: PropTypes.bool,
528522
SeriesUID: PropTypes.string,
529523
Caveat: PropTypes.string,
530-
CaveatViolationsResolvedID: PropTypes.string,
524+
EditableCaveat: PropTypes.bool,
525+
FullName: PropTypes.string,
531526
};
532527

533528

@@ -605,7 +600,8 @@ class ImagePanelQCPanel extends Component {
605600
HasQCPerm={this.props.HasQCPerm}
606601
Caveat={this.props.Caveat}
607602
SeriesUID={this.props.SeriesUID}
608-
CaveatViolationsResolvedID={this.props.CaveatViolationsResolvedID}
603+
EditableCaveat={this.props.EditableCaveat}
604+
FullName={this.props.FullName}
609605
/>
610606
<ImagePanelQCSNRValue
611607
FileID={this.props.FileID}
@@ -624,7 +620,8 @@ ImagePanelQCPanel.propTypes = {
624620
Caveat: PropTypes.string,
625621
SeriesUID: PropTypes.string,
626622
SNR: PropTypes.string,
627-
CaveatViolationsResolvedID: PropTypes.string,
623+
EditableCaveat: PropTypes.bool,
624+
FullName: PropTypes.string,
628625
};
629626

630627

@@ -924,10 +921,11 @@ class ImagePanelBody extends Component {
924921
HasQCPerm={this.props.HasQCPerm}
925922
QCStatus={this.props.QCStatus}
926923
Caveat={this.props.Caveat}
927-
CaveatViolationsResolvedID={this.props.CaveatViolationsResolvedID}
928924
Selected={this.props.Selected}
929925
SNR={this.props.SNR}
930926
SeriesUID={this.props.SeriesUID}
927+
EditableCaveat={this.props.EditableCaveat}
928+
FullName={this.props.Fullname}
931929
/>
932930
</div>
933931
</div>
@@ -971,8 +969,8 @@ ImagePanelBody.propTypes = {
971969
JsonFile: PropTypes.string,
972970
OtherTimepoints: PropTypes.string,
973971
HeadersExpanded: PropTypes.bool,
974-
CaveatViolationsResolvedID: PropTypes.string,
975972
HeaderInfo: PropTypes.object,
973+
EditableCaveat: PropTypes.bool,
976974
};
977975

978976

@@ -1049,7 +1047,7 @@ class ImagePanel extends Component {
10491047
HasQCPerm={this.props.HasQCPerm}
10501048
QCStatus={this.props.QCStatus}
10511049
Caveat={this.props.Caveat}
1052-
CaveatViolationsResolvedID={this.props.CaveatViolationsResolvedID}
1050+
EditableCaveat={this.props.EditableCaveat}
10531051
Selected={this.props.Selected}
10541052
SNR={this.props.SNR}
10551053

@@ -1092,7 +1090,7 @@ ImagePanel.propTypes = {
10921090
HeaderInfo: PropTypes.object,
10931091
HeadersExpanded: PropTypes.string,
10941092
APIFile: PropTypes.string,
1095-
CaveatViolationsResolvedID: PropTypes.string,
1093+
EditableCaveat: PropTypes.bool,
10961094
};
10971095

10981096
let RImagePanel = React.createFactory(ImagePanel);

modules/imaging_browser/php/viewsession.class.inc

Lines changed: 84 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -317,57 +317,63 @@ class ViewSession extends \NDB_Form
317317
(int)$FileObj->getParameter('AcquisitionProtocolID')
318318
);
319319

320-
$caveatViolationsResolvedID
320+
$manualCaveatViolationsResolvedID
321321
= $this->_getManualCaveatViolationsResolvedID($FileID);
322-
$caveat = $caveatViolationsResolvedID ? 1 : 0;
323-
$file = [
324-
'FileID' => $FileID,
325-
'Filename' => $Filename,
326-
'APIFile' => $APIFile,
327-
'FullFilename' => $FullFilename,
328-
'New' => $New,
329-
'OutputType' => $OutputType,
330-
'AcquisitionProtocol' => $AcquisitionProtocol,
331-
'CoordinateSpace' => $CoordinateSpace,
332-
'AcquisitionDate' => $AcquisitionDate,
333-
'ProcDate' => $ProcDate,
334-
'FileInsertDate' => $FileInsertDate,
335-
'SeriesDescription' => $SeriesDescription,
336-
'SeriesNumber' => $SeriesNumber,
337-
'SeriesUID' => $SeriesUID,
338-
'EchoTime' => $EchoTime,
339-
'InversionTime' => $InversionTime,
340-
'RepetitionTime' => $RepetitionTime,
341-
'SliceThickness' => $SliceThickness,
342-
'Time' => $Time,
343-
'ImageType' => $ImageType,
344-
'PhaseEncodingDirection' => $PhaseEncodingDirection,
345-
'EchoNumber' => $EchoNumber,
346-
'Comment' => $Comment,
347-
'ProcessingPipeline' => $ProcessingPipeline,
348-
'TotalRejected' => $TotalRejected,
349-
'SourceFile' => $SourceFile,
350-
'Tool' => $Tool,
351-
'SlicewiseRejected' => $SlicewiseRejected,
352-
'InterlaceRejected' => $InterlaceRejected,
353-
'IntergradientRejected' => $IntergradientRejected,
354-
'Xstep' => $Xstep,
355-
'Ystep' => $Ystep,
356-
'Zstep' => $Zstep,
357-
'Selected' => $Selected,
358-
'QCStatus' => $QCStatus,
359-
'QCDate' => $QCDate,
360-
'Caveat' => $caveat,
361-
'SNR' => $SNR,
362-
'XMLreport' => $XMLreport,
363-
'XMLprotocol' => $XMLprotocol,
364-
'NrrdFile' => $NrrdFile,
365-
'NiiFile' => $NiiFile,
366-
'BvalFile' => $BvalFile,
367-
'BvecFile' => $BvecFile,
368-
'JsonFile' => $JsonFile,
369-
'OtherTimepoints' => $OtherTimepoints,
370-
'CaveatViolationsResolvedID' => $caveatViolationsResolvedID,
322+
$caveat = $manualCaveatViolationsResolvedID ? 1 : 0;
323+
$foundProtocolViolations = $this->_getProtocolViolations($FileID);
324+
$editableCaveat = true;
325+
if ($foundProtocolViolations) {
326+
$caveat = 1;
327+
$editableCaveat = false;
328+
}
329+
$file = [
330+
'FileID' => $FileID,
331+
'Filename' => $Filename,
332+
'APIFile' => $APIFile,
333+
'FullFilename' => $FullFilename,
334+
'New' => $New,
335+
'OutputType' => $OutputType,
336+
'AcquisitionProtocol' => $AcquisitionProtocol,
337+
'CoordinateSpace' => $CoordinateSpace,
338+
'AcquisitionDate' => $AcquisitionDate,
339+
'ProcDate' => $ProcDate,
340+
'FileInsertDate' => $FileInsertDate,
341+
'SeriesDescription' => $SeriesDescription,
342+
'SeriesNumber' => $SeriesNumber,
343+
'SeriesUID' => $SeriesUID,
344+
'EchoTime' => $EchoTime,
345+
'InversionTime' => $InversionTime,
346+
'RepetitionTime' => $RepetitionTime,
347+
'SliceThickness' => $SliceThickness,
348+
'Time' => $Time,
349+
'ImageType' => $ImageType,
350+
'PhaseEncodingDirection' => $PhaseEncodingDirection,
351+
'EchoNumber' => $EchoNumber,
352+
'Comment' => $Comment,
353+
'ProcessingPipeline' => $ProcessingPipeline,
354+
'TotalRejected' => $TotalRejected,
355+
'SourceFile' => $SourceFile,
356+
'Tool' => $Tool,
357+
'SlicewiseRejected' => $SlicewiseRejected,
358+
'InterlaceRejected' => $InterlaceRejected,
359+
'IntergradientRejected' => $IntergradientRejected,
360+
'Xstep' => $Xstep,
361+
'Ystep' => $Ystep,
362+
'Zstep' => $Zstep,
363+
'Selected' => $Selected,
364+
'QCStatus' => $QCStatus,
365+
'QCDate' => $QCDate,
366+
'Caveat' => $caveat,
367+
'SNR' => $SNR,
368+
'XMLreport' => $XMLreport,
369+
'XMLprotocol' => $XMLprotocol,
370+
'NrrdFile' => $NrrdFile,
371+
'NiiFile' => $NiiFile,
372+
'BvalFile' => $BvalFile,
373+
'BvecFile' => $BvecFile,
374+
'JsonFile' => $JsonFile,
375+
'OtherTimepoints' => $OtherTimepoints,
376+
'EditableCaveat' => $editableCaveat,
371377
];
372378

373379
$this->tpl_data['files'][] = $file;
@@ -402,6 +408,29 @@ class ViewSession extends \NDB_Form
402408
return $this->_DB->pselectOneInt($query, ['fileID' => $fileID]);
403409
}
404410

411+
/**
412+
* Gets the ID of the record in table violations_resolved associated
413+
* to the manual caveat set on a given file.
414+
*
415+
* @param $fileID int the ID of the record in table files.
416+
*
417+
* @return ?array array of IDs of the associated records in table
418+
* mri_violations_log or null if there is none.
419+
*/
420+
function _getProtocolViolations(int $fileID): ?array
421+
{
422+
$query = "
423+
SELECT mvl.LogID
424+
FROM files f
425+
JOIN mri_violations_log mvl
426+
ON (mvl.MincFile = f.File)
427+
WHERE f.FileID =:fileID
428+
AND mvl.Header NOT LIKE 'Manual Caveat Set by %';
429+
";
430+
431+
return $this->_DB->pselect($query, ['fileID' => $fileID]);
432+
}
433+
405434
/**
406435
* Gets a rejected parameter according to its type
407436
*
@@ -537,11 +566,11 @@ class ViewSession extends \NDB_Form
537566
['FileID' => $curFileID]
538567
);
539568

540-
$caveatViolationsResolvedID
569+
$manualCaveatViolationsResolvedID
541570
= $this->_getManualCaveatViolationsResolvedID($curFileID);
542571
// If Caveat was set to true and there is not already a manual
543572
// caveat for that scan, then the user wants to create one
544-
if ($curCaveat === '1' && !$caveatViolationsResolvedID) {
573+
if ($curCaveat === '1' && !$manualCaveatViolationsResolvedID) {
545574
//----------------------------------------------------------//
546575
// Insert a record in mri_violations_log to indicate that //
547576
// there is an MRI violation for that scan. The Header //
@@ -622,9 +651,9 @@ class ViewSession extends \NDB_Form
622651
['Caveat' => 1],
623652
['FileID' => $curFileID],
624653
);
625-
} elseif ($curCaveat === '0' && $caveatViolationsResolvedID) {
654+
} elseif ($curCaveat === '0' && $manualCaveatViolationsResolvedID) {
626655
$quotedViolationsResolvedID
627-
= $this->_DB->quote("$caveatViolationsResolvedID");
656+
= $this->_DB->quote("$manualCaveatViolationsResolvedID");
628657
$query = "
629658
DELETE FROM mri_violations_log
630659
WHERE LogID = (
@@ -638,7 +667,7 @@ class ViewSession extends \NDB_Form
638667

639668
$this->_DB->delete(
640669
'violations_resolved',
641-
['ID' => $caveatViolationsResolvedID]
670+
['ID' => $manualCaveatViolationsResolvedID]
642671
);
643672

644673
$quotedFileID = $this->_DB->quote($curFileID);

modules/imaging_browser/templates/form_viewSession.tpl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@
3434
"Selected" : "{if $files[file].Selected}{$files[file].Selected}{/if}",
3535
3636
"Caveat" : "{$files[file].Caveat}",
37-
"CaveatViolationsResolvedID" : "{$files[file].CaveatViolationsResolvedID}",
37+
"EditableCaveat": "{$files[file].EditableCaveat}",
3838
"SNR" : "{if $files[file].SNR}{$files[file].SNR}{/if}",
3939
'HeaderInfo' : {
4040
"SeriesUID" : "{$files[file].SeriesUID}",

modules/imaging_browser/test/TestPlan.md

Lines changed: 19 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -31,37 +31,39 @@
3131
### Main panel: Per Acquisition
3232
16. Files can be downloaded (links clickable) if and only if user has at least one of the module permissions. Ensure that DICOM downloads are
3333
prepended with the Patient Name.
34-
17. Scan-level QC flags (Selected, pass/fail, Caveat emptor) are viewable to all, modifiable if and only if user has permission `imaging_browser_qc`.
35-
18. There will be a Caveat link just above the Caveat drop-down in the image panel of a given scan if and only if there is an MRI violation with:
34+
17. Scan-level QC flags (Selected, pass/fail) are viewable to all, modifiable if and only if user has permission `imaging_browser_qc`.
35+
18. Scan-level Caveat emptor are viewable to all, modifiable if and only if user has permission `imaging_browser_qc` and there are no
36+
pipeline protocol violations associated to the image in the MRI violation module (`Manual Caveat Set by...` protocol violation
37+
with no other protocol violations can be modified). Example in raisinbread: `OTT170_300170_V1` `fieldmapBOLD` images have
38+
pipeline protocol violations associated to the image in the MRI violation module and therefore Caveat should not be editable.
39+
19. There will be a Caveat link just above the Caveat drop-down in the image panel of a given scan if and only if there is an MRI violation with:
3640
i) the same path as the image file
3741
ii) the same SeriesUID as the image's SeriesUID
38-
iii) header set to 'Manual Caveat set by <username>'
39-
iv) resolution type set to 'Inserted with flag'
4042
Search in the MRI violations' Resolved tab using the scan's SeriesUID and image file path to verify this. Note that you can see the header
4143
of an MRI violation by clicking on the 'Protocol Violation' link in the 'Problem' column.
42-
19. In the imaging browser, pick a scan that does not have a Caveat link. Use the drop-down to set the Caveat to true and save your modification.
44+
20. In the imaging browser, pick a scan that does not have a Caveat link. Use the drop-down to set the Caveat to true and save your modification.
4345
Ensure that there is now a link to your newly created caveat and verify that when you click on it it redirects to the MRI violations' violations
4446
resolved submenu with your caveat displayed in the search result table.
45-
20. In the imaging browser, pick a scan that has a Caveat link. Use the drop-down to set the Caveat to false and save your modification.
47+
21. In the imaging browser, pick a scan that has a Caveat link. Use the drop-down to set the Caveat to false and save your modification.
4648
Ensure that there is no Caveat link for that scan now. Using the MRI violation module and the technique described in 17, validate that there
4749
are no MRI violations that would justify the presence of a link for that scan.
48-
21. Selected: can be set back to Null (blank).
49-
22. Clicking on an image launches the BrainBrowser.
50-
23. Clicking on the "QC Comments" button opens the QC comments window.
51-
24. Longitudinal View button launches the BrainBrowser with images of the chosen modality for that specific candidate across visits/timepoints.
50+
22. Selected: can be set back to Null (blank).
51+
23. Clicking on an image launches the BrainBrowser.
52+
24. Clicking on the "QC Comments" button opens the QC comments window.
53+
25. Longitudinal View button launches the BrainBrowser with images of the chosen modality for that specific candidate across visits/timepoints.
5254

5355
### MRI-QC : Scan-level (QC Comments) dialog window
54-
25. With the permission `imaging_browser_qc`, edit comments, checkboxes, and dropdown values.
55-
26. Clicking Save should update the values.
56-
27. Data should not be editable without this permission.
56+
26. With the permission `imaging_browser_qc`, edit comments, checkboxes, and dropdown values.
57+
27. Clicking Save should update the values.
58+
28. Data should not be editable without this permission.
5759

5860
### Visit-level QC feedback dialog window
59-
28. On the view session page, click the button "Visit Level Feedback".
60-
29. The entries in this dialog should be editable when a user has the permission `imaging_browser_qc`.
61-
30. Try editing comments (adding new ones, deleting old ones). Click Save and ensure the data is saved.
61+
29. On the view session page, click the button "Visit Level Feedback".
62+
30. The entries in this dialog should be editable when a user has the permission `imaging_browser_qc`.
63+
31. Try editing comments (adding new ones, deleting old ones). Click Save and ensure the data is saved.
6264

6365
### Test the Candidate Dashboard widget
64-
31. Go to the candidate dashboard in the candidate module and check the Imaging QC Summary widget.
66+
32. Go to the candidate dashboard in the candidate module and check the Imaging QC Summary widget.
6567
- For each visit, check that the QC status displayed matches the Imaging Browser Module by hovering over any visit to see detailed modality breakdown for visit.
6668
- Click on a visit from the graph to access the imaging browser. Check that the link redirects to the correct scans in the imaging browser.
6769
- For a few candidate/visits, check that all the files from the Imaging Browser Module appear in the widget for all the visits.

0 commit comments

Comments
 (0)