def setup_series(inputfile, params, headers_only): """ Shared routine to set runtime parameters and build structure Workflow: 1. Set runtime parameters 2. Check data format 3. Build and populate qcstructure """ # 1. Set runtime parameters # 2. Check data format dcmInfile, pixeldataIn, dicomMode = wadwrapper_lib.prepareInput( inputfile, headers_only=headers_only, logTag=logTag()) # 3. Build and populate qcstructure qclib = QCUS_lib.US_QC(guimode=False) cs = QCUS_lib.USStruct(dcmInfile, pixeldataIn, dicomMode) cs.verbose = False # do not produce detailed logging cs.uni_filter = int(params.find("uni_filter").text) cs.uni_delta = float(params.find("uni_delta").text) cs.uni_low = float(params.find("uni_low").text) cs.sen_filter = int(params.find("sen_filter").text) cs.sen_delta = float(params.find("sen_delta").text) cs.ver_offset = int(params.find("ver_offset").text) cs.hor_offset = int(params.find("hor_offset").text) cs.fitcircle_frac = float(params.find("fitcircle_frac").text) cs.cluster_fminsize = float(params.find("cluster_fminsize").text) try: cs.verbose = params.find('verbose').text.lower() in [ '1', 'true', 'y', 'yes' ] except: pass return qclib, cs
def cdmamsetup_series(inputfile, params, headers_only): """ Shared routine to set runtime parameters and build structure Workflow: 1. Set runtime parameters 2. Check data format 3. Build and populate qcstructure """ # 1. Set runtime parameters if not headers_only: # then we can skip the parameter check try: phantomversion = params.find("phantomversion").text except AttributeError: raise ValueError(logTag() + " missing phantomversion parameter!") try: modeCDCOM = (params.find("modeCDCOM").text == 'True') except AttributeError: raise ValueError(logTag() + " missing cdcommode parameter!") else: phantomversion = '3.2' # dummy for headers modeCDCOM = False # 2. Check data format dcmInfile, pixeldataIn, dicomMode = wadwrapper_lib.prepareInput( inputfile, headers_only=headers_only, logTag=logTag()) # 3. Build and populate qcstructure qclib = CDMam_lib.CDMam() cs = CDMam_lib.CDMamStruct(dcmInfile, pixeldataIn, phantomversion) cs.imnum = 0 # needs to be set to an increasing number if multiple files are used cs.verbose = False # do not produce detailed logging cs.imageFileName = inputfile[0] # only for CDCOM.exe qclib.determineScannerID(cs) return qclib, cs, modeCDCOM
def cdmamsetup_series(inputfile,params,headers_only): """ Shared routine to set runtime parameters and build structure Workflow: 1. Set runtime parameters 2. Check data format 3. Build and populate qcstructure """ # 1. Set runtime parameters if not headers_only: # then we can skip the parameter check try: phantomversion = params.find("phantomversion").text except AttributeError: raise ValueError(logTag()+" missing phantomversion parameter!") try: modeCDCOM = (params.find("modeCDCOM").text == 'True') except AttributeError: raise ValueError(logTag()+" missing cdcommode parameter!") else: phantomversion = '3.2' # dummy for headers modeCDCOM = False # 2. Check data format dcmInfile,pixeldataIn,dicomMode = wadwrapper_lib.prepareInput(inputfile,headers_only=headers_only,logTag=logTag()) # 3. Build and populate qcstructure qclib = CDMam_lib.CDMam() cs = CDMam_lib.CDMamStruct(dcmInfile,pixeldataIn,phantomversion) cs.imnum = 0 # needs to be set to an increasing number if multiple files are used cs.verbose = False # do not produce detailed logging cs.imageFileName = inputfile[0] # only for CDCOM.exe qclib.determineScannerID(cs) return qclib,cs,modeCDCOM
def setup_series(inputfile, params, headers_only): """ Shared routine to set runtime parameters and build structure Workflow: 1. Set runtime parameters 2. Check data format 3. Build and populate qcstructure """ # 1. Set runtime parameters """ if not headers_only: # then we can skip the parameter check try: phantomversion = params.find("phantomversion").text except AttributeError: raise ValueError(logTag()+" missing phantomversion parameter!") try: modeCDCOM = (params.find("modeCDCOM").text == 'True') except AttributeError: raise ValueError(logTag()+" missing cdcommode parameter!") else: phantomversion = '3.2' # dummy for headers modeCDCOM = False """ # 2. Check data format dcmInfile, pixeldataIn, dicomMode = wadwrapper_lib.prepareInput( inputfile, headers_only=headers_only, logTag=logTag()) # 3. Build and populate qcstructure qclib = QCUS_lib.US_QC(guimode=False) cs = QCUS_lib.USStruct(dcmInfile, pixeldataIn, dicomMode) cs.verbose = False # do not produce detailed logging return qclib, cs
def setup_series(inputfile,params,headers_only): """ Shared routine to set runtime parameters and build structure Workflow: 1. Set runtime parameters 2. Check data format 3. Build and populate qcstructure """ # 1. Set runtime parameters """ if not headers_only: # then we can skip the parameter check try: phantomversion = params.find("phantomversion").text except AttributeError: raise ValueError(logTag()+" missing phantomversion parameter!") try: modeCDCOM = (params.find("modeCDCOM").text == 'True') except AttributeError: raise ValueError(logTag()+" missing cdcommode parameter!") else: phantomversion = '3.2' # dummy for headers modeCDCOM = False """ # 2. Check data format dcmInfile,pixeldataIn,dicomMode = wadwrapper_lib.prepareInput(inputfile,headers_only=headers_only,logTag=logTag()) # 3. Build and populate qcstructure qclib = QCUS_lib.US_QC(guimode=False) cs = QCUS_lib.USStruct(dcmInfile,pixeldataIn,dicomMode) cs.verbose = False # do not produce detailed logging return qclib,cs
def xrayqc_series(data, results, params): """ QCXRay_UMCU checks: Horizontal uniformity XRayEdges LowContrast DynamicRange MTF Workflow: 2. Check data format 3. Build and populate qcstructure 4. Run tests 5. Build xml output 6. Build artefact picture thumbnail """ inputfile = data.series_filelist[0] # give me a filename ## 2. Check data format dcmInfile, pixeldataIn, dicomMode = wadwrapper_lib.prepareInput( inputfile, headers_only=False, logTag=logTag()) ## 3. Build and populate qcstructure remark = "" qclib = QCXRay_lib.XRayQC() room = _getRoomDefinition(params) cs = QCXRay_lib.XRayStruct(dcmInfile, pixeldataIn, room) cs.verbose = False # do not produce detailed logging ## 4. Run tests error, msg = qclib.QC(cs) ## 5. Build xml output ## Struct now contains all the results and we can write these to the WAD IQ database stand = qclib.TableOrWall(cs) idname = '_' + stand labvals = qclib.ReportEntries(cs) tmpdict = {} for elem in labvals: #labvals.append( {'name':'label','value':0, 'quantity':'columnname','level':'1:default, 2: detail','pos':missing or a number} ) # if no pos given, the next one will be given # if no quantity given, 'name' will be used # if no level given, the default will be used quan = elem['quantity'] if 'quantity' in elem else str(elem['name']) level = elem['level'] if 'level' in elem else None rank = elem['rank'] if 'rank' in elem else None results.addFloat(elem['name'] + str(idname), elem['value'], quantity=quan, level=level, rank=rank) ## 6. Build artefact picture thumbnail filename = 'test' + idname + '.jpg' # Use jpg if a thumbnail is desired qclib.saveAnnotatedImage(cs, filename) results.addObject('AnnotatedImage' + idname, filename)
def xrayqc_uniformity_series(data, results, params): """ n13_uniformity checks: Uniformity Artefacts Workflow: 2. Check data format 3. Build and populate qcstructure 4. Run tests 5. Build xml output 6. Build artefact picture thumbnail """ inputfile = data.series_filelist[0] # give me a filename ## 2. Check data format dcmInfile,pixeldataIn,dicomMode = wadwrapper_lib.prepareInput(inputfile,headers_only=False,logTag=logTag()) ## 3. Build and populate qcstructure remark = "" qclib = n13_lib.XRayQC() room = _getRoomDefinition(params) cs = n13_lib.XRayStruct(dcmInfile,pixeldataIn,room) cs.verbose = False # do not produce detailed logging ## 4. Run tests error,msg = qclib.QCUnif(cs) ## 5. Build xml output ## Struct now contains all the results and we can write these to the WAD IQ database if not cs.DetectorSuffix() is None: idname = '_'+cs.DetectorSuffix() else: idname = '' ## First Build artefact picture thumbnail label = 'unif' filename = '%s%s.jpg'%(label,idname) # Use jpg if a thumbnail is desired qclib.saveAnnotatedImage(cs,filename, 'artefacts') results.addObject('%s%s'%(label,idname),filename) labvals = qclib.ReportEntries(cs) tmpdict={} for elem in labvals: #labvals.append( {'name':'label','value':0, 'quantity':'columnname','level':'1:default, 2: detail','pos':missing or a number} ) # if no pos given, the next one will be given # if no quantity given, 'name' will be used # if no level given, the default will be used quan = elem['quantity'] if 'quantity' in elem else str(elem['name']) level = elem['level'] if 'level' in elem else None rank = elem['rank'] if 'rank' in elem else None results.addFloat(elem['name']+str(idname), elem['value'], quantity=quan, level=level,rank=rank)
def xrayqc_series(data, results, params): """ QCXRay_UMCU checks: Horizontal uniformity XRayEdges LowContrast DynamicRange MTF Workflow: 2. Check data format 3. Build and populate qcstructure 4. Run tests 5. Build xml output 6. Build artefact picture thumbnail """ inputfile = data.series_filelist[0] # give me a filename ## 2. Check data format dcmInfile, pixeldataIn, dicomMode = wadwrapper_lib.prepareInput( inputfile, headers_only=False, logTag=logTag()) ## 3. Build and populate qcstructure remark = "" qclib = QCXRay_lib.XRayQC() room = _getRoomDefinition(params) cs = QCXRay_lib.XRayStruct(dcmInfile, pixeldataIn, room) cs.verbose = False # do not produce detailed logging ## 4. Run tests error, msg = qclib.QC(cs) ## 5. Build xml output ## Struct now contains all the results and we can write these to the WAD IQ database stand = qclib.TableOrWall(cs) idname = '_' + stand labvals = qclib.ReportEntries(cs) tmpdict = {} for key, val in labvals: results.addFloat(key + str(idname), val, quantity=str(key)) ## 6. Build artefact picture thumbnail filename = 'test' + idname + '.jpg' # Use jpg if a thumbnail is desired qclib.saveAnnotatedImage(cs, filename) results.addObject('AnnotatedImage' + idname, filename)
def xrayqc_series(data, results, params): """ QCXRay_UMCU checks: Horizontal uniformity XRayEdges LowContrast DynamicRange MTF Workflow: 2. Check data format 3. Build and populate qcstructure 4. Run tests 5. Build xml output 6. Build artefact picture thumbnail """ inputfile = data.series_filelist[0] # give me a filename ## 2. Check data format dcmInfile,pixeldataIn,dicomMode = wadwrapper_lib.prepareInput(inputfile,headers_only=False,logTag=logTag()) ## 3. Build and populate qcstructure remark = "" qclib = QCXRay_lib.XRayQC() room = _getRoomDefinition(params) cs = QCXRay_lib.XRayStruct(dcmInfile,pixeldataIn,room) cs.verbose = False # do not produce detailed logging ## 4. Run tests error,msg = qclib.QC(cs) ## 5. Build xml output ## Struct now contains all the results and we can write these to the WAD IQ database stand = qclib.TableOrWall(cs) idname = '_'+stand labvals = qclib.ReportEntries(cs) tmpdict={} for key,val in labvals: results.addFloat(key+str(idname), val, quantity=str(key)) ## 6. Build artefact picture thumbnail filename = 'test'+idname+'.jpg' # Use jpg if a thumbnail is desired qclib.saveAnnotatedImage(cs,filename) results.addObject('AnnotatedImage'+idname,filename)
def ctheader_series(data, results, params): """ Read selected dicomfields and write to IQC database Workflow: 1. Run tests 2. Build xml output """ info = 'dicom' dcmInfile, pixeldataIn, dicomMode = wadwrapper_lib.prepareInput( data.series_filelist[0], headers_only=True, logTag=logTag()) qcctlib = QCCT_lib.CT_QC() cs = QCCT_lib.CTStruct(dcmInfile=dcmInfile, pixeldataIn=pixeldataIn, dicomMode=dicomMode) cs.verbose = False error = qcctlib.HeadOrBody(cs) if (error == True or cs.anatomy == lit.stUnknown): raise ValueError("{} ERROR! Cannot determine Anatomy".format(logTag)) result_dict = {} idname = "" if cs.anatomy == lit.stHead: idname = "_H" else: idname = "_B" # only uncomment if same config used for all scanners: idname += "_"+cs.guessScanner.name ## 1. Run tests dicominfo = qcctlib.DICOMInfo(cs, info) ## 2. Add results to 'result' object # plugionversion is newly added in for this plugin since pywad2 results.addChar('pluginversion' + idname, str( qcctlib.qcversion)) # do not specify level, use default from config results.addChar('Anatomy', str( cs.anatomy)) # do not specify level, use default from config for di in dicominfo: results.addChar(di[0] + idname, str(di[1])[:min(len(str(di[1])), 128)] ) # do not specify level, use default from config
def header_series(data, results, **kwargs): """ Read selected dicomfields and write to IQC database Workflow: 1. Read only headers 2. Run tests 3. Build xml output """ info = 'qc' ## 1. read only headers dcmInfile, pixeldataIn, dicomMode = wadwrapper_lib.prepareInput( data.series_filelist[0], headers_only=True, logTag=logTag()) ## 2. Run tests qclib = QCDDL_lib.DDLQC() ## Table or Wall? from distances and sensitivity; for well defined protocols to be defined in DESCRIPTION field cs = QCDDL_lib.DDLStruct(dcmInfile, None, dicomMode) cs.verbose = False # do not produce detailed logging dicominfo = qclib.DICOMInfo(cs, info) idname = '_' + qclib.HorizontalOrVertical(cs) ## 3. Build xml output floatlist = [] results.addChar('pluginversion' + idname, str( qclib.qcversion)) # do not specify level, use default from config for di in dicominfo: if di[0] in floatlist: results.addFloat( di[0] + idname, di[1]) # do not specify level, use default from config else: results.addChar(di[0] + idname, str(di[1])[:min(len(str(di[1])), 128)] ) # do not specify level, use default from config results.addChar( 'room' + idname, cs.guessroom.name) # do not specify level, use default from config results.addChar('stand' + idname, qclib.HorizontalOrVertical( cs)) # do not specify level, use default from config
def qc_series(data, results, **kwargs): """ QCDDL_UMCU checks: Horizontal uniformity LowContrast DynamicRange Workflow: 2. Check data format 3. Build and populate qcstructure 4. Run tests 5. Build xml output 6. Build artefact picture thumbnail """ ## 2. Check data format dcmInfile, pixeldataIn, dicomMode = wadwrapper_lib.prepareInput( data.series_filelist[0], headers_only=False, logTag=logTag()) ## 3. Build and populate qcstructure remark = "" qclib = QCDDL_lib.DDLQC() cs = QCDDL_lib.DDLStruct(dcmInfile, pixeldataIn, dicomMode) cs.verbose = False # do not produce detailed logging ## 4. Run tests error, msg = qclib.QC(cs) ## 5. Build xml output ## Struct now contains all the results and we can write these to the WAD IQ database stand = qclib.HorizontalOrVertical(cs) idname = '_' + stand labvals = qclib.ReportEntries(cs) tmpdict = {} for key, val in labvals: results.addFloat(key + str(idname), val, quantity=str(key)) ## 6. Build artefact picture thumbnail filename = 'test' + idname + '.jpg' # Use jpg if a thumbnail is desired qclib.saveAnnotatedImage(cs, filename) results.addObject('AnnotatedImage' + idname, filename)
def ctheader_series(data,results,params): """ Read selected dicomfields and write to IQC database Workflow: 1. Run tests 2. Build xml output """ info = 'dicom' dcmInfile,pixeldataIn,dicomMode = wadwrapper_lib.prepareInput(data.series_filelist[0],headers_only=True,logTag=logTag()) qcctlib = QCCT_lib.CT_QC() cs = QCCT_lib.CTStruct(dcmInfile=dcmInfile,pixeldataIn=pixeldataIn,dicomMode=dicomMode) cs.verbose = False error = qcctlib.HeadOrBody(cs) if(error == True or cs.anatomy == lit.stUnknown): raise ValueError("{} ERROR! Cannot determine Anatomy".format(logTag)) result_dict = {} idname = "" if cs.anatomy == lit.stHead: idname = "_H" else: idname = "_B" # only uncomment if same config used for all scanners: idname += "_"+cs.guessScanner.name ## 1. Run tests dicominfo = qcctlib.DICOMInfo(cs,info) ## 2. Add results to 'result' object # plugionversion is newly added in for this plugin since pywad2 results.addChar('pluginversion'+idname, str(qcctlib.qcversion)) # do not specify level, use default from config results.addChar('Anatomy', str(cs.anatomy)) # do not specify level, use default from config for di in dicominfo: results.addChar(di[0]+idname, str(di[1])[:min(len(str(di[1])),128)]) # do not specify level, use default from config
def mammoqc_series(data, results, **kwargs): """ QCMammo_UMCU checks: Uniformity (5 rois) and SNR (hologic), DoseRatio (empirical/calculated from DICOM) Artefacts (spots, dead pixels) Workflow: 2. Check data format 3. Build and populate qcstructure 4. Run tests 5. Build xml output 6. Build artefact picture thumbnail """ inputfile = data.series_filelist[0] # give me a filename ## 2. Check data format dcmInfile, pixeldataIn, dicomMode = wadwrapper_lib.prepareInput(inputfile, headers_only=False, logTag=logTag()) ### try: ### dcmInfile = dicom.read_file(inputfile) ### pixeldataIn = dcmInfile.pixel_array.transpose() # MODULE EXPECTS PYQTGRAPH DATA: X AND Y ARE TRANSPOSED! ### except: ### print logTag()+"could not open dicomfile!" ### sys.exit() ## 3. Build and populate qcstructure remark = "" qcmammolib = QCMammo_lib.Mammo_QC() cs_mam = QCMammo_lib.MammoStruct(dcmInfile, pixeldataIn) cs_mam.verbose = False # do not produce detailed logging if qcmammolib.NeedsCropping(cs_mam): cs_mam.expertmode = True qcmammolib.RestrictROI(cs_mam) remark = "CROPPED" ## 4. Run tests # Uniformity check error = qcmammolib.Uniformity(cs_mam) if error: remark += "/ERROR_UNIFORMITY" # Contrast L50 error = qcmammolib.L50Contrast(cs_mam) # doesn't do anything if not L50 if error: remark += "/ERROR_L50CONTRAST" # Dose Ratio error = qcmammolib.DoseRatio(cs_mam) if error: remark += "/ERROR_DOSERATIO" # Artefacts error = qcmammolib.Artefacts(cs_mam) if error: remark += "/ERROR_ARTEFACTS" ## 5. Build xml output ## Struct now contains all the results and we can write these to the ## WAD IQ database includedlist = ["unif_pct", "snr_hol", "doseratio", "art_clusters", "expert_inoutoverin", "contrast_snr"] excludedlist = [ "verbose", "dcmInfile", "pixeldataIn", "hasmadeplots", "means", "stdevs", "unif", "snr_hol", "unif_rois", "doseratio", "art_clusters", "art_image", "art_borderpx", "art_threshold", "art_rois", "expertmode", "expert_roipts", "expert_frac", "expert_inoutoverin", "filtername", "scannername", "contrast_rois", "contrast_mean", "contrast_sd", ] idname = "_" + cs_mam.filtername if "SUMPRES" in idname: idname = "" # only one image results.addChar("NOTE" + idname, remark) for elem in cs_mam.__dict__: if elem in includedlist: newkeys = [] newvals = [] try: elemval = cs_mam.__dict__[elem] if "contrast_snr" in elem: # array for ix, snr in enumerate(elemval): newkeys.append("CNR" + str(ix)) newvals.append(snr) elif "art_clusters" in elem: newkeys.append(str(elem)) newvals.append(len(elemval)) else: newkeys.append(str(elem)) newvals.append(elemval) except: print logTag() + "error for", elem tmpdict = {} for key, val in zip(newkeys, newvals): results.addFloat(key + str(idname), val, quantity=str(key)) ## 6. Build artefact picture thumbnail filename = "test" + idname + ".jpg" # Use jpg if a thumbnail is desired # object_naam_pad = outputfile.replace('result.xml','test'+idname+'.jpg') # Use jpg if a thumbnail is desired qcmammolib.saveAnnotatedArtefactImage(cs_mam, filename) results.addObject("ArtefactImage" + idname, filename)
def ctqc_series(data,results,params): """ QCCT_UMCU Checks: extension of Philips QuickIQ (also for older scanners without that option), for both Head and Body if provided Uniformity HU values Noise Linearity Workflow: 1. Read image or sequence 2. Run test 3. Build xml output """ dcmInfile,pixeldataIn,dicomMode = wadwrapper_lib.prepareInput(data.series_filelist[0],headers_only=False,logTag=logTag()) qclib = QCCT_lib.CT_QC() cs = QCCT_lib.CTStruct(dcmInfile=dcmInfile,pixeldataIn=pixeldataIn,dicomMode=dicomMode) cs.forceScanner = _getScannerDefinition(params) cs.verbose = False ## id scanner error = qclib.DetermineCTID(cs) if(error == True or cs.guessScanner.name == lit.stUnknown): raise ValueError("{} ERROR! Cannot determine CT ID".format(logTag)) error = qclib.HeadOrBody(cs) if(error == True or cs.anatomy == lit.stUnknown): raise ValueError("{} ERROR! Cannot determine Anatomy".format(logTag)) idname = "" if cs.anatomy == lit.stHead: idname = "_H" else: idname = "_B" # only uncomment if same config used for all scanners: idname += cs.guessScanner.name ## 2. Run tests error = qclib.AnalyseCT(cs) if error: raise ValueError("{} ERROR! Error in AnalyseCT".format(logTag)) ## Struct now contains all the results and we can write these to the ## WAD IQ database includedlist = [ 'roiavg', 'roisd', 'snr_hol', 'unif', 'linearity', 'maxdev', 'shiftxypx', ] excludedlist = [ 'verbose', 'dcmInfile', 'pixeldataIn', 'dicomMode', 'hasmadeplots', 'guessScanner', 'anatomy', 'roiavg', 'roisd', 'snr_hol', 'unif', 'linearity', 'maxdev', 'shiftxypx', 'valid' 'skull_avg', 'unif_slice', 'unif_rois' ] for elem in cs.__dict__: if elem in includedlist: newkeys = [] newvals = [] try: elemval = cs.__dict__[elem] if 'roiavg' in elem: # array of avgs newkeys.append('MeanCenter') newvals.append(elemval[0]) newkeys.append('MeanAir') newvals.append(elemval[3]) elif 'shiftxypx' in elem: newkeys.append('shiftxpx') newvals.append(elemval[0]) newkeys.append('shiftypx') newvals.append(elemval[1]) else: newkeys.append(str(elem)) newvals.append(elemval) except: print logTag()+"error for",elem elemval = -1. for key,val in zip(newkeys,newvals): results.addFloat(key+str(idname), val, quantity=str(key)) ## Build thumbnail filename = 'test'+idname+'.jpg' # Use jpg if a thumbnail is desired if cs.dicomMode == wadwrapper_lib.stMode2D: scipy.misc.imsave(filename,cs.pixeldataIn.transpose()) # MODULE EXPECTS PYQTGRAPH DATA: X AND Y ARE TRANSPOSED! else: scipy.misc.imsave(filename,(cs.pixeldataIn[cs.unif_slice]).transpose()) # MODULE EXPECTS PYQTGRAPH DATA: X AND Y ARE TRANSPOSED! results.addObject('CTslice'+idname,filename)
def ocr_series(data, results, params): """ Use pyOCR which for OCR returns rect rois for plotting in overview """ inputfile = data.series_filelist[0] # give me a [filename] dcmInfile, pixeldataIn, dicomMode = wadwrapper_lib.prepareInput( inputfile, headers_only=False, logTag=logTag()) rectrois = [] error = False msg = '' # solve ocr params regions = {} for param in params: #'OCR_TissueIndex.xywh' = 'x;y;w;h' #'OCR_TissueIndex.prefix' = 'prefix' #'OCR_TissueIndex.suffix' = 'suffix' if param.tag.startswith('OCR_'): split = param.tag.find('.') # ':' is illegal in xml names name = param.tag[:split] stuff = param.tag[split + 1:] if not name in regions: regions[name] = {'prefix': '', 'suffix': ''} if stuff == 'xywh': regions[name]['xywh'] = [int(p) for p in param.text.split(';')] elif stuff == 'prefix': regions[name]['prefix'] = param.text elif stuff == 'suffix': regions[name]['suffix'] = param.text elif stuff == 'type': regions[name]['type'] = param.text for name, region in regions.items(): rectrois.append([(region['xywh'][0], region['xywh'][1]), (region['xywh'][0] + region['xywh'][2], region['xywh'][1] + region['xywh'][3])]) txt, part = ocr_lib.OCR(pixeldataIn, region['xywh']) if region['type'] == 'object': import scipy im = scipy.misc.toimage(part) fn = '%s.jpg' % name im.save(fn) results.addObject(name, fn) else: try: value = ocr_lib.txt2type(txt, region['type'], region['prefix'], region['suffix']) if region['type'] == 'float': results.addFloat(name, value) elif region['type'] == 'string': results.addChar(name, value) elif region['type'] == 'bool': results.addBool(name, value) except: error = True msg += name + ' ' return rectrois, error, msg
def mrheader_series(data, results, **kwargs): """ Read selected dicomfields and write to IQC database Workflow: 1. Run tests 2. Build xml output """ info = 'dicom' dcmInfile, pixeldataIn, dicomMode = wadwrapper_lib.prepareInput( data.series_filelist[0], headers_only=True, logTag=logTag()) qclib = QCMR_lib.PiQT_QC() cs = QCMR_lib.PiQT_Struct(dcmInfile=dcmInfile, pixeldataIn=pixeldataIn, dicomMode=dicomMode, piqttest=None) cs.verbose = False ## id scanner idname = "" error = qclib.DetermineScanID(cs) if error == True or cs.scanID == lit.stUnknown: raise ValueError("{} ERROR! Cannot determine MR Scan ID".format( logTag())) ## 1. Run tests setname = cs.scanID piqttests = [] if setname == 'QA1': piqttests = [ # seq test, "M", philips_slicenumber, echonumber, echotime, ("QA1_Uniformity", "M", 3, 1, 30), ("QA1_Uniformity", "M", 3, 2, 100), ("QA1_Linearity", "M", 2, 1, 30), ("QA1_SliceProfile", "M", 4, 1, 30), ("QA1_SliceProfile", "M", 4, 2, 100), ("QA1_MTF", "M", 5, 1, 30), ("QA1_MTF", "M", 5, 2, 100), ] elif setname == 'QA2': piqttests = [ # seq test, "M", philips_slicenumber, echonumber, echotime, ("QA2_Uniformity", "M", 2, 1, 15), ("QA2_SliceProfile", "M", 3, 1, 15), ] elif setname == 'QA3': piqttests = [ # seq test, "M", philips_slicenumber, echonumber, echotime, ("QA3_Uniformity", "M", 1, 1, 50), ("QA3_Uniformity", "M", 1, 2, 100), ("QA3_Uniformity", "M", 1, 3, 150), ] reportkeyvals = [] for piqt in piqttests: cs = QCMR_lib.PiQT_Struct(dcmInfile, pixeldataIn, dicomMode, piqt) cs.verbose = None ## 1b. Run tests sliceno = qclib.ImageSliceNumber(cs, piqt) if sliceno < 0: print(logTag() + "[mrheader]: ", piqt, "not available for given image") sys.exit() dicominfo = qclib.DICOMInfo(cs, info, sliceno) if len(dicominfo) > 0: idname = "_" + setname + make_idname(qclib, cs, sliceno) for di in dicominfo: reportkeyvals.append((di[0] + idname, str(di[1]))) ## 2. Build xml output # plugionversion is newly added in for this plugin since pywad2 results.addChar('pluginversion' + idname, str( qclib.qcversion)) # do not specify level, use default from config for key, val in reportkeyvals: val2 = "".join([x if ord(x) < 128 else '?' for x in val]) #ignore non-ascii results.addChar(key, str(val2)[:min(len(str(val)), 128)] ) # do not specify level, use default from config
def mammoqc_series(data, results, **kwargs): """ QCMammo_UMCU checks: Uniformity (5 rois) and SNR (hologic), DoseRatio (empirical/calculated from DICOM) Artefacts (spots, dead pixels) Workflow: 2. Check data format 3. Build and populate qcstructure 4. Run tests 5. Build xml output 6. Build artefact picture thumbnail """ inputfile = data.series_filelist[0] # give me a filename ## 2. Check data format dcmInfile, pixeldataIn, dicomMode = wadwrapper_lib.prepareInput( inputfile, headers_only=False, logTag=logTag()) ## 3. Build and populate qcstructure remark = "" qcmammolib = QCMammo_lib.Mammo_QC() cs_mam = QCMammo_lib.MammoStruct(dcmInfile, pixeldataIn) cs_mam.verbose = False # do not produce detailed logging if qcmammolib.NeedsCropping(cs_mam): cs_mam.expertmode = True qcmammolib.RestrictROI(cs_mam) remark = "CROPPED" ## 4. Run tests # Uniformity check error = qcmammolib.Uniformity(cs_mam) if error: remark += "/ERROR_UNIFORMITY" # Contrast L50 error = qcmammolib.L50Contrast(cs_mam) # doesn't do anything if not L50 if error: remark += "/ERROR_L50CONTRAST" # Dose Ratio error = qcmammolib.DoseRatio(cs_mam) if error: remark += "/ERROR_DOSERATIO" # Artefacts error = qcmammolib.Artefacts(cs_mam) if error: remark += "/ERROR_ARTEFACTS" ## 5. Build xml output ## Struct now contains all the results and we can write these to the ## WAD IQ database includedlist = [ 'unif_pct', 'snr_hol', 'doseratio', 'art_clusters', 'expert_inoutoverin', 'contrast_snr' ] excludedlist = [ 'verbose', 'dcmInfile', 'pixeldataIn', 'hasmadeplots', 'means', 'stdevs', 'unif', 'snr_hol', 'unif_rois', 'doseratio', 'art_clusters', 'art_image', 'art_borderpx', 'art_threshold', 'art_rois', 'expertmode', 'expert_roipts', 'expert_frac', 'expert_inoutoverin', 'filtername', 'scannername', 'contrast_rois', 'contrast_mean', 'contrast_sd' ] idname = '_' + cs_mam.filtername if "SUMPRES" in idname: idname = "" # only one image results.addChar('NOTE' + idname, remark) for elem in cs_mam.__dict__: if elem in includedlist: newkeys = [] newvals = [] try: elemval = cs_mam.__dict__[elem] if 'contrast_snr' in elem: # array for ix, snr in enumerate(elemval): newkeys.append('CNR' + str(ix)) newvals.append(snr) elif 'art_clusters' in elem: newkeys.append(str(elem)) newvals.append(len(elemval)) else: newkeys.append(str(elem)) newvals.append(elemval) except: print(logTag() + "error for", elem) tmpdict = {} for key, val in zip(newkeys, newvals): results.addFloat(key + str(idname), val, quantity=str(key)) ## 6. Build artefact picture thumbnail filename = 'test' + idname + '.jpg' # Use jpg if a thumbnail is desired #object_naam_pad = outputfile.replace('result.xml','test'+idname+'.jpg') # Use jpg if a thumbnail is desired qcmammolib.saveAnnotatedArtefactImage(cs_mam, filename) results.addObject('ArtefactImage' + idname, filename)
def ctqc_series(data, results, params): """ QCCT_UMCU Checks: extension of Philips QuickIQ (also for older scanners without that option), for both Head and Body if provided Uniformity HU values Noise Linearity Workflow: 1. Read image or sequence 2. Run test 3. Build xml output """ dcmInfile, pixeldataIn, dicomMode = wadwrapper_lib.prepareInput( data.series_filelist[0], headers_only=False, logTag=logTag()) qclib = QCCT_lib.CT_QC() cs = QCCT_lib.CTStruct(dcmInfile=dcmInfile, pixeldataIn=pixeldataIn, dicomMode=dicomMode) cs.forceScanner = _getScannerDefinition(params) cs.verbose = False ## id scanner error = qclib.DetermineCTID(cs) if (error == True or cs.guessScanner.name == lit.stUnknown): raise ValueError("{} ERROR! Cannot determine CT ID".format(logTag)) error = qclib.HeadOrBody(cs) if (error == True or cs.anatomy == lit.stUnknown): raise ValueError("{} ERROR! Cannot determine Anatomy".format(logTag)) idname = "" if cs.anatomy == lit.stHead: idname = "_H" else: idname = "_B" # only uncomment if same config used for all scanners: idname += cs.guessScanner.name ## 2. Run tests error = qclib.AnalyseCT(cs) if error: raise ValueError("{} ERROR! Error in AnalyseCT".format(logTag)) ## Struct now contains all the results and we can write these to the ## WAD IQ database includedlist = [ 'roiavg', 'roisd', 'snr_hol', 'unif', 'linearity', 'maxdev', 'shiftxypx', ] excludedlist = [ 'verbose', 'dcmInfile', 'pixeldataIn', 'dicomMode', 'hasmadeplots', 'guessScanner', 'anatomy', 'roiavg', 'roisd', 'snr_hol', 'unif', 'linearity', 'maxdev', 'shiftxypx', 'valid' 'skull_avg', 'unif_slice', 'unif_rois' ] for elem in cs.__dict__: if elem in includedlist: newkeys = [] newvals = [] try: elemval = cs.__dict__[elem] if 'roiavg' in elem: # array of avgs newkeys.append('MeanCenter') newvals.append(elemval[0]) newkeys.append('MeanAir') newvals.append(elemval[3]) elif 'shiftxypx' in elem: newkeys.append('shiftxpx') newvals.append(elemval[0]) newkeys.append('shiftypx') newvals.append(elemval[1]) else: newkeys.append(str(elem)) newvals.append(elemval) except: print logTag() + "error for", elem elemval = -1. for key, val in zip(newkeys, newvals): results.addFloat(key + str(idname), val, quantity=str(key)) ## Build thumbnail filename = 'test' + idname + '.jpg' # Use jpg if a thumbnail is desired if cs.dicomMode == wadwrapper_lib.stMode2D: scipy.misc.imsave(filename, cs.pixeldataIn.transpose( )) # MODULE EXPECTS PYQTGRAPH DATA: X AND Y ARE TRANSPOSED! else: scipy.misc.imsave(filename, (cs.pixeldataIn[cs.unif_slice]).transpose( )) # MODULE EXPECTS PYQTGRAPH DATA: X AND Y ARE TRANSPOSED! results.addObject('CTslice' + idname, filename)
def mrheader_series(data,results,**kwargs): """ Read selected dicomfields and write to IQC database Workflow: 1. Run tests 2. Build xml output """ info = 'dicom' dcmInfile,pixeldataIn,dicomMode = wadwrapper_lib.prepareInput(data.series_filelist[0],headers_only=True,logTag=logTag()) qclib = QCMR_lib.PiQT_QC() cs = QCMR_lib.PiQT_Struct(dcmInfile=dcmInfile,pixeldataIn=pixeldataIn,dicomMode=dicomMode,piqttest=None) cs.verbose = False ## id scanner idname = "" error = qclib.DetermineScanID(cs) if error == True or cs.scanID == lit.stUnknown: raise ValueError("{} ERROR! Cannot determine MR Scan ID".format(logTag)) ## 1. Run tests setname = cs.scanID piqttests = [] if setname == 'QA1': piqttests = [ # seq test, "M", philips_slicenumber, echonumber, echotime, ("QA1_Uniformity", "M",3,1, 30), ("QA1_Uniformity", "M",3,2,100), ("QA1_Linearity" , "M",2,1, 30), ("QA1_SliceProfile", "M",4,1, 30), ("QA1_SliceProfile", "M",4,2,100), ("QA1_MTF", "M",5,1, 30), ("QA1_MTF", "M",5,2,100), ] elif setname== 'QA2': piqttests = [ # seq test, "M", philips_slicenumber, echonumber, echotime, ("QA2_Uniformity", "M",2,1, 15), ("QA2_SliceProfile", "M",3,1, 15), ] elif setname == 'QA3': piqttests = [ # seq test, "M", philips_slicenumber, echonumber, echotime, ("QA3_Uniformity", "M",1,1, 50), ("QA3_Uniformity", "M",1,2,100), ("QA3_Uniformity", "M",1,3,150), ] reportkeyvals = [] for piqt in piqttests: cs = QCMR_lib.PiQT_Struct(dcmInfile,pixeldataIn,dicomMode,piqt) cs.verbose = None ## 1b. Run tests sliceno = qclib.ImageSliceNumber(cs,piqt) if sliceno <0: print logTag()+"[mrheader]: ", piqt, "not available for given image" sys.exit() dicominfo = qclib.DICOMInfo(cs,info,sliceno) if len(dicominfo) >0: idname = "_"+setname+make_idname(qclib,cs,sliceno) for di in dicominfo: reportkeyvals.append( (di[0]+idname,str(di[1])) ) ## 2. Build xml output # plugionversion is newly added in for this plugin since pywad2 results.addChar('pluginversion'+idname, str(qclib.qcversion)) # do not specify level, use default from config for key,val in reportkeyvals: val2 = "".join([x if ord(x) < 128 else '?' for x in val]) #ignore non-ascii results.addChar(key, str(val2)[:min(len(str(val)),128)]) # do not specify level, use default from config
def mrqc_series(data, results, **kwargs): """ QCMR_UMCU Checks: Philips PiQT reimplementen in python Uniformity (several ways) Geometrical deformation ArtifactLevel Signal-to-noise (several positions) Resolution (MTF, FTW, SliceWidth) Workflow: 1. Read image or sequence 2. Run test 3. Build xml output """ dcmInfile, pixeldataIn, dicomMode = wadwrapper_lib.prepareInput( data.series_filelist[0], headers_only=False, logTag=logTag()) qclib = QCMR_lib.PiQT_QC() cs = QCMR_lib.PiQT_Struct(dcmInfile=dcmInfile, pixeldataIn=pixeldataIn, dicomMode=dicomMode, piqttest=None) cs.verbose = False ## id scanner idname = "" error = qclib.DetermineScanID(cs) if error == True or cs.scanID == lit.stUnknown: raise ValueError("{} ERROR! Cannot determine MR Scan ID".format( logTag())) ## 2. Run tests setname = cs.scanID piqttests = [] if setname == 'QA1': piqttests = [ # seq test, "M", philips_slicenumber, echonumber, echotime, ("QA1_Uniformity", "M", 3, 1, 30), ("QA1_Uniformity", "M", 3, 2, 100), ("QA1_Linearity", "M", 2, 1, 30), ("QA1_SliceProfile", "M", 4, 1, 30), ("QA1_SliceProfile", "M", 4, 2, 100), ("QA1_MTF", "M", 5, 1, 30), ("QA1_MTF", "M", 5, 2, 100), ] elif setname == 'QA2': piqttests = [ # seq test, "M", philips_slicenumber, echonumber, echotime, ("QA2_Uniformity", "M", 2, 1, 15), ("QA2_SliceProfile", "M", 3, 1, 15), ] elif setname == 'QA3': piqttests = [ # seq test, "M", philips_slicenumber, echonumber, echotime, ("QA3_Uniformity", "M", 1, 1, 50), ("QA3_Uniformity", "M", 1, 2, 100), ("QA3_Uniformity", "M", 1, 3, 150), ] reportkeyvals = [] for piqt in piqttests: print("[mrqc]", 2, piqt) if "Uniformity" in piqt[0]: test = lit.stTestUniformity doTest = "SNR_ArtifactLevel_FloodFieldUniformity" if "Linearity" in piqt[0]: test = lit.stTestSpatialLinearity doTest = "SpatialLinearity" if "SliceProfile" in piqt[0]: test = lit.stTestSliceProfile doTest = "SliceProfile" if "MTF" in piqt[0]: test = lit.stTestMTF doTest = "MTF" cs = QCMR_lib.PiQT_Struct(dcmInfile, pixeldataIn, dicomMode, piqt) cs.verbose = None if "FloodFieldUniformity" in doTest: # FFU also contains SNR and ArtifactLevel error = qclib.FloodFieldUniformity(cs) if not error: import numpy as np idname = "_" + setname + make_idname(qclib, cs, cs.snr_slice) reportkeyvals.append(("S/N (B)" + idname, cs.snr_SNB)) reportkeyvals.append( ("Art_Level" + idname, cs.artefact_ArtLevel)) reportkeyvals.append(("T/C-20" + idname, cs.ffu_TCm20)) reportkeyvals.append(("C-20/C-10" + idname, cs.ffu_Cm20Cm10)) reportkeyvals.append(("C-10/C+10" + idname, cs.ffu_Cm10Cp10)) reportkeyvals.append(("C+10/C+20" + idname, cs.ffu_Cp10Cp20)) reportkeyvals.append(("C+20/Max" + idname, cs.ffu_Cp20MAX)) reportkeyvals.append(("Rad 10%" + idname, cs.ffu_rad10)) reportkeyvals.append(("Int_Unif" + idname, cs.ffu_lin_unif)) ## Build thumbnail filename = 'FFU' + idname + '.jpg' # Use jpg if a thumbnail is desired qclib.saveResultImage(cs, 'FFU', filename) results.addObject('FFU' + '_' + idname, filename) elif "ArtifactLevel" in doTest: # Artifact also contains SNR error = qclib.ArtifactLevel(cs) if not error: idname = "_" + setname + make_idname(qclib, cs, cs.snr_slice) reportkeyvals.append(("S/N (B)" + idname, cs.snr_SNB)) reportkeyvals.append( ("Art_Level" + idname, cs.artefact_ArtLevel)) elif "SNR" in doTest: error = qclib.SNR(cs) if not error: idname = "_" + setname + make_idname(qclib, cs, cs.snr_slice) reportkeyvals.append(("S/N (B)" + idname, cs.snr_SNB)) if "SpatialLinearity" in doTest: error = qclib.SpatialLinearity(cs) if not error: idname = "_" + setname + make_idname(qclib, cs, cs.lin_slice) reportkeyvals.append( ("phant_rot" + idname, cs.lin_phantomrotdeg)) reportkeyvals.append(("m/p_angle" + idname, str(-360))) reportkeyvals.append(("size_hor" + idname, cs.lin_sizehor)) reportkeyvals.append(("size_ver" + idname, cs.lin_sizever)) reportkeyvals.append( ("hor_int_av" + idname, cs.lin_intshiftavg[0])) reportkeyvals.append( ("hor_int_dev" + idname, cs.lin_intshiftsdev[0])) reportkeyvals.append( ("hor_max_right" + idname, cs.lin_shiftmax[0])) reportkeyvals.append( ("hor_max_left" + idname, cs.lin_shiftmin[0])) reportkeyvals.append( ("hor_diff_av" + idname, cs.lin_intdiffavg[0])) reportkeyvals.append( ("hor_diff_dev" + idname, cs.lin_intdiffsdev[0])) reportkeyvals.append( ("hor_max" + idname, cs.lin_intdiffmax[0])) reportkeyvals.append( ("hor_min" + idname, cs.lin_intdiffmin[0])) reportkeyvals.append( ("ver_int_av" + idname, cs.lin_intshiftavg[1])) reportkeyvals.append( ("ver_int_dev" + idname, cs.lin_intshiftsdev[1])) reportkeyvals.append( ("ver_max_up" + idname, cs.lin_shiftmax[1])) reportkeyvals.append( ("ver_max_down" + idname, cs.lin_shiftmin[1])) reportkeyvals.append( ("ver_diff_av" + idname, cs.lin_intdiffavg[1])) reportkeyvals.append( ("ver_diff_dev" + idname, cs.lin_intdiffsdev[1])) reportkeyvals.append( ("ver_max" + idname, cs.lin_intdiffmax[1])) reportkeyvals.append( ("ver_min" + idname, cs.lin_intdiffmin[1])) ## Build thumbnail filename = 'LIN' + idname + '.jpg' # Use jpg if a thumbnail is desired qclib.saveResultImage(cs, 'LIN', filename) results.addObject('LIN' + '_' + idname, filename) if "SliceProfile" in doTest: error = qclib.SliceProfile(cs) if not error: idname = "_" + setname + make_idname(qclib, cs, cs.sp_slice) reportkeyvals.append( ("Pos_shift" + idname, cs.sp_phantomshift)) reportkeyvals.append(("FWHM" + idname, cs.sp_slicewidth_fwhm)) reportkeyvals.append(("FWTM" + idname, cs.sp_slicewidth_fwtm)) reportkeyvals.append( ("Slice_int" + idname, cs.sp_slicewidth_lineint)) reportkeyvals.append( ("Angle" + idname, cs.sp_phantomzangledeg)) reportkeyvals.append( ("phant_rot" + idname, cs.sp_phantomrotdeg)) reportkeyvals.append( ("Phase_Shift" + idname, cs.sp_phaseshift)) ## Build thumbnail filename = 'SLP' + idname + '.jpg' # Use jpg if a thumbnail is desired qclib.saveResultImage(cs, 'SLP', filename) results.addObject('SLP' + '_' + idname, filename) if "MTF" in doTest: error = qclib.MTF(cs) if not error: idname = "_" + setname + make_idname(qclib, cs, cs.mtf_slice) reportkeyvals.append( ("Hor_pxl_size" + idname, cs.mtf_pixelsize[0])) reportkeyvals.append( ("Ver_pxl_size" + idname, cs.mtf_pixelsize[1])) ## Build thumbnail filename = 'MTF' + idname + '.jpg' # Use jpg if a thumbnail is desired qclib.saveResultImage(cs, 'MTF', filename) results.addObject('MTF' + '_' + idname, filename) if error: raise ValueError("{} ERROR! processing error in {} {}".format( logTag(), piqt, doTest)) for key, val in reportkeyvals: results.addFloat(key, val, quantity=str(key.split('_QA')[0]))
def mrqc_series(data,results,**kwargs): """ QCMR_UMCU Checks: Philips PiQT reimplementen in python Uniformity (several ways) Geometrical deformation ArtifactLevel Signal-to-noise (several positions) Resolution (MTF, FTW, SliceWidth) Workflow: 1. Read image or sequence 2. Run test 3. Build xml output """ dcmInfile,pixeldataIn,dicomMode = wadwrapper_lib.prepareInput(data.series_filelist[0],headers_only=False,logTag=logTag()) qclib = QCMR_lib.PiQT_QC() cs = QCMR_lib.PiQT_Struct(dcmInfile=dcmInfile,pixeldataIn=pixeldataIn,dicomMode=dicomMode,piqttest=None) cs.verbose = False ## id scanner idname = "" error = qclib.DetermineScanID(cs) if error == True or cs.scanID == lit.stUnknown: raise ValueError("{} ERROR! Cannot determine MR Scan ID".format(logTag)) ## 2. Run tests setname = cs.scanID piqttests = [] if setname == 'QA1': piqttests = [ # seq test, "M", philips_slicenumber, echonumber, echotime, ("QA1_Uniformity", "M",3,1, 30), ("QA1_Uniformity", "M",3,2,100), ("QA1_Linearity" , "M",2,1, 30), ("QA1_SliceProfile", "M",4,1, 30), ("QA1_SliceProfile", "M",4,2,100), ("QA1_MTF", "M",5,1, 30), ("QA1_MTF", "M",5,2,100), ] elif setname== 'QA2': piqttests = [ # seq test, "M", philips_slicenumber, echonumber, echotime, ("QA2_Uniformity", "M",2,1, 15), ("QA2_SliceProfile", "M",3,1, 15), ] elif setname == 'QA3': piqttests = [ # seq test, "M", philips_slicenumber, echonumber, echotime, ("QA3_Uniformity", "M",1,1, 50), ("QA3_Uniformity", "M",1,2,100), ("QA3_Uniformity", "M",1,3,150), ] reportkeyvals = [] for piqt in piqttests: print "[mrqc]",2,piqt if "Uniformity" in piqt[0]: test = lit.stTestUniformity doTest = "SNR_ArtifactLevel_FloodFieldUniformity" if "Linearity" in piqt[0]: test = lit.stTestSpatialLinearity doTest = "SpatialLinearity" if "SliceProfile" in piqt[0]: test = lit.stTestSliceProfile doTest = "SliceProfile" if "MTF" in piqt[0]: test = lit.stTestMTF doTest = "MTF" cs = QCMR_lib.PiQT_Struct(dcmInfile,pixeldataIn,dicomMode,piqt) cs.verbose = None if "SNR" in doTest: error = qclib.SNR(cs) if not error: idname = "_"+setname+make_idname(qclib,cs,cs.snr_slice) reportkeyvals.append( ("S/N (B)"+idname,cs.snr_SNB) ) if "ArtifactLevel" in doTest: error = qclib.ArtifactLevel(cs) if not error: idname = "_"+setname+make_idname(qclib,cs,cs.snr_slice) reportkeyvals.append( ("Art_Level"+idname,cs.artefact_ArtLevel) ) if "FloodFieldUniformity" in doTest: error = qclib.FloodFieldUniformity(cs) if not error: import numpy as np idname = "_"+setname+make_idname(qclib,cs,cs.snr_slice) reportkeyvals.append( ("T/C-20"+idname,cs.ffu_TCm20) ) reportkeyvals.append( ("C-20/C-10"+idname,cs.ffu_Cm20Cm10) ) reportkeyvals.append( ("C-10/C+10"+idname,cs.ffu_Cm10Cp10) ) reportkeyvals.append( ("C+10/C+20"+idname,cs.ffu_Cp10Cp20) ) reportkeyvals.append( ("C+20/Max"+idname,cs.ffu_Cp20MAX) ) reportkeyvals.append( ("Rad 10%"+idname,cs.ffu_rad10) ) reportkeyvals.append( ("Int_Unif"+idname,cs.ffu_lin_unif) ) ## Build thumbnail filename = 'test'+idname+'.jpg' # Use jpg if a thumbnail is desired scipy.misc.imsave(filename,cs.lastimage.transpose()) # MODULE EXPECTS PYQTGRAPH DATA: X AND Y ARE TRANSPOSED! results.addObject('FFU'+'_'+idname,filename) if "SpatialLinearity" in doTest: error = qclib.SpatialLinearity(cs) if not error: idname = "_"+setname+make_idname(qclib,cs,cs.lin_slice) reportkeyvals.append( ("phant_rot"+idname,cs.lin_phantomrotdeg) ) reportkeyvals.append( ("m/p_angle"+idname,str(-360)) ) reportkeyvals.append( ("size_hor"+idname,cs.lin_sizehor) ) reportkeyvals.append( ("size_ver"+idname,cs.lin_sizever) ) reportkeyvals.append( ("hor_int_av"+idname,cs.lin_intshiftavg[0]) ) reportkeyvals.append( ("hor_int_dev"+idname,cs.lin_intshiftsdev[0]) ) reportkeyvals.append( ("hor_max_right"+idname,cs.lin_shiftmax[0]) ) reportkeyvals.append( ("hor_max_left"+idname,cs.lin_shiftmin[0]) ) reportkeyvals.append( ("hor_diff_av"+idname,cs.lin_intdiffavg[0]) ) reportkeyvals.append( ("hor_diff_dev"+idname,cs.lin_intdiffsdev[0]) ) reportkeyvals.append( ("hor_max"+idname,cs.lin_intdiffmax[0]) ) reportkeyvals.append( ("hor_min"+idname,cs.lin_intdiffmin[0]) ) reportkeyvals.append( ("ver_int_av"+idname,cs.lin_intshiftavg[1]) ) reportkeyvals.append( ("ver_int_dev"+idname,cs.lin_intshiftsdev[1]) ) reportkeyvals.append( ("ver_max_up"+idname,cs.lin_shiftmax[1]) ) reportkeyvals.append( ("ver_max_down"+idname,cs.lin_shiftmin[1]) ) reportkeyvals.append( ("ver_diff_av"+idname,cs.lin_intdiffavg[1]) ) reportkeyvals.append( ("ver_diff_dev"+idname,cs.lin_intdiffsdev[1]) ) reportkeyvals.append( ("ver_max"+idname,cs.lin_intdiffmax[1]) ) reportkeyvals.append( ("ver_min"+idname,cs.lin_intdiffmin[1]) ) if "SliceProfile" in doTest: error = qclib.SliceProfile(cs) if not error: idname = "_"+setname+make_idname(qclib,cs,cs.sp_slice) reportkeyvals.append( ("Pos_shift"+idname,cs.sp_phantomshift) ) reportkeyvals.append( ("FWHM"+idname,cs.sp_slicewidth_fwhm) ) reportkeyvals.append( ("FWTM"+idname,cs.sp_slicewidth_fwtm) ) reportkeyvals.append( ("Slice_int"+idname,cs.sp_slicewidth_lineint) ) reportkeyvals.append( ("Angle"+idname,cs.sp_phantomzangledeg) ) reportkeyvals.append( ("phant_rot"+idname,cs.sp_phantomrotdeg) ) reportkeyvals.append( ("Phase_Shift"+idname,cs.sp_phaseshift) ) if "MTF" in doTest: error = qclib.MTF(cs) if not error: idname = "_"+setname+make_idname(qclib,cs,cs.mtf_slice) reportkeyvals.append( ("Hor_pxl_size"+idname,cs.mtf_pixelsize[0]) ) reportkeyvals.append( ("Ver_pxl_size"+idname,cs.mtf_pixelsize[1]) ) if error: raise ValueError("{} ERROR! processing error in {} {}".format(logTag,piqt,doTest)) for key,val in reportkeyvals: results.addFloat(key, val, quantity=str(key.split('_QA')[0]))