Is there any sort of "batch" segment statistics?

Hello everyone,

I performed semi-automated segmentation of muscles on many CT-scan of patients. The data base is organized this way : patients \ slice \ segmentation. For each patients, there is 2 or 3 slice at different time points (its only one slice for the measurements, not a volume). I would like to compute the mean area + mean density in a first step (and eventually apply a pyradiomics pipeline further on). Here is the structure of the data :

Is there anyway to compute a batch script (or maybe it already exists?) that would create a single table with patients name and corresponding ā€œsegment statistic outputā€ ? I have more >100 and must admit Iā€™m afraid Iā€™ll have to do everything manuallyā€¦

I havenā€™t done this myself, but if you are able to do a little bit of python programming this is certainly doable. Have you gone through the tutorials enough that you are comfortable with doing some scripting? If so we can give you some specific suggestions for this task.

Hello,

Thank you very much for your answer. The problem is I am a complete beginner in programming languageā€¦currently starting with R for PhD purposes but never done python or matlabā€¦

I went through the tutorial but did not find any pre-set option/tools to get the segment statistic output in a table with patientā€™s name (as organized in the DICOM)ā€¦

Is there anyone here who has done something similar and is able to step up with some code?

100 cases is on that borderline where you might just be more efficient to do it by hand, although you will benefit much more in the long term by learning the python scripting.

You might start by looking at the Case Iterator.

Thank you for your quick feedback.

My main issue is that I already performed all segmentations and it seems that Case Iterator would have required me to start with it beforehandā€¦

I already tried manually but this is a nightmare as I have Ā± 100 patients with 1 to 3 studies per patients (hence >200) and when I go to segment statistics, the lists of studies are not sorted by patients name but by slice names, which makes almost impossible to match each slice names with each .DICOM files :
Slicer segment

Help^^

You can find example scripts for processing a single case script repository and module tests). Once you have a code snippet that works for a single file, you can iterate through all the files in a folder.

Dear @Maxnach

Can you try something like the following (iterate through all the segmentation MRML modes in your slicer scene and generate the statisticsā€¦)? here is a code snippet to demonstrate this for mean intensity

for segmentationNode in slicer.util.getNodesByClass('vtkMRMLSegmentationNode'):
    segStatLogic.getParameterNode().SetParameter("Segmentation", segmentationNode.GetID())
    segStatLogic.getParameterNode().SetParameter("ScalarVolumeSegmentStatisticsPlugin.mean.enabled", str(True)) 
    segStatLogic.computeStatistics()
    stats = segStatLogic.getStatistics()
    for segmentId in stats['SegmentIDs']:
        mean = np.array(stats[segmentId,"ScalarVolumeSegmentStatisticsPlugin.mean"])
        print(mean)

Andinet

Dear Andinet,

Many thanks for your suggestion, Iā€™m a proper beginner and maybe I did it wrong, but here is the outcome in the python command prompt :

image

Also, maybe that could help, I read a bit since your mentionned MRML and it seems indeed that every segmentation has its MRML ref, however the labelling (numbers) does not make any sense to me :

image

The magical solution would be some script that measures the segment.stat from the MRML-ref segmentation/scalar volume and could ā€œmatchā€ it with DICOM name/dateā€¦ which I guess is what you did with this code snippetā€¦ but tried everything cannot launch it properlyā€¦ any ideas where I could have go wrong ?

Many thanks in advance, I feel a solution is not far but my 0 background in coding is probably hiding it :confused:

Here is a little bit of a more complete code snippet

import SegmentStatistics
import numpy as np

segStatLogic = SegmentStatistics.SegmentStatisticsLogic()

#Scalar Volume MRML Node List ( You will need this to generate image intensity statistics )
scalarVolumeNode = slicer.util.getNodesByClass('vtkMRMLScalarVolumeNode')

#WARNING: Assuming all segmentations were done on the same master volume, in this case the first one
segStatLogic.getParameterNode().SetParameter("ScalarVolume", scalarVolumeNode[0].GetID())
segStatLogic.getParameterNode().SetParameter("ScalarVolumeSegmentStatisticsPlugin.mean.enabled", str(True))

for segmentationNode in slicer.util.getNodesByClass('vtkMRMLSegmentationNode'):
    print(segmentationNode.GetID())
    segStatLogic.getParameterNode().SetParameter("Segmentation", segmentationNode.GetID())
    segStatLogic.computeStatistics()
    stats = segStatLogic.getStatistics()
    for segmentId in stats['SegmentIDs']:
        mean = np.array(stats[segmentId,"ScalarVolumeSegmentStatisticsPlugin.mean"])
        print(mean)

Andinet

Thank you so much, it seems it loader the segmentation, but there were an error at some point. Of note, each master volume has its own segmentation (actually each master volume = 1 slice of 1 patient at 1 time point)

import SegmentStatistics

import numpy as np

segStatLogic = SegmentStatistics.SegmentStatisticsLogic()

#Scalar Volume MRML Node List ( You will need this to generate image intensity statistics )

scalarVolumeNode = slicer.util.getNodesByClass(ā€˜vtkMRMLScalarVolumeNodeā€™)

#WARNING: Assuming all segmentations were done on the same master volume, in this case the first one

segStatLogic.getParameterNode().SetParameter(ā€œScalarVolumeā€, scalarVolumeNode[0].GetID())

segStatLogic.getParameterNode().SetParameter(ā€œScalarVolumeSegmentStatisticsPlugin.mean.enabledā€, str(True))

for segmentationNode in slicer.util.getNodesByClass(ā€˜vtkMRMLSegmentationNodeā€™):

ā€¦

ā€¦ print(segmentationNode.GetID())

ā€¦

vtkMRMLSegmentationNode10

vtkMRMLSegmentationNode11

vtkMRMLSegmentationNode12

vtkMRMLSegmentationNode13

vtkMRMLSegmentationNode14

vtkMRMLSegmentationNode15

vtkMRMLSegmentationNode16

vtkMRMLSegmentationNode17

vtkMRMLSegmentationNode18

vtkMRMLSegmentationNode19

vtkMRMLSegmentationNode20

vtkMRMLSegmentationNode21

vtkMRMLSegmentationNode22

vtkMRMLSegmentationNode23

vtkMRMLSegmentationNode24

vtkMRMLSegmentationNode25

vtkMRMLSegmentationNode26

vtkMRMLSegmentationNode27

vtkMRMLSegmentationNode28

vtkMRMLSegmentationNode29

vtkMRMLSegmentationNode30

vtkMRMLSegmentationNode31

vtkMRMLSegmentationNode32

vtkMRMLSegmentationNode33

vtkMRMLSegmentationNode34

vtkMRMLSegmentationNode35

vtkMRMLSegmentationNode36

vtkMRMLSegmentationNode37

vtkMRMLSegmentationNode38

vtkMRMLSegmentationNode39

vtkMRMLSegmentationNode40

vtkMRMLSegmentationNode41

vtkMRMLSegmentationNode42

vtkMRMLSegmentationNode43

vtkMRMLSegmentationNode44

vtkMRMLSegmentationNode45

vtkMRMLSegmentationNode46

vtkMRMLSegmentationNode47

vtkMRMLSegmentationNode48

vtkMRMLSegmentationNode49

vtkMRMLSegmentationNode50

vtkMRMLSegmentationNode51

vtkMRMLSegmentationNode52

vtkMRMLSegmentationNode53

vtkMRMLSegmentationNode54

vtkMRMLSegmentationNode55

vtkMRMLSegmentationNode56

vtkMRMLSegmentationNode57

vtkMRMLSegmentationNode58

vtkMRMLSegmentationNode59

vtkMRMLSegmentationNode60

vtkMRMLSegmentationNode61

vtkMRMLSegmentationNode62

vtkMRMLSegmentationNode63

vtkMRMLSegmentationNode64

vtkMRMLSegmentationNode65

vtkMRMLSegmentationNode66

vtkMRMLSegmentationNode67

vtkMRMLSegmentationNode68

vtkMRMLSegmentationNode69

vtkMRMLSegmentationNode70

vtkMRMLSegmentationNode71

vtkMRMLSegmentationNode72

vtkMRMLSegmentationNode73

vtkMRMLSegmentationNode74

vtkMRMLSegmentationNode75

vtkMRMLSegmentationNode76

vtkMRMLSegmentationNode77

vtkMRMLSegmentationNode78

vtkMRMLSegmentationNode79

vtkMRMLSegmentationNode80

vtkMRMLSegmentationNode81

vtkMRMLSegmentationNode82

vtkMRMLSegmentationNode83

vtkMRMLSegmentationNode84

vtkMRMLSegmentationNode85

vtkMRMLSegmentationNode86

vtkMRMLSegmentationNode87

vtkMRMLSegmentationNode88

vtkMRMLSegmentationNode89

vtkMRMLSegmentationNode90

vtkMRMLSegmentationNode91

vtkMRMLSegmentationNode92

vtkMRMLSegmentationNode93

vtkMRMLSegmentationNode94

vtkMRMLSegmentationNode95

vtkMRMLSegmentationNode96

vtkMRMLSegmentationNode97

vtkMRMLSegmentationNode98

vtkMRMLSegmentationNode99

vtkMRMLSegmentationNode100

vtkMRMLSegmentationNode101

vtkMRMLSegmentationNode102

vtkMRMLSegmentationNode103

vtkMRMLSegmentationNode104

vtkMRMLSegmentationNode105

vtkMRMLSegmentationNode106

vtkMRMLSegmentationNode107

vtkMRMLSegmentationNode108

vtkMRMLSegmentationNode109

vtkMRMLSegmentationNode110

vtkMRMLSegmentationNode111

vtkMRMLSegmentationNode112

vtkMRMLSegmentationNode113

vtkMRMLSegmentationNode114

vtkMRMLSegmentationNode115

vtkMRMLSegmentationNode116

vtkMRMLSegmentationNode117

vtkMRMLSegmentationNode118

vtkMRMLSegmentationNode119

vtkMRMLSegmentationNode120

vtkMRMLSegmentationNode121

vtkMRMLSegmentationNode122

vtkMRMLSegmentationNode123

vtkMRMLSegmentationNode124

vtkMRMLSegmentationNode125

vtkMRMLSegmentationNode126

vtkMRMLSegmentationNode127

vtkMRMLSegmentationNode128

vtkMRMLSegmentationNode129

vtkMRMLSegmentationNode130

vtkMRMLSegmentationNode131

vtkMRMLSegmentationNode132

vtkMRMLSegmentationNode133

vtkMRMLSegmentationNode134

vtkMRMLSegmentationNode135

vtkMRMLSegmentationNode136

vtkMRMLSegmentationNode137

vtkMRMLSegmentationNode138

vtkMRMLSegmentationNode139

vtkMRMLSegmentationNode140

vtkMRMLSegmentationNode141

vtkMRMLSegmentationNode142

vtkMRMLSegmentationNode143

vtkMRMLSegmentationNode144

vtkMRMLSegmentationNode145

vtkMRMLSegmentationNode146

vtkMRMLSegmentationNode147

vtkMRMLSegmentationNode148

vtkMRMLSegmentationNode149

vtkMRMLSegmentationNode150

vtkMRMLSegmentationNode151

vtkMRMLSegmentationNode152

vtkMRMLSegmentationNode153

vtkMRMLSegmentationNode154

vtkMRMLSegmentationNode155

vtkMRMLSegmentationNode156

vtkMRMLSegmentationNode157

vtkMRMLSegmentationNode158

vtkMRMLSegmentationNode159

vtkMRMLSegmentationNode160

vtkMRMLSegmentationNode161

vtkMRMLSegmentationNode162

vtkMRMLSegmentationNode163

vtkMRMLSegmentationNode164

vtkMRMLSegmentationNode165

vtkMRMLSegmentationNode166

vtkMRMLSegmentationNode167

vtkMRMLSegmentationNode168

vtkMRMLSegmentationNode169

vtkMRMLSegmentationNode170

vtkMRMLSegmentationNode171

vtkMRMLSegmentationNode172

vtkMRMLSegmentationNode173

vtkMRMLSegmentationNode174

vtkMRMLSegmentationNode175

vtkMRMLSegmentationNode176

vtkMRMLSegmentationNode177

vtkMRMLSegmentationNode178

vtkMRMLSegmentationNode179

vtkMRMLSegmentationNode180

vtkMRMLSegmentationNode181

segStatLogic.getParameterNode().SetParameter(ā€œSegmentationā€, segmentationNode.GetID())

File ā€œā€, line 1

segStatLogic.getParameterNode().SetParameter(ā€œSegmentationā€, segmentationNode.GetID())

^

IndentationError: unexpected indent

segStatLogic.computeStatistics()

File ā€œā€, line 1

segStatLogic.computeStatistics()

^

IndentationError: unexpected indent

stats = segStatLogic.getStatistics()

File ā€œā€, line 1

stats = segStatLogic.getStatistics()

^

IndentationError: unexpected indent

for segmentId in stats[ā€˜SegmentIDsā€™]:

File ā€œā€, line 1

for segmentId in stats[ā€˜SegmentIDsā€™]:

^

IndentationError: unexpected indent

mean = np.array(stats[segmentId,ā€œScalarVolumeSegmentStatisticsPlugin.meanā€])

File ā€œā€, line 1

mean = np.array(stats[segmentId,ā€œScalarVolumeSegmentStatisticsPlugin.meanā€])

^

IndentationError: unexpected indent

print(mean)

Python is very sensitive to indentation.

Indentation error is most likely due to how you copy-paste the code into the console (extra line breaks may interfere with the parser). Copy-pasting the code in smaller chunks or putting the code into a Python scripted module should fix the issue.

Thank you for that input, Iā€™ve been trying for weeks to make it work without success, Iā€™m on the edge to give upā€¦ Basically when I enter the script, here is the output :

vtkMRMLSegmentationNode10

vtkMRMLSegmentationNode11

vtkMRMLSegmentationNode12

-496.58272879464283

vtkMRMLSegmentationNode13

-74.15475789615462

vtkMRMLSegmentationNode14

vtkMRMLSegmentationNode15

vtkMRMLSegmentationNode16

vtkMRMLSegmentationNode17

vtkMRMLSegmentationNode18

vtkMRMLSegmentationNode19

vtkMRMLSegmentationNode20

-1024.0

vtkMRMLSegmentationNode21

vtkMRMLSegmentationNode22

vtkMRMLSegmentationNode23

vtkMRMLSegmentationNode24

vtkMRMLSegmentationNode25

-462.4361410918192

vtkMRMLSegmentationNode26

-256.5129649980126

vtkMRMLSegmentationNode27

-227.99324965434977

vtkMRMLSegmentationNode28

vtkMRMLSegmentationNode29

vtkMRMLSegmentationNode30

vtkMRMLSegmentationNode31

-316.79681233215916

vtkMRMLSegmentationNode32

-137.02753698998654

vtkMRMLSegmentationNode33

vtkMRMLSegmentationNode34

vtkMRMLSegmentationNode35

vtkMRMLSegmentationNode36

-215.98637721279232

vtkMRMLSegmentationNode37

vtkMRMLSegmentationNode38

vtkMRMLSegmentationNode39

vtkMRMLSegmentationNode40

vtkMRMLSegmentationNode41

-254.12470667113644

vtkMRMLSegmentationNode42

vtkMRMLSegmentationNode43

vtkMRMLSegmentationNode44

vtkMRMLSegmentationNode45

30.2841052299937

vtkMRMLSegmentationNode46

vtkMRMLSegmentationNode47

vtkMRMLSegmentationNode48

vtkMRMLSegmentationNode49

vtkMRMLSegmentationNode50

vtkMRMLSegmentationNode51

vtkMRMLSegmentationNode52

vtkMRMLSegmentationNode53

-1024.0

vtkMRMLSegmentationNode54

vtkMRMLSegmentationNode55

vtkMRMLSegmentationNode56

vtkMRMLSegmentationNode57

vtkMRMLSegmentationNode58

-1024.0

vtkMRMLSegmentationNode59

vtkMRMLSegmentationNode60

-1024.0

vtkMRMLSegmentationNode61

vtkMRMLSegmentationNode62

14.96579391891892

vtkMRMLSegmentationNode63

vtkMRMLSegmentationNode64

vtkMRMLSegmentationNode65

vtkMRMLSegmentationNode66

vtkMRMLSegmentationNode67

vtkMRMLSegmentationNode68

vtkMRMLSegmentationNode69

vtkMRMLSegmentationNode70

vtkMRMLSegmentationNode71

vtkMRMLSegmentationNode72

vtkMRMLSegmentationNode73

vtkMRMLSegmentationNode74

vtkMRMLSegmentationNode75

-128.97017045454547

vtkMRMLSegmentationNode76

vtkMRMLSegmentationNode77

vtkMRMLSegmentationNode78

vtkMRMLSegmentationNode79

vtkMRMLSegmentationNode80

vtkMRMLSegmentationNode81

vtkMRMLSegmentationNode82

vtkMRMLSegmentationNode83

vtkMRMLSegmentationNode84

vtkMRMLSegmentationNode85

vtkMRMLSegmentationNode86

vtkMRMLSegmentationNode87

vtkMRMLSegmentationNode88

vtkMRMLSegmentationNode89

vtkMRMLSegmentationNode90

vtkMRMLSegmentationNode91

vtkMRMLSegmentationNode92

vtkMRMLSegmentationNode93

vtkMRMLSegmentationNode94

vtkMRMLSegmentationNode95

vtkMRMLSegmentationNode96

vtkMRMLSegmentationNode97

vtkMRMLSegmentationNode98

vtkMRMLSegmentationNode99

vtkMRMLSegmentationNode100

vtkMRMLSegmentationNode101

vtkMRMLSegmentationNode102

vtkMRMLSegmentationNode103

vtkMRMLSegmentationNode104

vtkMRMLSegmentationNode105

vtkMRMLSegmentationNode106

vtkMRMLSegmentationNode107

vtkMRMLSegmentationNode108

vtkMRMLSegmentationNode109

vtkMRMLSegmentationNode110

vtkMRMLSegmentationNode111

vtkMRMLSegmentationNode112

vtkMRMLSegmentationNode113

vtkMRMLSegmentationNode114

vtkMRMLSegmentationNode115

-1024.0

vtkMRMLSegmentationNode116

vtkMRMLSegmentationNode117

vtkMRMLSegmentationNode118

vtkMRMLSegmentationNode119

vtkMRMLSegmentationNode120

vtkMRMLSegmentationNode121

vtkMRMLSegmentationNode122

vtkMRMLSegmentationNode123

vtkMRMLSegmentationNode124

vtkMRMLSegmentationNode125

vtkMRMLSegmentationNode126

vtkMRMLSegmentationNode127

vtkMRMLSegmentationNode128

vtkMRMLSegmentationNode129

vtkMRMLSegmentationNode130

vtkMRMLSegmentationNode131

vtkMRMLSegmentationNode132

vtkMRMLSegmentationNode133

vtkMRMLSegmentationNode134

vtkMRMLSegmentationNode135

vtkMRMLSegmentationNode136

vtkMRMLSegmentationNode137

vtkMRMLSegmentationNode138

vtkMRMLSegmentationNode139

vtkMRMLSegmentationNode140

-505.8226897069872

vtkMRMLSegmentationNode141

vtkMRMLSegmentationNode142

vtkMRMLSegmentationNode143

vtkMRMLSegmentationNode144

vtkMRMLSegmentationNode145

vtkMRMLSegmentationNode146

vtkMRMLSegmentationNode147

45.87743054397492

vtkMRMLSegmentationNode148

vtkMRMLSegmentationNode149

vtkMRMLSegmentationNode150

vtkMRMLSegmentationNode151

vtkMRMLSegmentationNode152

vtkMRMLSegmentationNode153

vtkMRMLSegmentationNode154

vtkMRMLSegmentationNode155

vtkMRMLSegmentationNode156

vtkMRMLSegmentationNode157

vtkMRMLSegmentationNode158

vtkMRMLSegmentationNode159

vtkMRMLSegmentationNode160

vtkMRMLSegmentationNode161

vtkMRMLSegmentationNode162

vtkMRMLSegmentationNode163

vtkMRMLSegmentationNode164

vtkMRMLSegmentationNode165

vtkMRMLSegmentationNode166

vtkMRMLSegmentationNode167

vtkMRMLSegmentationNode168

vtkMRMLSegmentationNode169

vtkMRMLSegmentationNode170

vtkMRMLSegmentationNode171

vtkMRMLSegmentationNode172

vtkMRMLSegmentationNode173

vtkMRMLSegmentationNode174

-305.12905001376066

vtkMRMLSegmentationNode175

vtkMRMLSegmentationNode176

vtkMRMLSegmentationNode177

vtkMRMLSegmentationNode178

vtkMRMLSegmentationNode179

vtkMRMLSegmentationNode180

vtkMRMLSegmentationNode181

No results anywhere except some random number in between some lines.

I am just getting crazy. I have around 70 patients, each one has 2 to 3 slice (DICOM format), corresponding to different timepoints.

My problems are the following :

  • The DICOM file is named ideally for me (in the directory folder) e.g. ā€œPatientsname-T0ā€ (with either T0, T1 or T2 to denote the timepoint). However, when I performed measurements, patients are well recognized (name ect. from the dicom), but the slice on 3Dslicer is not named like I did : it is name with acquisition parameters (like ā€œAbdomen i_doseā€) which are generic names. Hence, seen the number of patients, slice are names completely randomly (Abdomen i_dose, Abdomen i_dose(1), Abdomen i_dose(2), etc;).

  • The segmentation nodes are also names completely randomly, even though I can manually see which segmentation node is connected with which image :

image
(The name of the patients is on the left of that column)

Therefore, itā€™s a nightmare for me as I donā€™t have any idea of where are the radiomics features corresponding to those segmentation nodes. And even if I did, Iā€™d still have to cross-link manually every segmentation nodes to every patients images (i.e. abdomne i_dose (1) ect.) and finally link those random names to the actual dicom file name.

I have no clue what to doā€¦ would anyone help?

Edit: to make it more complicated, Iā€™m actually trying to apply the pyradiomic pipleline on those imagesā€¦

HI @Maxnach, have you tried using the Slicer GUI to load in a single patient volume and segmentation and use the SegmentStatistics module to generate the statistics you are looking for?

It is helpful to think about the individual case in GUI to help guide the python scripting. Once you have successfully completed what you want for one individual case, then you can begin thinking about how you would do this in a repeated manner.

1 Like