def saveState(self, fn=None, clobber=False): """ Save the state of the fitting object. This method collects the parameter values, the applied restrictions, and the information whether parameters are free or frozen and saves them to the specified file (if given) using pickle. The saved state can be restored using the `restoreState` method. .. note:: Unfortunately, "relations" cannot be saved. Parameters ---------- fn : string, optional The filename to which the state shall be written. If None, the output will not be written to a file. clobber : boolean, optional If True, existing files will be overwritten (default is False). Returns ------- Saved data : dict The dictionary containing the data saved to the file. """ dat = {} dat["parameters"] = self.parameters() dat["restrictions"] = self.getRestrictions() dat["frozenParameters"] = self.frozenParameters() if isinstance(fn, six.string_types): if os.path.isfile(fn) and (not clobber): raise(PE.PyANameClash("The file '"+fn+"' exists.", where="saveState", \ solution="Change filename or set clobber to True.")) pickle.dump(dat, open(fn, 'wb')) return dat
def addPassband(self, name, wvl, trans, snc=False): """ Add a new passband to the inventory. Parameters ---------- name : string The name of the passband. wvl : array Wavelength in A. trans : array Transmission of the passband. snc : boolean, optional A `Skip Name Check` flag. If False (default), an exception is raised if the passband name is already present in the inventory of passbands. Otherwise the old passband is replaced by the new specification. """ if not snc: if name in self.bands: raise (PE.PyANameClash( "A passband with name '" + str(name) + "' is already present.", solution=[ "Change the name.", "Use `snc=True` to ignore and overwrite old passband." ])) self.bands[name] = np.vstack((wvl, trans)).transpose()
def __add__(self, right): """ This member allows to combine the properties of two Param class \ instances. All parameter properties will be copied into the new \ Parameter class instance, which is returned by this function. .. caution:: All parameter names must be unique! """ paLeft = self.parameters() paRight = right.parameters() # Check whether parameters have unique names for p in paLeft: if p in paRight: raise (PE.PyANameClash( "At least two parameters share the same name.", where="Params::__add__")) # List of new names nlist = list(paLeft.keys()) nlist.extend(paRight.keys()) # Create new parameter objects result = Params(nlist) # Combine properties result.paramNum = self.paramNum.copy() pn = len(result.paramNum) for i in smo.range(len(right.paramNum)): result.paramNum[pn + i] = right.paramNum[i] result.isFree = self.isFree.copy() result.isFree.update(right.isFree) result.isRestricted = self.isRestricted.copy() result.isRestricted.update(right.isRestricted) result.restrictions = self.restrictions.copy() result.restrictions.update(right.restrictions) result.relations = self.relations.copy() result.relations.update(right.relations) result.conditionalRestrictions = self.conditionalRestrictions.copy() result.conditionalRestrictions.update(right.conditionalRestrictions) result.assignValue(self.parameters()) result.assignValue(right.parameters()) return result
def load(self, fn, constClobber=False): """ Load constants file. Parameters ---------- fn : string The file name. constClobber : boolean, optional If True, existing constants will be overwritten. """ config = _ConfigParser.RawConfigParser() config.read(fn) for s in config.sections(): nc = None try: nc = {} nc["symbol"] = config.get(s, "symbol") nc["descr"] = config.get(s, "descr") nc["valueSI"] = config.get(s, "valueSI") nc["errSI"] = config.get(s, "errSI") nc["units"] = {} for u in _systems: nc["units"][u] = config.get(s, "unit" + u) nc["source"] = config.get(s, "source") except _ConfigParser.NoOptionError as e: _PE.warn(_PE.PyAValError("The definition of the constant defined in section '" + s + "' of file '" + \ fn + "' is incomplete. Ignoring this constant. Caught the error:\n" + \ str(e))) nc = None if nc is not None: if (nc["symbol"] in self.inventory) and (not constClobber): raise(_PE.PyANameClash("A constant with the symbol '" + nc["symbol"] + "' is already defined.", \ solution=["Choose another symbol.", "Set the `constClobber` flag to True to overwrite existing definitions of constants."])) self.inventory[nc["symbol"]] = nc self._inventoryToScope()
def turnIntoRebin(CO): """ Turn a "normal" fitting object into rebinning fitting object. This function accepts a class object representing a model and returns another class object extended by the rebinning functionality. Parameters ---------- CO : A class object The class object describing the model to use rebinning. Returns ------- Rebinned model : Fitting object Another class object extended by the rebinning functionality. """ # Check for evaluate if not hasattr(CO, "evaluate"): raise(PE.PyANotImplemented("The class object has no evaluate method. Is it really a model?", where="turnIntoRebin")) # Check for other properties and methods for p in ["setRebinArray_Ndt", "rebinTimes", "rebinIdent"]: if hasattr(CO, p): PE.warn(PE.PyANameClash("Class object already has attribute: `" + p + "`. Potentially harmful..", solution="Check class object, maybe rename attribute", where="turnIntoRebin")) class _ModelRebin(CO): """ Base class providing rebinning functionality. The model is evaluated at more points than actually needed. Several points are than averaged to obtain a "binned" model, which can, for example, account for finite integration times in observations. Attributes ---------- rebinTimes : array Defined the abscissa values at which to evaluate the model to be rebinned afterwards. rebinIdent : dict A dictionary associating bin number (in the unbinned model) with a list holding the bins in `rebinTimes`, which are to be averaged to obtain the binned model. """ def __init__(self, *args, **kwargs): CO.__init__(self, *args, **kwargs) self.rebinTimes = None self.rebinIdent = None def setRebinArray_Ndt(self, time, N, dt): """ Defines the overbinning parameters (`rebinTimes`, `rebinIdent`). It is assumed that the time points given in the `time` array refer to the center of the time bins and every bin has length `dt`. The bins are then subdivided into `N` subintervals; the center of each such subinterval becomes a point in the overbinned time axis (`rebinTimes`). Parameters ---------- time : array The time axis of the "observed" (not overbinned) transit light-curve. N : int The number of point into which to subdivide each time bin of length `dt`. dt : float The length of each time bin (on the original not oversampled time axis). """ self.rebinTimes = numpy.zeros(time.size * N) self.rebinIdent = {} for i in smo.range(time.size): self.rebinTimes[i * N:(i + 1) * N] = \ (time[i] - dt / 2.0) + (numpy.arange(N) * dt) / \ float(N) + dt / float(N) / 2.0 self.rebinIdent[i] = list(range(i * N, (i + 1) * N)) def evaluate(self, x): """ Calculate the model. Parameters ---------- x : array The abscissa values. Returns ------- model : array, The binned model. Notes ----- This function calculates the model at those time points specified by the `rebinTimes` property and saves the result in the class property `unbinnedModel`. Then it bins according to the definitions in `rebinIdent` and save the resulting model in the `binnedModel` property. """ if (self.rebinTimes is None) or (self.rebinIdent is None): raise(PE.PyAValError("Rebinning parameters (properties rebinTimes and/or rebinIdent) not appropriately defined.", solution=["Use setRebinArray_Ndt method.", "Define the properties by accessing them directly."])) # Calculate the model using current parameters at the time points # defined in the `rebinTimes` array self.unbinnedModel = CO.evaluate(self, self.rebinTimes) # Build up rebinned model self.binnedModel = numpy.zeros(x.size) for i in smo.range(x.size): self.binnedModel[i] = numpy.mean( self.unbinnedModel[self.rebinIdent[i]]) # Return the resulting model return self.binnedModel return _ModelRebin