def marshall(self): yts=md.constants.yts; WriteData(fid,prefix,'object',self,'class','inversion','fieldname','iscontrol','format','Boolean'); WriteData(fid,prefix,'name','md.inversion.type','data',4,'format','Integer'); if not self.iscontrol: return WriteData(fid,prefix,'object',self,'class','inversion','fieldname','control_scaling_factors','format','DoubleMat','mattype',3); WriteData(fid,prefix,'object',self,'class','inversion','fieldname','maxsteps','format','Integer'); WriteData(fid,prefix,'object',self,'class','inversion','fieldname','maxiter','format','Integer'); WriteData(fid,prefix,'object',self,'class','inversion','fieldname','dxmin','format','Double'); WriteData(fid,prefix,'object',self,'class','inversion','fieldname','gttol','format','Double'); WriteData(fid,prefix,'object',self,'class','inversion','fieldname','cost_functions_coefficients','format','DoubleMat','mattype',1); WriteData(fid,prefix,'object',self,'class','inversion','fieldname','min_parameters','format','DoubleMat','mattype',3); WriteData(fid,prefix,'object',self,'class','inversion','fieldname','max_parameters','format','DoubleMat','mattype',3); WriteData(fid,prefix,'object',self,'class','inversion','fieldname','vx_obs','format','DoubleMat','mattype',1,'scale',1./yts); WriteData(fid,prefix,'object',self,'class','inversion','fieldname','vy_obs','format','DoubleMat','mattype',1,'scale',1./yts); WriteData(fid,prefix,'object',self,'class','inversion','fieldname','vz_obs','format','DoubleMat','mattype',1,'scale',1./yts); if(numel(self.thickness_obs)==md.mesh.numberofelements): mattype=2; else: mattype=1; WriteData(fid,prefix,'object',self,'class','inversion','fieldname','thickness_obs','format','DoubleMat','mattype',mattype); WriteData(fid,prefix,'object',self,'class','inversion','fieldname','surface_obs','format','DoubleMat','mattype',mattype); #process control parameters num_control_parameters = np.numel(self.control_parameters); WriteData(fid,prefix,'object',self,'fieldname','control_parameters','format','StringArray'); WriteData(fid,prefix,'data',num_control_parameters,'name','md.inversion.num_control_parameters','format','Integer'); #process cost functions num_cost_functions=np.size(self.cost_functions,2); data=copy.deepcopy(self.cost_functions) data[np.nonzero(self.cost_functions==101)] =['SurfaceAbsVelMisfit']; data[np.nonzero(self.cost_functions==102)]=['SurfaceRelVelMisfit']; data[np.nonzero(self.cost_functions==103)]=['SurfaceLogVelMisfit']; data[np.nonzero(self.cost_functions==104)]=['SurfaceLogVxVyMisfit']; data[np.nonzero(self.cost_functions==105)]=['SurfaceAverageVelMisfit']; data[np.nonzero(self.cost_functions==201)]=['ThicknessAbsMisfit']; data[np.nonzero(self.cost_functions==501)]=['DragCoefficientAbsGradient']; data[np.nonzero(self.cost_functions==502)]=['RheologyBbarAbsGradient']; data[np.nonzero(self.cost_functions==503)]=['ThicknessAbsGradient']; data[np.nonzero(self.cost_functions==504)]=['ThicknessAlongGradient']; data[np.nonzero(self.cost_functions==505)]=['ThicknessAcrossGradient']; data[np.nonzero(self.cost_functions==506)]=['BalancethicknessMisfit']; data[np.nonzero(self.cost_functions==601)]=['SurfaceAbsMisfit']; data[np.nonzero(self.cost_functions==1001)]=['Outputdefinition1']; data[np.nonzero(self.cost_functions==1002)]=['Outputdefinition2']; data[np.nonzero(self.cost_functions==1003)]=['Outputdefinition3']; data[np.nonzero(self.cost_functions==1004)]=['Outputdefinition4']; data[np.nonzero(self.cost_functions==1005)]=['Outputdefinition5']; data[np.nonzero(self.cost_functions==1006)]=['Outputdefinition6']; data[np.nonzero(self.cost_functions==1007)]=['Outputdefinition7']; data[np.nonzero(self.cost_functions==1008)]=['Outputdefinition8']; data[np.nonzero(self.cost_functions==1009)]=['Outputdefinition8']; data[np.nonzero(self.cost_functions==1010)]=['Outputdefinition10']; WriteData(fid,prefix,'data',data,'name','md.inversion.cost_functions','format','StringArray'); WriteData(fid,prefix,'data',num_cost_functions,'name','md.inversion.num_cost_functions','format','Integer');
def checkconsistency(self, md, solution, analyses): # Early return if not self.iscontrol: return if not IssmConfig('_HAVE_M1QN3_')[0]: md = checkmessage(md,['M1QN3 has not been installed, ISSM needs to be reconfigured and recompiled with AD']) num_controls=np.numel(md.inversion.control_parameters) num_costfunc=np.size(md.inversion.cost_functions,2) md = checkfield(md,'fieldname','inversion.iscontrol','values',[0, 1]) md = checkfield(md,'fieldname','inversion.control_parameters','cell',1,'values',\ ['BalancethicknessThickeningRate' 'FrictionCoefficient' 'MaterialsRheologyBbar' 'DamageDbar',\ 'Vx' 'Vy' 'Thickness' 'BalancethicknessOmega' 'BalancethicknessApparentMassbalance']) md = checkfield(md,'fieldname','inversion.control_scaling_factors','size',[1, num_controls],'>',0,float('Nan'),1) md = checkfield(md,'fieldname','inversion.maxsteps','numel',1,'>=',0) md = checkfield(md,'fieldname','inversion.maxiter','numel',1,'>=',0) md = checkfield(md,'fieldname','inversion.dxmin','numel',1,'>',0) md = checkfield(md,'fieldname','inversion.gttol','numel',1,'>',0) md = checkfield(md,'fieldname','inversion.cost_functions','size',[1, num_costfunc],'values', [i for i in range(101,106)]+[201]+[i for i in range(501,507)]+[i for i in range(601,605)]+[i for i in range(1001, 1011)]) md = checkfield(md,'fieldname','inversion.cost_functions_coefficients','size',[md.mesh.numberofvertices, num_costfunc],'>=',0) md = checkfield(md,'fieldname','inversion.min_parameters','size',[md.mesh.numberofvertices, num_controls]) md = checkfield(md,'fieldname','inversion.max_parameters','size',[md.mesh.numberofvertices, num_controls]) if solution=='BalancethicknessSolution': md = checkfield(md,'fieldname','inversion.thickness_obs','size',[md.mesh.numberofvertices],float('Nan'),1) md = checkfield(md,'fieldname','inversion.surface_obs','size',[md.mesh.numberofvertices], float('Nan'),1) elif solution=='BalancethicknessSoftSolution': md = checkfield(md,'fieldname','inversion.thickness_obs','size',[md.mesh.numberofvertices],float('Nan'),1) else: md = checkfield(md,'fieldname','inversion.vx_obs','size',[md.mesh.numberofvertices],float('Nan'),1) if not np.strcmp(domaintype(md.mesh),'2Dvertical'): md = checkfield(md,'fieldname','inversion.vy_obs','size',[md.mesh.numberofvertices],float('Nan'),1) return md
def marshall(self, md, fid): yts=365.0*24.0*3600.0; WriteData(fid,'object',self,'class','inversion','fieldname','iscontrol','format','Boolean') WriteData(fid,'enum',InversionTypeEnum(),'data',1,'format','Integer') if not self.iscontrol: return WriteData(fid,'object',self,'class','inversion','fieldname','incomplete_adjoint','format','Boolean') WriteData(fid,'object',self,'class','inversion','fieldname','maxsteps','format','Integer') WriteData(fid,'object',self,'class','inversion','fieldname','maxiter','format','Integer') WriteData(fid,'object',self,'class','inversion','fieldname','fatol','format','Double') WriteData(fid,'object',self,'class','inversion','fieldname','frtol','format','Double') WriteData(fid,'object',self,'class','inversion','fieldname','gatol','format','Double') WriteData(fid,'object',self,'class','inversion','fieldname','grtol','format','Double') WriteData(fid,'object',self,'class','inversion','fieldname','gttol','format','Double') WriteData(fid,'object',self,'class','inversion','fieldname','algorithm','format','String') WriteData(fid,'object',self,'class','inversion','fieldname','cost_functions_coefficients','format','DoubleMat','mattype',1) WriteData(fid,'object',self,'class','inversion','fieldname','min_parameters','format','DoubleMat','mattype',3) WriteData(fid,'object',self,'class','inversion','fieldname','max_parameters','format','DoubleMat','mattype',3) WriteData(fid,'object',self,'class','inversion','fieldname','vx_obs','format','DoubleMat','mattype',1,'scale',1./yts) WriteData(fid,'object',self,'class','inversion','fieldname','vy_obs','format','DoubleMat','mattype',1,'scale',1./yts) WriteData(fid,'object',self,'class','inversion','fieldname','vz_obs','format','DoubleMat','mattype',1,'scale',1./yts) WriteData(fid,'object',self,'class','inversion','fieldname','thickness_obs','format','DoubleMat','mattype',1) WriteData(fid,'object',self,'class','inversion','fieldname','surface_obs','format','DoubleMat','mattype',1) #process control parameters num_control_parameters = numpy.numel(self.control_parameters) data = numpy.array([StringToEnum(self.control_parameter[0]) for control_parameter in self.control_parameters]).reshape(1,-1) WriteData(fid,'data',data,'enum',InversionControlParametersEnum(),'format','DoubleMat','mattype',3) WriteData(fid,'data',num_control_parameters,'enum',InversionNumControlParametersEnum(),'format','Integer') #process cost functions num_cost_functions = numpy.size(self.cost_functions,2) data= marshallcostfunctions(self.cost_functions) WriteData(fid,'data',data,'enum',InversionCostFunctionsEnum(),'format','DoubleMat','mattype',3) WriteData(fid,'data',num_cost_functions,'enum',InversionNumCostFunctionsEnum(),'format','Integer')
def checkconsistency(self,md,solution,analyses): if not self.control: return md if not IssmConfig('_HAVE_TAO_'): md = checkmessage(md,['TAO has not been installed, ISSM needs to be reconfigured and recompiled with TAO']) num_controls= numpy.numel(md.inversion.control_parameters) num_costfunc= numpy.size(md.inversion.cost_functions,2) md = checkfield(md,'fieldname','inversion.iscontrol','values',[0, 1]) md = checkfield(md,'fieldname','inversion.incomplete_adjoint','values',[0, 1]) md = checkfield(md,'fieldname','inversion.control_parameters','cell',1,'values',supportedcontrols()) md = checkfield(md,'fieldname','inversion.maxsteps','numel',1,'>=',0) md = checkfield(md,'fieldname','inversion.maxiter','numel',1,'>=',0) md = checkfield(md,'fieldname','inversion.fatol','numel',1,'>=',0) md = checkfield(md,'fieldname','inversion.frtol','numel',1,'>=',0) md = checkfield(md,'fieldname','inversion.gatol','numel',1,'>=',0) md = checkfield(md,'fieldname','inversion.grtol','numel',1,'>=',0) md = checkfield(md,'fieldname','inversion.gttol','numel',1,'>=',0) PETSCMAJOR = IssmConfig('_PETSC_MAJOR_') PETSCMINOR = IssmConfig('_PETSC_MINOR_') if(PETSCMAJOR>3 or (PETSCMAJOR==3 and PETSCMINOR>=5)): md = checkfield(md,'fieldname','inversion.algorithm','values',{'blmvm','cg','lmvm'}) else: md = checkfield(md,'fieldname','inversion.algorithm','values',{'tao_blmvm','tao_cg','tao_lmvm'}) md = checkfield(md,'fieldname','inversion.cost_functions','size',[1, num_costfunc],'values',supportedcostfunctions()) md = checkfield(md,'fieldname','inversion.cost_functions_coefficients','size',[md.mesh.numberofvertices, num_costfunc],'>=',0) md = checkfield(md,'fieldname','inversion.min_parameters','size',[md.mesh.numberofvertices, num_controls]) md = checkfield(md,'fieldname','inversion.max_parameters','size',[md.mesh.numberofvertices, num_controls]) if solution==BalancethicknessSolutionEnum(): md = checkfield(md,'fieldname','inversion.thickness_obs','size',[md.mesh.numberofvertices, 1],'NaN',1,'Inf',1) elif solution==BalancethicknessSoftSolutionEnum(): md = checkfield(md,'fieldname','inversion.thickness_obs','size',[md.mesh.numberofvertices, 1],'NaN',1,'Inf',1) else: md = checkfield(md,'fieldname','inversion.vx_obs','size',[md.mesh.numberofvertices, 1],'NaN',1,'Inf',1) md = checkfield(md,'fieldname','inversion.vy_obs','size',[md.mesh.numberofvertices, 1],'NaN',1,'Inf',1) def marshall(self, md, fid): yts=365.0*24.0*3600.0; WriteData(fid,'object',self,'class','inversion','fieldname','iscontrol','format','Boolean') WriteData(fid,'enum',InversionTypeEnum(),'data',1,'format','Integer') if not self.iscontrol: return WriteData(fid,'object',self,'class','inversion','fieldname','incomplete_adjoint','format','Boolean') WriteData(fid,'object',self,'class','inversion','fieldname','maxsteps','format','Integer') WriteData(fid,'object',self,'class','inversion','fieldname','maxiter','format','Integer') WriteData(fid,'object',self,'class','inversion','fieldname','fatol','format','Double') WriteData(fid,'object',self,'class','inversion','fieldname','frtol','format','Double') WriteData(fid,'object',self,'class','inversion','fieldname','gatol','format','Double') WriteData(fid,'object',self,'class','inversion','fieldname','grtol','format','Double') WriteData(fid,'object',self,'class','inversion','fieldname','gttol','format','Double') WriteData(fid,'object',self,'class','inversion','fieldname','algorithm','format','String') WriteData(fid,'object',self,'class','inversion','fieldname','cost_functions_coefficients','format','DoubleMat','mattype',1) WriteData(fid,'object',self,'class','inversion','fieldname','min_parameters','format','DoubleMat','mattype',3) WriteData(fid,'object',self,'class','inversion','fieldname','max_parameters','format','DoubleMat','mattype',3) WriteData(fid,'object',self,'class','inversion','fieldname','vx_obs','format','DoubleMat','mattype',1,'scale',1./yts) WriteData(fid,'object',self,'class','inversion','fieldname','vy_obs','format','DoubleMat','mattype',1,'scale',1./yts) WriteData(fid,'object',self,'class','inversion','fieldname','vz_obs','format','DoubleMat','mattype',1,'scale',1./yts) WriteData(fid,'object',self,'class','inversion','fieldname','thickness_obs','format','DoubleMat','mattype',1) WriteData(fid,'object',self,'class','inversion','fieldname','surface_obs','format','DoubleMat','mattype',1) #process control parameters num_control_parameters = numpy.numel(self.control_parameters) data = numpy.array([StringToEnum(self.control_parameter[0]) for control_parameter in self.control_parameters]).reshape(1,-1) WriteData(fid,'data',data,'enum',InversionControlParametersEnum(),'format','DoubleMat','mattype',3) WriteData(fid,'data',num_control_parameters,'enum',InversionNumControlParametersEnum(),'format','Integer') #process cost functions num_cost_functions = numpy.size(self.cost_functions,2) data= marshallcostfunctions(self.cost_functions) WriteData(fid,'data',data,'enum',InversionCostFunctionsEnum(),'format','DoubleMat','mattype',3) WriteData(fid,'data',num_cost_functions,'enum',InversionNumCostFunctionsEnum(),'format','Integer')
def mri_window(image_in: np.ndarray, mask: Optional[np.ndarray], output_range: Tuple[float, float] = (-1.0, 1.0), sharpen: float = 1.9, tail: Union[List[float], float] = 1.0, debug_mode: bool = False) -> Tuple[np.array, str]: """ This function takes an MRI Image, removes to first peak of values (air). Then a window range is found centered around the mean of the remaining values and with a range controlled by the standard deviation and the sharpen input parameter. The larger sharpen is, the wider the range. The resulting values are the normalised to the given output_range, with values below and above the range being set the the boundary values. :param image_in: The image to normalize. :param mask: Consider only pixel values of the input image for which the mask is non-zero. If None the whole image is considered. :param output_range: The desired value range of the result image. :param sharpen: number of standard deviation either side of mean to include in the window :param tail: Default 1, allow window range to include more of tail of distribution. :param debug_mode: If true, create diagnostic plots. :return: normalized image """ nchannel = image_in.shape[0] imout = np.zeros_like(image_in) if isinstance(tail, int): tail = float(tail) if isinstance(tail, float): tail = [tail] * nchannel status = "" for ichannel in range(nchannel): if ichannel > 0: status += "Channel {}: ".format(ichannel) # Flatten to apply Otsu_thresholding imflat = image_in[ichannel, ...].flatten() if mask is None: maflat = None in_mask = False else: maflat = mask.flatten() in_mask = mask > 0 # Find Otsu's threshold for the values of the input image threshold = threshold_otsu(imflat) # Find window level level, std_i, _, max_foreground = robust_mean_std( imflat[imflat > threshold]) # If lower value of window is below threshold replace lower value with threshold input_range = (max(level - std_i * sharpen, threshold), min(max_foreground, level + tail[ichannel] * std_i * sharpen)) im_thresh = image_in[ichannel, ...] im_thresh[image_in[ichannel, ...] < threshold] = 0 # Use Polynomial transform function to convert data to output range imout[ichannel, ...] = LinearTransform.transform(im_thresh, input_range, output_range) status += f"Otsu {threshold:0.0f}, level {level:0.0f}, range ({input_range[0]:0.0f}, {input_range[1]:0.0f}) " logging.debug(status) if debug_mode: print('Otsu {}, range {}'.format(threshold, input_range)) if mask is None: no_thresh = np.sum(imflat < threshold) no_high = np.sum(imout == output_range[1]) pc_thresh = no_thresh / np.numel(imflat) * 100 pc_high = no_high / np.numel(imflat) * 100 else: no_thresh = np.sum(imflat[maflat == 1] < threshold) no_high = np.sum(imout == output_range[1]) pc_thresh = no_thresh / np.sum(in_mask) * 100 pc_high = no_high / np.sum(in_mask) * 100 print('Percent of values outside window range: low,high', pc_thresh, pc_high, no_high) with open("channels_trim.txt", 'a') as fileout: fileout.write( "Thresholded: {ich:d}, {pl:4.2f}, {ph:4.2f} \n".format( ich=ichannel, pl=pc_thresh, ph=pc_high)) # Plot input distribution fig, axs = plt.subplots(2, 2, figsize=(9, 9)) axs[0, 0].set_title("Original Image") axs[0, 0].imshow(image_in[ichannel, :, :, 70], cmap='gray') # axs[1,0].hist(image.flatten(), 100) axs[1, 0].set_title("Original Image - Histogram with Mask") if mask is None: axs[1, 0].hist(image_in[ichannel, ...].flatten(), 200) else: axs[1, 0].hist(image_in[ichannel, ...][in_mask].flatten(), 200) axs[0, 1].set_title( "Normalised Image, Level= {level:4.1f},\n " "Window range {in1:4.1f} to {in2:4.1f}, \n" "{pt:4.1f} % below threshold, {ph:4.1f} % above window \n" "Threshold= {th:4.1f}".format(level=level, in1=input_range[0], in2=input_range[1], pt=pc_thresh, ph=pc_high, th=threshold)) axs[0, 1].imshow(imout[ichannel, :, :, 70], cmap='gray') axs[1, 1].set_title("Normalised Image - Histogram with Mask") if mask is None: axs[1, 1].hist(imout[ichannel, ...].flatten(), 200) else: axs[1, 1].hist(imout[ichannel, ...][in_mask].flatten(), 200) plt.show() return imout, status