Skip to content

Instantly share code, notes, and snippets.

@pieper
Created June 27, 2025 00:38
Show Gist options
  • Save pieper/04b72eb1a60192a33c207fb73d9f7170 to your computer and use it in GitHub Desktop.
Save pieper/04b72eb1a60192a33c207fb73d9f7170 to your computer and use it in GitHub Desktop.
IDC-chart in Slicer
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