Created
June 27, 2025 00:38
-
-
Save pieper/04b72eb1a60192a33c207fb73d9f7170 to your computer and use it in GitHub Desktop.
IDC-chart in Slicer
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import json | |
import random | |
import sys | |
try: | |
import idc_index | |
import pandas | |
except ModuleNotFoundError: | |
import pip | |
pip.main("install idc_index".split()) | |
import idc_index | |
import pandas | |
idc = idc_index.IDCClient() | |
query = """ | |
SELECT DISTINCT | |
PatientAge, | |
PatientSex, | |
BodyPartExamined, | |
Modality, | |
collection_id, | |
StudyInstanceUID, | |
FROM | |
index | |
WHERE | |
collection_id != 'nlst' | |
AND Modality != 'SM' | |
AND Modality != 'SEG' | |
AND Modality != 'SR' | |
""" | |
studies = idc.sql_query(query) | |
def ageMap(value): | |
if not value: | |
return 50 | |
if value.find("Y") != -1: | |
return value.replace("Y", "") | |
if value.find("M") != -1: | |
return 1 | |
if value.find("D") != -1: | |
return 0 | |
try: | |
int(value) | |
return value | |
except ValueError: | |
return 50 | |
def sexMap(value): | |
if value in ["M", "F", "O"]: | |
return value | |
return "U" | |
studies['PatientAge'] = studies['PatientAge'].apply(lambda x: pandas.to_numeric(ageMap(x))) | |
studies['PatientSex'] = studies['PatientSex'].apply(lambda x: sexMap(x)) | |
columnNames = studies.columns.values.tolist() | |
studyList = list(studies.itertuples(index=False, name=None)) | |
print(studyList[:20]) | |
print(len(studyList)) | |
studyList = random.sample(studyList, 1000) | |
valueTypes = [ 'PatientAge' ] | |
parallelAxis = [] | |
for index,columnName in enumerate(columnNames): | |
if columnName.find("UID") == -1: | |
axisRow = {'dim': index, 'name': columnName} | |
axisRow['type'] = 'value' if columnName in valueTypes else 'category' | |
parallelAxis.append(axisRow) | |
seriesData = { | |
'name': 'data', | |
'type': 'parallel', | |
'inactiveOpacity': 0.00, | |
'lineStyle': { 'width': 0.5, 'opacity': 0.5 }, | |
'emphasis': {'lineStyle': { 'width': 3, 'opacity': 0.9 } }, | |
'data': studyList, | |
} | |
pageHTML = """ | |
<body style="height: 100%; margin: 0"> | |
<div id="container" style="height: 100%"></div> | |
<script type="text/javascript" src="https://fastly.jsdelivr.net/npm/echarts@5/dist/echarts.min.js"></script> | |
<script type="text/javascript"> | |
var dom = document.getElementById('container'); | |
var lnqChart = echarts.init(dom, null, { renderer: 'canvas', useDirtyRect: false }); | |
var selectedIDList = []; | |
lnqChart.setOption({ | |
backgroundColor: '#333', | |
/*legend: { bottom: 30, data: %%KEYS%%, itemGap: 20, textStyle: { color: '#fff', fontSize: 14 } },*/ | |
visualMap: {dimension: 4}, | |
tooltip: { padding: 10, backgroundColor: '#222', borderColor: '#777', borderWidth: 1, | |
formatter: (params) => { | |
let data = params.data; | |
return ` | |
<div> | |
${data[0]},${data[1]}: ${data[2]}, ${data[3]}, ${data[4]} | |
</div> | |
`; | |
} | |
}, | |
parallel: { left: '5%', right: '18%', bottom: 100, | |
parallelAxisDefault: { type: 'value', min: 'dataMin', max: 'dataMax', name: 'age', nameLocation: 'end', nameGap: 20, | |
nameTextStyle: { color: '#fff', fontSize: 12 }, | |
axisLine: { lineStyle: { color: '#aaa' } }, | |
axisTick: { lineStyle: { color: '#777' } }, | |
splitLine: { show: false }, axisLabel: { color: '#fff' } | |
} | |
}, | |
parallelAxis: %%AXIS%%, | |
series: %%DATA%%, | |
}); | |
window.addEventListener('resize', lnqChart.resize); | |
lnqChart.on('click', (params) => { | |
console.log(params); | |
if (window.slicerPython && params.event.event.shiftKey) { | |
window.slicerPython.evalPython(`loadLNQCase('${JSON.stringify(params.data)}')`); | |
} | |
}); | |
lnqChart.on('axisareaselected', (params) => { | |
console.log(params); | |
selectedIDList = lnqChart.getModel().getSeries()[0].getData()._idList; | |
}); | |
</script> | |
</body> | |
</html> | |
""" | |
pageHTML = pageHTML.replace("%%AXIS%%", json.dumps(parallelAxis, indent=2)) | |
pageHTML = pageHTML.replace("%%DATA%%", json.dumps(seriesData, indent=2)) | |
lnqChart = slicer.qSlicerWebWidget() | |
lnqChart.size = qt.QSize (1331, 1368) | |
lnqChart.pos = qt.QPoint (1758, 38) | |
lnqChart.setHtml(pageHTML) | |
lnqChart.show() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment