def sample_flux(fit, data, src, method=calc_energy_flux, correlated=False, num=1, lo=None, hi=None, numcores=None, samples=None): # # The following function should be modified to take advantage of numpy # def within_limits(mysamples, mymins, mymaxs): num_par = mysamples.shape[1] for row in mysamples: for index in xrange(num_par): if row[index] < mymins[index]: row[index] = mymins[index] if row[index] > mymaxs[index]: row[index] = mymaxs[index] return mysamples sampler = NormalParameterSampleFromScaleVector() if correlated: sampler = NormalParameterSampleFromScaleMatrix() # If user entered a covariance matrix but wants to run with # correlated as false then extract the diagonal elements. if correlated == False and samples is not None: if numpy.ndarray == type(samples): samples = samples.diagonal(0) samples = sampler.get_sample(fit, samples, num=num) hardmins = fit.model._get_thawed_par_hardmins() hardmaxs = fit.model._get_thawed_par_hardmaxes() samples = within_limits(samples, hardmins, hardmaxs) return calc_flux(fit, data, src, samples, method, lo, hi, numcores)
def _sample_flux_get_samples(fit, src, correlated, num, clip='hard'): """Return the parameter samples, using fit to define the scales. The covariance method is used to estimate the errors for the parameter sampling. Parameters ---------- fit : sherpa.fit.Fit instance The fit instance. The fit.model expression is assumed to include any necessary response information. The number of free parameters in the model expression is mfree. src : sherpa.models.ArithmeticModel instance The model for which the flux is being calculated. This must be a subset of the fit.model expression, and should not include the response information. There must be at least one thawed parameter in this model. The number of free parameters in src is sfree and must be <= mfree. correlated : bool Are the parameters assumed to be correlated or not? num : int Tne number of samples to return. This must be 1 or greater. clip : {'hard', 'soft', 'none'}, optional What clipping strategy should be applied to the sampled parameters. The default ('hard') is to fix values at their hard limits if they exceed them. A value of 'soft' uses the soft limits instead, and 'none' applies no clipping. The last column in the returned arrays indicates if the row had any clipped parameters (even when clip is set to 'none'). Returns ------- samples, clipped : 2D NumPy array, 1D NumPy array The dimensions are num by mfree. The ordering of the parameter values in each row matches that of the free parameters in fit.model. The clipped array indicates whether a row had one or more clipped parameters. Notes ----- The support for src being a subset of the fit.model argument has not been tested for complex models, that is when fit.model is rmf(arf(source_model)) and src is a combination of components in source_model but not all the components of source_model. """ npar = len(src.thawedpars) mpar = len(fit.model.thawedpars) assert mpar >= npar if correlated: sampler = NormalParameterSampleFromScaleMatrix() else: sampler = NormalParameterSampleFromScaleVector() samples = sampler.get_sample(fit, num=num) clipped = sampler.clip(fit, samples, clip=clip) return samples, clipped
def _sample_flux_get_samples(fit, src, correlated, num): """Return the parameter samples, using fit to define the scales. The covariance method is used to estimate the errors for the parameter sampling. Parameters ---------- fit : sherpa.fit.Fit instance The fit instance. The fit.model expression is assumed to include any necessary response information. The number of free parameters in the model expression is mfree. src : sherpa.models.ArithmeticModel instance The model for which the flux is being calculated. This must be a subset of the fit.model expression, and should not include the response information. There must be at least one thawed parameter in this model. The number of free parameters in src is sfree and must be <= mfree. correlated : bool Are the parameters assumed to be correlated or not? num : int Tne number of samples to return. This must be 1 or greater. Returns ------- samples : 2D NumPy array The dimensions are num by mfree. The ordering of the parameter values in each row matches that of the free parameters in fit.model. Notes ----- The support for src being a subset of the fit.model argument has not been tested for complex models, that is when fit.model is rmf(arf(source_model)) and src is a combination of components in source_model but not all the components of source_model. """ npar = len(src.thawedpars) mpar = len(fit.model.thawedpars) assert mpar >= npar if correlated: sampler = NormalParameterSampleFromScaleMatrix() else: sampler = NormalParameterSampleFromScaleVector() return sampler.get_sample(fit, num=num)
def _sample_flux_get_samples_with_scales(fit, src, correlated, scales, num, clip='hard'): """Return the parameter samples given the parameter scales. Parameters ---------- fit : sherpa.fit.Fit instance The fit instance. The fit.model expression is assumed to include any necessary response information. The number of free parameters in fit.model is mfree. src : sherpa.models.ArithmeticModel instance The model for which the flux is being calculated. This must be a subset of the fit.model expression, and should not include the response information. There must be at least one thawed parameter in this model. The number of free parameters in src is sfree. correlated : bool Are the parameters assumed to be correlated or not? If correlated is True then scales must be 2D. scales : 1D or 2D array The parameter scales. When 1D they are the gaussian sigma values for the parameter, and when a 2D array they are the covariance matrix. The scales parameter must match the number of parameters in fit (mfree) and not in src (sfree) when they are different. For 1D the size is mfree and for 2D it is mfree by mfree. num : int Tne number of samples to return. This must be 1 or greater. clip : {'hard', 'soft', 'none'}, optional What clipping strategy should be applied to the sampled parameters. The default ('hard') is to fix values at their hard limits if they exceed them. A value of 'soft' uses the soft limits instead, and 'none' applies no clipping. The last column in the returned arrays indicates if the row had any clipped parameters (even when clip is set to 'none'). Returns ------- samples, clipped : 2D NumPy array, 1D NumPy array The dimensions are num by mfree. The ordering of the parameter values in each row matches that of the free parameters in fit.model. The clipped array indicates whether a row had one or more clipped parameters. Raises ------ ArgumentErr If the scales argument contains invalid (e.g. None or IEEE non-finite values) values, or is the wrong shape. ModelErr If the scales argument has the wrong size (that is, it does not represent mfree parameter values). Notes ----- The support for src being a subset of the fit.model argument has not been tested for complex models, that is when fit.model is rmf(arf(source_model)) and src is a combination of components in source_model but not all the components of source_model. """ npar = len(src.thawedpars) mpar = len(fit.model.thawedpars) assert mpar >= npar scales = numpy.asarray(scales) # A None value will cause scales to have a dtype of object, # which is not supported by isfinite, so check for this # first. # # Numpy circa 1.11 raises a FutureWarning with 'if None in scales:' # about this changing to element-wise comparison (which is what # we want). To avoid this warning I use the suggestion from # https://github.com/numpy/numpy/issues/1608#issuecomment-9618150 # if numpy.equal(None, scales).any(): raise ArgumentErr('bad', 'scales', 'must not contain None values') # We require that scales only has finite values in it. # The underlying sample routines are assumed to check other # constraints, or deal with negative values (for the 1D case # uncorrelated case the absolute value is used). # if not numpy.isfinite(scales).all(): raise ArgumentErr('bad', 'scales', 'must only contain finite values') if scales.ndim == 2 and (scales.shape[0] != scales.shape[1]): raise ArgumentErr('bad', 'scales', 'scales must be square when 2D') # Ensure the scales array matches the correlated parameter: # - when True it must be the covariance matrix (2D) # - when False it can be either be a 1D array of sigmas or # the covariance matrix, which we convert to an array of # sigmas # if correlated: if scales.ndim != 2: raise ArgumentErr('bad', 'scales', 'when correlated=True, scales must be 2D') elif scales.ndim == 2: # convert from covariance matrix scales = numpy.sqrt(scales.diagonal()) elif scales.ndim != 1: raise ArgumentErr('bad', 'scales', 'when correlated=False, scales must be 1D or 2D') # At this point either 1D or 2D square array. Now to check the # number of elements. # if scales.shape[0] != mpar: raise ModelErr('numthawed', mpar, scales.shape[0]) if correlated: sampler = NormalParameterSampleFromScaleMatrix() else: sampler = NormalParameterSampleFromScaleVector() samples = sampler.get_sample(fit, scales, num=num) clipped = sampler.clip(fit, samples, clip=clip) return samples, clipped