def GenerateModel(self, pars, nofit=False, separate_source=False, return_resolution=False, broaden=False, model=None):
        """
        This function does the actual work of generating a model with the given parameters,
        fitting the continuum, making sure the model and data are well aligned in
        wavelength, and fitting the detector resolution. In general, it is not meant to be
        called directly by the user. However, the 'nofit' keyword turns this into a wrapper
        to MakeModel.Modeler().MakeModel() with all the appropriate parameters.

        :param pars: A list of the parameters currently being fit (as given in self.FitVariable).
        :param nofit: If true, it will not perform a fit to the data and simply return the model.
        :param separate_source: If true, it will fit the source spectrum as a smoothed version of the residuals.
                                Useful for spectra with broad lines.
        :param return_resolution: If true, it will return the best-fit resolution.
        :param broaden: If true and nofit=True, it will broaden the returned model by the expected detector resolution.
                        Ignored if nofit=False
        :param model: A DataStructures.xypoint instance containing an un-broadened telluric model.
                      If given, it uses this instead of making one.

        :return:  The best-fit telluric model, as a DataStructures.xypoint instance where the x-axis is
                 sampled the same as the data (so you should be able to directly divide the two). If
                 separate_source = True, this method also returns the estimate for the source spectrum *before*
                 the telluric model. If return_resolution is True, it also returns a float with the
                 best resolution fit. The return order is:
                 source_spec, model_spec, resolution
        """
        data = self.data

        #Update self.const_pars to include the new values in fitpars
        #  I know, it's confusing that const_pars holds some non-constant parameters...
        fit_idx = 0
        for i in range(len(self.parnames)):
            if self.fitting[i]:
                #Change from internal to bounded (physical) parameters
                if self.bounds[i][1] < np.inf:
                    self.const_pars[i] = self.bounds[i][0] + (np.sin(pars[fit_idx]*self.normalization[i]) + 1.0) * \
                                                             (self.bounds[i][1] - self.bounds[i][0])/2.0
                else:
                    self.const_pars[i] = self.bounds[i][0] - 1.0 + \
                                         np.sqrt((pars[fit_idx]*self.normalization[i])**2 + 1.0)
                fit_idx += 1
        self.DisplayVariables(fitonly=True)

        #Extract parameters from pars and const_pars. They will have variable
        #  names set from self.parnames
        fit_idx = 0
        for i in range(len(self.parnames)):
            #Assign to local variables by the parameter name
            exec("%s = %g" % (self.parnames[i], self.const_pars[i]))


        wavenum_start = 1e7 / waveend
        wavenum_end = 1e7 / wavestart
        lat = self.observatory["latitude"]
        alt = self.observatory["altitude"]


        #Generate the model:
        if model is None:
            model = self.Modeler.MakeModel(pressure, temperature, wavenum_start, wavenum_end, angle, h2o, co2, o3, n2o, co,
                                           ch4, o2, no, so2, no2, nh3, hno3, lat=lat, alt=alt, wavegrid=None,
                                           resolution=None, vac2air=self.air_wave)

            #Save each model if debugging
            if self.debug and self.debug_level >= 5:
                FittingUtilities.ensure_dir("Models/")
                model_name = "Models/transmission" + "-%.2f" % pressure + "-%.2f" % temperature + "-%.1f" % h2o + "-%.1f" % angle + "-%.2f" % (
                co2) + "-%.2f" % (o3 * 100) + "-%.2f" % ch4 + "-%.2f" % (co * 10)
                np.savetxt(model_name, np.transpose((model.x, model.y)), fmt="%.8f")

            #Interpolate to constant wavelength spacing
            xgrid = np.linspace(model.x[0], model.x[-1], model.x.size)
            model = FittingUtilities.RebinData(model, xgrid)

            #Use nofit if you want a model with reduced resolution. Probably easier
            #  to go through MakeModel directly though...
            if data == None or nofit:
                if broaden:
                    model = FittingUtilities.ReduceResolution(model, resolution)

                # Give units to the output model
                model.x *= u.nm.to(self.xunits)
                return model

        #Make a copy of the model before broadening it
        model_original = model.copy()

        #Reduce to initial guess resolution
        if (resolution - 10 < self.resolution_bounds[0] or resolution + 10 > self.resolution_bounds[1]):
            resolution = np.mean(self.resolution_bounds)
        model = FittingUtilities.ReduceResolution(model, resolution)
        model = FittingUtilities.RebinData(model, data.x)

        #Shift the data (or model) by a constant offset. This gets the wavelength calibration close
        shift = FittingUtilities.CCImprove(data, model, tol=0.1)
        logging.debug("Shifting model by {:.5g} pixels".format((shift)))
        if self.adjust_wave is not "data" and shift != 0:
            data.x += shift
        elif self.adjust_wave == "model" and shift != 0:
            model_original.x -= shift
            # In this case, we need to adjust the resolution again
            model = FittingUtilities.ReduceResolution(model_original.copy(), resolution)
            model = FittingUtilities.RebinData(model, data.x)
        elif shift != 0:
            sys.exit("Error! adjust_wave parameter set to invalid value: %s" % self.adjust_wave)
        self.shift += shift

        resid = data.y / model.y
        nans = np.isnan(resid)
        resid[nans] = data.cont[nans]
        infs = np.isinf(resid)
        resid[infs] = data.cont[infs]

        #As the model gets better, the continuum will be less affected by
        #  telluric lines, and so will get better
        data.cont = FittingUtilities.Continuum(data.x, resid, fitorder=self.continuum_fit_order, lowreject=2,
                                               highreject=3)

        if separate_source or self.fit_source:
            logging.info("Generating Primary star model")
            primary_star = data.copy()
            primary_star.y = resid
            primary_star = self.source_fcn(primary_star, *self.source_args, **self.source_kwargs)
            data.cont *= primary_star.y



        if self.debug and self.debug_level >= 4:
            logging.debug("Saving data and model arrays right before fitting the wavelength")
            logging.debug("  and resolution to Debug_Output1.log")
            np.savetxt("Debug_Output1.log", np.transpose((data.x, data.y, data.cont, model.x, model.y)))


        #Fine-tune the wavelength calibration by fitting the location of several telluric lines
        modelfcn, mean = self.FitWavelengthNew(data, model.copy(), fitorder=self.wavelength_fit_order)

        if self.adjust_wave == "data":
            test = data.x + modelfcn(data.x - mean)
            xdiff = [test[j] - test[j - 1] for j in range(1, len(test) - 1)]
            if min(xdiff) > 0 and np.max(np.abs(test - data.x)) < 0.1 and min(test) > 0:
                logging.info("Adjusting data wavelengths by at most %.8g nm" % np.max(test - model.x))
                data.x = test.copy()
            else:
                logging.warn("Wavelength calibration did not succeed!")
        elif self.adjust_wave == "model":
            test = model_original.x - modelfcn(model_original.x - mean)
            test2 = model.x - modelfcn(model.x - mean)
            xdiff = [test[j] - test[j - 1] for j in range(1, len(test) - 1)]
            if min(xdiff) > 0 and np.max(np.abs(test2 - model.x)) < 0.1 and min(test) > 0 and abs(
                            test[0] - data.x[0]) < 50 and abs(test[-1] - data.x[-1]) < 50:
                logging.info("Adjusting wavelength calibration by at most %.8g nm" % max(test2 - model.x))
                model_original.x = test.copy()
                model.x = test2.copy()
            else:
                logging.warn("Wavelength calibration did not succeed!")

        else:
            sys.exit("Error! adjust_wave set to an invalid value: %s" % self.adjust_wave)

        if self.debug and self.debug_level >= 4:
            logging.debug("Saving data and model arrays after fitting the wavelength")
            logging.debug("  and before the resolution fit to Debug_Output2.log")
            np.savetxt("Debug_Output2.log", np.transpose((data.x, data.y, data.cont, model.x, model.y)))


        #Fit instrumental resolution
        done = False
        while not done:
            done = True
            if 'gauss' in self.resolution_fit_mode.lower() or min(model.y) > 0.95:
                model, resolution = self.FitResolution(data.copy(), model_original.copy(), resolution)
            elif "svd" in self.resolution_fit_mode.lower():
                model, self.broadstuff = self.Broaden2(data.copy(), model_original.copy(), full_output=True)
            else:
                done = False
                print("Resolution fit mode set to an invalid value: %s" % self.resolution_fit_mode)
                self.resolution_fit_mode = raw_input("Enter a valid mode (SVD or guass): ")

        self.data = data
        self.first_iteration = False
        if separate_source:
            if return_resolution:
                return primary_star, model, resolution
            else:
                return primary_star, model
        else:
            #if self.fit_source:
            #  data.cont /= primary_star.y
            if return_resolution:
                return model, resolution
            return model


    # ## -----------------------------------------------
    ### Several functions for refining the wavelength calibration
    ### -----------------------------------------------
dataset/ETHPy150Open kgullikson88/Telluric-Fitter/src/TelluricFitter.py/TelluricFitter.GenerateModel/operator `==` -> `is not`