def load_xml_data(infile): """Read in a file in RFB format and return a list of Beam objects""" f = open(infile,'rb') tree = objectify.parse(f) f.close() schema_file = open('radpy/plugins/BeamAnalysis/BDML/bdml.xsd','r') bdml_schema = etree.parse(schema_file) xmlschema = etree.XMLSchema(bdml_schema) if not xmlschema.validate(tree): raise IOError('Not a valid BDML file.') bdml = tree.getroot() b = [] for i in bdml.Beam: xml_class = Beam() xml_class.importXML(i) b.append(xml_class) f.close() return b
def load_xml_data(infile): """Read in a file in RFB format and return a list of Beam objects""" f = open(infile, 'rb') tree = objectify.parse(f) f.close() schema_file = open('radpy/plugins/BeamAnalysis/BDML/bdml.xsd', 'r') bdml_schema = etree.parse(schema_file) xmlschema = etree.XMLSchema(bdml_schema) if not xmlschema.validate(tree): raise IOError('Not a valid BDML file.') bdml = tree.getroot() b = [] for i in bdml.Beam: xml_class = Beam() xml_class.importXML(i) b.append(xml_class) f.close() return b
def editAll(self): global_beam = Beam() beams = self.model().asRecord(self.currentIndex()) global_dict = global_beam.trait_get() for key in global_dict.keys(): if key == 'Data_Abscissa' or key == 'Data_Ordinate': continue traits = [getattr(beam[1], key) for beam in beams] #Test if all traits in the list are the same if all(traits[0] == trait for trait in traits): setattr(global_beam, key, traits[0]) #removeRecord returns True if the root node is deleted. This will #require a reset of the TreeView. (the second parameter of addRecord #must be True) root_reset = self.model().removeRecord(self.currentIndex()) #Since traitsUI windows cannot be set to be application modal, the #tree view must be disabled to prevent the user from making changes #to the tree model during editing. Allowing changes can lead to #unexpected behavior. self.setEnabled(False) global_beam.edit_traits() self.setEnabled(True) global_dict = global_beam.trait_get() for beam in beams: for key in global_dict.keys(): if key == 'Data_Abscissa' or key == 'Data_Ordinate': continue try: global_val = getattr(global_beam, key) trait_val = getattr(beam[1], key) if global_val != trait_val and not global_beam.is_null( key): setattr(beam[1], key, global_val) except AttributeError: pass self.model().addRecord(beam[1], root_reset)
def editAll(self): global_beam = Beam() beams = self.model().asRecord(self.currentIndex()) global_dict = global_beam.trait_get() for key in global_dict.keys(): if key == 'Data_Abscissa' or key == 'Data_Ordinate': continue traits = [getattr(beam[1], key) for beam in beams] #Test if all traits in the list are the same if all(traits[0] == trait for trait in traits): setattr(global_beam, key, traits[0]) #removeRecord returns True if the root node is deleted. This will #require a reset of the TreeView. (the second parameter of addRecord #must be True) root_reset = self.model().removeRecord(self.currentIndex()) #Since traitsUI windows cannot be set to be application modal, the #tree view must be disabled to prevent the user from making changes #to the tree model during editing. Allowing changes can lead to #unexpected behavior. self.setEnabled(False) global_beam.edit_traits() self.setEnabled(True) global_dict = global_beam.trait_get() for beam in beams: for key in global_dict.keys(): if key == 'Data_Abscissa' or key == 'Data_Ordinate': continue try: global_val = getattr(global_beam, key) trait_val = getattr(beam[1], key) if global_val != trait_val and not global_beam.is_null(key): setattr(beam[1], key, global_val) except AttributeError: pass self.model().addRecord(beam[1], root_reset)
def get_beam(self, start, stop, axis_len): """Given two points, returns a beam object with a profile between them""" #Currently, this assumes that the profile will be either #inplane, crossplane or a depth dose (i.e. start and stop positions #are the same in two coordinates). #This function needs a good way to determine the abscissa axis values #in order to generalize to any linear scan. #Orient start-stop from negative to positive values scan_range = numpy.array([start[0]-stop[0],start[1]-stop[1], start[2]-stop[2]]) if len(scan_range.nonzero()[0]) != 1: raise ValueError("Point to point scans are not able to matched in RadPy.") axis = scan_range.nonzero()[0][0] #Always orient the array from negative to positive coordinate values. if start[axis] > stop[axis]: start[axis], stop[axis] = stop[axis], start[axis] dcm_start = [min(self.Data.x_axis), min(self.Data.y_axis), min(self.Data.z_axis)] dcm_stop = [max(self.Data.x_axis), max(self.Data.y_axis), max(self.Data.z_axis)] for i in range(3): if not (self.overlap((start[i],stop[i]),(dcm_start[i], dcm_stop[i]))): raise ValueError("The scan range is outside the Dicom data range.") #Truncate if scan extends beyond dicom range if start[i] < dcm_start[i]: start[i] = dcm_start[i] if stop[i] > dcm_stop[i]: stop[i] = dcm_stop[i] #axis = scan_range.nonzero()[0][0] # abs_0 = dcm_start[axis] # abs_1 = dcm_stop[axis] abscissa = numpy.linspace(start[axis], stop[axis], axis_len) # abs_0 = start[axis] # abs_1 = stop[axis] x_interp = scipy.interpolate.interp1d(self.Data.x_axis, numpy.arange(len(self.Data.x_axis))) y_interp = scipy.interpolate.interp1d(self.Data.y_axis, numpy.arange(len(self.Data.y_axis))) z_indices = numpy.argsort(self.Data.z_axis) z_interp = scipy.interpolate.interp1d(self.Data.z_axis[z_indices], numpy.arange(len(self.Data.z_axis))) x_values = x_interp(numpy.linspace(start[0],stop[0],axis_len)) y_values = y_interp(numpy.linspace(start[1],stop[1],axis_len)) z_values = z_interp(numpy.linspace(start[2],stop[2],axis_len)) # axes = [x_values, y_values, z_values] # #abscissa = numpy.linspace(abs_0,abs_1,axis_len) # abscissa = axes[axis] # x_ind, y_ind, z_ind = numpy.mgrid[0:axis_len,0:axis_len,0:axis_len] # x_step = self.Data.x_axis[1] - self.Data.x_axis[0] # x_values = x_ind*x_step + start[0] interp_vals = numpy.array([x_values,y_values,z_values]) ordinate = scipy.ndimage.map_coordinates(self.Data.dose, interp_vals) # abscissa = self.Data.x_axis[27:89] # ordinate = self.Data.dose[27:89,38,24] # abscissa = [] # i0 = numpy.sqrt(start[0]**2 + start[1]**2 + start[2]**2) # i1 = numpy.sqrt((stop[0] - start[0])**2 + (stop[1] - start[1])**2 + # (stop[2] - start[2])**2)/len(ordinate) # for i in range(len(ordinate)): # abscissa.append(i0 + i*i1) #Create and initialize a new Beam object xml_beam = Beam() xml_beam.copy_traits(self) if axis == 2: #Depth dose xml_beam.Data_Abscissa = -abscissa[::-1] xml_beam.Data_Ordinate = ordinate[::-1] else: xml_beam.Data_Abscissa = abscissa xml_beam.Data_Ordinate = ordinate xml_beam.MeasurementDetails_StartPosition_x = start[0] xml_beam.MeasurementDetails_StopPosition_x = stop[0] xml_beam.MeasurementDetails_StartPosition_y = start[1] xml_beam.MeasurementDetails_StopPosition_y = stop[1] xml_beam.MeasurementDetails_StartPosition_z = start[2] xml_beam.MeasurementDetails_StopPosition_z = stop[2] xml_beam.filename = self.filename xml_beam.scan_type = xml_beam.get_scan_type() #xml_beam.set_label() return xml_beam