4Quant / COPD-staging

Package of tools to quantify lung disease (COPD) using any number of popular medical quantifiers (PD15, LAA-x...)
1 stars 0 forks source link

Voxel Volume Discrepancy #79

Closed drtjre closed 8 years ago

drtjre commented 8 years ago

Voxel volume (and subsequently all absolute volumes) for quantities are double those previously calculated.

Investigating which is correct by checking previous calculations using Osirix (3rd calculation).

kmader commented 8 years ago

Thanks, I will check, in the mean time you can run the tests automatically for the sample data by using the RIQAE java project. By running PerformanceTest (https://github.com/4Quant/RIQAE-Java/blob/master/src/test/java/fourquant/PerformanceTests.java) it will create the table, download the images, show the slices and calibration information, export the images to files on the hard drive, run the COPD plugin, and ensure the results meet a minimal criteria (PD15<-500 for example). They are in java and can be easily modified. You can also run them using maven (mvn test) or IntelliJ. I put a version in the RIQAE folder and you can update it using the git pull command.

drtjre commented 8 years ago

I am suspecting that the values from the "ground truth" may actually be those in error. Yes, they are calculated on the individual pixel volume (which corresponds to the ImageInfo in Imagej), but perhaps there is an inter-slice spacing which you are including which I am not.
I am trying to use Osirix to estimate the lung volume as an outside second calculation...

drtjre commented 8 years ago

Thanks for creating all of these tests.

kmader commented 8 years ago

Here are what the results are inside of IntelliJ (https://cdn.rawgit.com/kmader/40dc12969c8d358ad01fa70b8aa0fcf6/raw/d0cf4d1d7ca16b6035e22addfaeb2caf4cfc9f26/Performance_Test_Results.html)

drtjre commented 8 years ago

Thomas test:

drtjre commented 8 years ago
StudyID  LungVol (l)  VoxelVolume (mm^3)
SID10003  9.129  0.826
SID10007  2.841  0.844 
SID10040  9.125  0.689 
SID10113  3.680  0.939 
SID10120  9.086  1.221 
SID10201  4.471  0.976 
SID10003   | LungVol:[18.259],vox volume mm^3:[1.65252685546875]
SID10007   | LungVol:[5.682],vox volume mm^3:[1.6875]
SID10040   | LungVol:[18.25],vox volume mm^3:[1.3779716491699219]
SID10113   | LungVol:[7.359],vox volume mm^3:[1.8771171569824219]
SID10120   | LungVol:[18.172],vox volume mm^3:[2.4426727294921875]
SID10201   | LungVol:[7.37],vox volume mm^3:[1.6093254089355469]

Details:
+------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--+
| patientID  |                                                                                                                                                                                  _c1                                                                                                                                                                                   |
+------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--+
| SID10007   | {"FOV voxels ":[8.2313216E7],"LAA-1024%":[0.1],"LAA-1024mm^3":[4411.125],"LAA-900%":[4.1],"LAA-900mm^3":[233690.0625],"LAA-950%":[1.7],"LAA-950mm^3":[98480.8125],"LungVol (Liters)":[5.682],"LungVol mm^3":[5682457.0],"LungVol voxs":[3367382.0],"PD15":[-858.0],"StudyID":[NaN],"sex":[NaN],"vox volume mm^3":[1.6875]}                                             |
| SID10120   | {"FOV voxels ":[5.6885248E7],"LAA-1024%":[0.0],"LAA-1024mm^3":[2169.0933837890625],"LAA-900%":[64.3],"LAA-900mm^3":[1.169173332875061E7],"LAA-950%":[29.7],"LAA-950mm^3":[5397051.198394775],"LungVol (Liters)":[18.172],"LungVol mm^3":[1.8172195E7],"LungVol voxs":[7439472.0],"PD15":[-971.0],"StudyID":[NaN],"sex":[NaN],"vox volume mm^3":[2.4426727294921875]}   |
| SID10040   | {"FOV voxels ":[6.0030976E7],"LAA-1024%":[0.2],"LAA-1024mm^3":[31333.697330474854],"LAA-900%":[68.7],"LAA-900mm^3":[1.2537567374073029E7],"LAA-950%":[52.8],"LAA-950mm^3":[9633311.609161377],"LungVol (Liters)":[18.25],"LungVol mm^3":[1.824972E7],"LungVol voxs":[1.3243901E7],"PD15":[-994.0],"StudyID":[NaN],"sex":[NaN],"vox volume mm^3":[1.3779716491699219]}  |
| SID10003   | {"FOV voxels ":[6.7633152E7],"LAA-1024%":[0.5],"LAA-1024mm^3":[86410.62927246094],"LAA-900%":[74.8],"LAA-900mm^3":[1.3660089399719238E7],"LAA-950%":[51.4],"LAA-950mm^3":[9377533.003234863],"LungVol (Liters)":[18.259],"LungVol mm^3":[1.8258693E7],"LungVol voxs":[1.1048954E7],"PD15":[-993.0],"StudyID":[NaN],"sex":[NaN],"vox volume mm^3":[1.65252685546875]}   |
| SID10201   | {"FOV voxels ":[4.6923776E7],"LAA-1024%":[0.1],"LAA-1024mm^3":[4544.734954833984],"LAA-900%":[45.3],"LAA-900mm^3":[3337090.7306671143],"LAA-950%":[8.7],"LAA-950mm^3":[643638.4320259094],"LungVol (Liters)":[7.37],"LungVol mm^3":[7369556.0],"LungVol voxs":[4579283.0],"PD15":[-937.0],"StudyID":[NaN],"sex":[NaN],"vox volume mm^3":[1.6093254089355469]}          |
| SID10113   | {"FOV voxels ":[5.7933824E7],"LAA-1024%":[0.0],"LAA-1024mm^3":[779.0036201477051],"LAA-900%":[9.4],"LAA-900mm^3":[694324.988079071],"LAA-950%":[1.1],"LAA-950mm^3":[83137.51888275146],"LungVol (Liters)":[7.359],"LungVol mm^3":[7359262.0],"LungVol voxs":[3920513.0],"PD15":[-886.0],"StudyID":[NaN],"sex":[NaN],"vox volume mm^3":[1.8771171569824219]} 
kmader commented 8 years ago

So RIQAE gets the right result for voxel volume? I know for my data the showcalibration command on the images returned a d=3.0 which matches what you are getting in osirix. Is maybe the act of exporting and importing dicom changing the values? Can you look at the info / calibration information in FIJI directly?

drtjre commented 8 years ago

working on outputing only the calibration info...

drtjre commented 8 years ago

Wrote a quick plugin to dump the calibration pixel info:

...
        ResultsTable rt= Analyzer.getResultsTable();
        _volumeUnits= _calibration.getUnit()+"^3";
        rt.addValue("vox width "+_volumeUnits, _calibration.pixelWidth);
        rt.addValue("vox height "+_volumeUnits, _calibration.pixelHeight);
        rt.addValue("vox depth "+_volumeUnits, _calibration.pixelDepth);
        _voxelVolume= _calibration.pixelWidth*_calibration.pixelHeight*_calibration.pixelDepth;
        rt.addValue("vox volume "+_volumeUnits, _voxelVolume);
...

VoxelVolume Plugin Called from FIJI Directly on Dicom Stack

Data from the CALIBRATION for a single Voxel Output of FIJI directly.

StudyID vox: hight  width  depth  volume
SID10003     0.742  0.742  1.500  0.826
SID10007     0.750  0.750  1.500  0.844
SID10040     0.678  0.678  1.500  0.689
SID10113     0.791  0.791  0.748  0.468
SID10120     0.902  0.902  1.500  1.221
SID10201     0.732  0.732  0.908  0.487

VoxelVolume plugin called from RIQAE

+------------+-------------------------------------------------------------------------------------------------------------------------------------------------+--+
| patientID  |                                                                       voxelVolumeInfo                                                                       |
+------------+-------------------------------------------------------------------------------------------------------------------------------------------------+--+
| SID10003   | {"StudyID":[NaN],"vox depth mm^3":[3.0],"vox height mm^3":[0.7421875],"vox volume mm^3":[1.65252685546875],"vox width mm^3":[0.7421875]}        |
| SID10007   | {"StudyID":[NaN],"vox depth mm^3":[3.0],"vox height mm^3":[0.75],"vox volume mm^3":[1.6875],"vox width mm^3":[0.75]}                            |
| SID10040   | {"StudyID":[NaN],"vox depth mm^3":[3.0],"vox height mm^3":[0.677734375],"vox volume mm^3":[1.3779716491699219],"vox width mm^3":[0.677734375]}  |
| SID10113   | {"StudyID":[NaN],"vox depth mm^3":[3.0],"vox height mm^3":[0.791015625],"vox volume mm^3":[1.8771171569824219],"vox width mm^3":[0.791015625]}  |
| SID10120   | {"StudyID":[NaN],"vox depth mm^3":[3.0],"vox height mm^3":[0.90234375],"vox volume mm^3":[2.4426727294921875],"vox width mm^3":[0.90234375]}    |
| SID10201   | {"StudyID":[NaN],"vox depth mm^3":[3.0],"vox height mm^3":[0.732421875],"vox volume mm^3":[1.6093254089355469],"vox width mm^3":[0.732421875]}  |
+------------+-------------------------------------------------------------------------------------------------------------------------------------------------+--+

Note that after images are fetched with RIQAE, the voxel depth (z) is always 3.0, while different image sets have different depths (mostly 1.5, but also other values). This value may correspond to the "slice thickness" indicated by Osirix, but will not account for possible slice overlap. We are working on scanning a phantom to confirm actual volumes.

drtjre commented 8 years ago

This said, the Average human lung volumes is: Lung capacities in healthy adults[6] Volume Average value (litres)
In men In women Total lung capacity 5.8 4.2

The FIJI direct Lung volumes range 3.7 to 9.1 L.

FIJI Direct
StudyID  LungVol (l)  VoxelVolume (mm^3)
SID10003  9.129  0.826
SID10007  2.841  0.844 
SID10040  9.125  0.689 
SID10113  3.680  0.939 
SID10120  9.086  1.221 
SID10201  4.471  0.976 

The RIQAE lung volumes range is:

SID10003   | LungVol:[18.259],vox volume mm^3:[1.65252685546875]
SID10007   | LungVol:[5.682],vox volume mm^3:[1.6875]
SID10040   | LungVol:[18.25],vox volume mm^3:[1.3779716491699219]
SID10113   | LungVol:[7.359],vox volume mm^3:[1.8771171569824219]
SID10120   | LungVol:[18.172],vox volume mm^3:[2.4426727294921875]
SID10201   | LungVol:[7.37],vox volume mm^3:[1.6093254089355469]

We are suspecting that the RIQAE value is the one at fault, as it is highly unlikely to have a human lung volume above 18L. But our understanding will not be complete until we test a phantom - hopefully later today/tomorrow.

TJ

drtjre commented 8 years ago

Something is not quite consistent. Summary:

drtjre commented 8 years ago

Need Phantom Data. Spoke with Dr Heyer who promised to provide this in "next days".

drtjre commented 8 years ago

PHANTOM STUDY

                                            voxel dims
Reconstruction          LungVol(L) PD15 width   height  depth   vox-vol
1.0 I26f 3 axial        0.087     -1004 0.266   0.266   1.000   0.071   
1.0 I50F 3 LCAD (AA)    0.085     -995  0.266   0.266   2.500   0.176   
5.0 I26f 3              0.087     -1006 0.266   0.266   1.000   0.071   
Ball 87cc Reconstruction Filter  | Results
1.0 I26f 3 axial      | {LungVol (L):[0.087]} {vox depth mm^3":[1.0],"vox height mm^3":[0.265625],"vox volume mm^3":[0.070556640625],"vox width mm^3":[0.265625
1.0 I50F 3 LCAD (AA)  | {LungVol (L):[0.087]} {vox depth mm^3":[1.0],"vox height mm^3":[0.265625],"vox volume mm^3":[0.070556640625],"vox width mm^3":[0.265625
5.0 I26f 3            | {LungVol (L):[0.17]} {vox depth mm^3":[5.0],"vox height mm^3":[0.265625],"vox volume mm^3":[0.352783203125],"vox width mm^3":[0.265625]

Conclusion:

drtjre commented 8 years ago

Output of showcalibration+nslices:

0: jdbc:hive2://127.0.0.1:8000/> select seriesDescription,showcalibration(fetch_dicom_imagej(studyInstanceUID,seriesInstanceUID)) from fantoms where success=true;
+--------------------------------------+-----------------------------------------------------------------------------------------+--+
|          seriesDescription           |                                           calibration                                           |
+--------------------------------------+-----------------------------------------------------------------------------------------+--+
|  1.0 I26f 3 axial      | (w=0.265625, h=0.265625, d=1.0, unit=mm, f=22, nc=null, table=65536, vunit=Gray Value)  |
|  1.0 I50F 3 LCAD (AA)  | (w=0.265625, h=0.265625, d=1.0, unit=mm, f=22, nc=null, table=65536, vunit=Gray Value)  |
|  5.0 I26f 3            | (w=0.265625, h=0.265625, d=5.0, unit=mm, f=22, nc=null, table=65536, vunit=Gray Value)  |
+--------------------------------------+-----------------------------------------------------------------------------------------+--+

+--------------------------------------+----------+--+
|          seriesDescription           | nslices  |
+--------------------------------------+----------+--+
| Phantom_yellow 1.0 I26f 3 axial      | 75       |
| Phantom_yellow 1.0 I50F 3 LCAD (AA)  | 75       |
| Phantom_yellow 5.0 I26f 3            | 30       |
+--------------------------------------+----------+--+
drtjre commented 8 years ago

Kevin evaluating. Discussed possibility to use alternative dicom info for calculating voxel depth - for example dividing total volume by nslices.

drtjre commented 8 years ago

Commands to perform from macTJ2 for repeating phantom calculation:

start osirix!

cd ~/Desktop/tomjre_gmail.com/USBshare/riqae/

java -cp assembly/libs/datanucleus-api-jdo-3.2.6.jar:assembly/libs/datanucleus-core-3.2.10.jar:assembly/libs/datanucleus-rdbms-3.2.9.jar:assembly/target/riqae-assembly-0.1-SNAPSHOT.jar fourquant.riqae.demo -r sampletifs/ -d 1 -x tif --fijiDir /Applications/Fiji.app/

CREATE TEMPORARY TABLE fantom USING fourquant.pacs OPTIONS (bind "YETI", username "OSIRIX", server "localhost", port "11112", path "fantom.csv");

SELECT patientName, patientID,success FROM fantom;

select patientID,studydate,seriesdescription,runmap(fetch_dicom_imagej(studyInstanceUID,seriesInstanceUID),"Measure","") from fantom where success=true;

select patientID,studydate,seriesdescription,runmap(run2(fetch_dicom_imagej(studyInstanceUID,seriesInstanceUID),"Segment Lung Tissue",""),"PD LAA Quantify SegmentedLung","") from fantom where success=true;
drtjre commented 8 years ago

KevinM - modified riqae - now results are inline with Fiji direct -

| patientID  | studydate  |          seriesdescription           |                                                                                                                                                                          _c3                                                                                                                                                                           |
+------------+------------+--------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--+
| PH087      | 20160511   | Phantom_yellow 5.0 I26f 3            | {"FOV voxels ":[7864320.0],"LAA-1024%":[0.2],"LAA-1024mm^3":[183.800048828125],"LAA-900%":[87.4],"LAA-900mm^3":[74321.36657714844],"LAA-950%":[83.7],"LAA-950mm^3":[71200.29357910156],"LungVol (Liters)":[0.085],"LungVol mm^3":[85069.0],"LungVol voxs":[482276.0],"PD15":[-995.0],"StudyID":[NaN],"sex":[NaN],"vox volume mm^3":[0.1763916015625]}  |
| PH087      | 20160511   | Phantom_yellow 1.0 I26f 3 axial      | {"FOV voxels ":[1.96608E7],"LAA-1024%":[1.4],"LAA-1024mm^3":[1219.783203125],"LAA-900%":[94.7],"LAA-900mm^3":[82429.70043945312],"LAA-950%":[92.4],"LAA-950mm^3":[80383.76953125],"LungVol (Liters)":[0.087],"LungVol mm^3":[87016.0],"LungVol voxs":[1233275.0],"PD15":[-1004.0],"StudyID":[NaN],"sex":[NaN],"vox volume mm^3":[0.070556640625]}      |
| PH087      | 20160511   | Phantom_yellow 1.0 I50F 3 LCAD (AA)  | {"FOV voxels ":[1.96608E7],"LAA-1024%":[2.8],"LAA-1024mm^3":[2416.98828125],"LAA-900%":[97.1],"LAA-900mm^3":[84552.39697265625],"LAA-950%":[83.2],"LAA-950mm^3":[72427.23828125],"LungVol (Liters)":[0.087],"LungVol mm^3":[87070.0],"LungVol voxs":[1234042.0],"PD15":[-1006.0],"StudyID":[NaN],"sex":[NaN],"vox volume mm^3":[0.070556640625]}       |
+------------+------------+--------------------------------------+-------------------------------------------------------------------------------------------------------------------

As a note (according to KM): riqae is now modifying the calibration object associated with the ImagePlus object so that the voxel depth=(z_last - z_first)/(slices-1)