diff --git a/config/auxtel.ini b/config/auxtel.ini index ea488c2f4..f504aa97a 100644 --- a/config/auxtel.ini +++ b/config/auxtel.ini @@ -20,7 +20,9 @@ SPECTRACTOR_FIT_TIMEOUT_PER_ITER = 1200 # maximum time per gradient descent before TimeoutError in seconds SPECTRACTOR_FIT_TIMEOUT = 7200 # library to compute atmospheric transmission: none, libradtran, getobsatmo -SPECTRACTOR_ATMOSPHERE_SIM = getobstamo +SPECTRACTOR_ATMOSPHERE_SIM = getobsatmo +# simulate star field with Gaia catalog: False, True +SPECTRACTOR_SIMULATE_STARFIELD = False [instrument] # instrument name @@ -55,7 +57,7 @@ CCD_PIXEL2ARCSEC = 0.0952 # approximate maximum ADU output of the CCD CCD_MAXADU = 170000 # electronic gain : elec/ADU -CCD_GAIN = 1.1 +CCD_GAIN = 1.3 # rebinning of the image in pixel CCD_REBIN = 2 diff --git a/config/ctio.ini b/config/ctio.ini index 46aa69201..98ba7bd59 100644 --- a/config/ctio.ini +++ b/config/ctio.ini @@ -17,6 +17,8 @@ SPECTRACTOR_DECONVOLUTION_PSF2D = True SPECTRACTOR_DECONVOLUTION_FFM = True # library to compute atmospheric transmission: none, libradtran, getobsatmo SPECTRACTOR_ATMOSPHERE_SIM = none +# simulate star field with Gaia catalog: False, True +SPECTRACTOR_SIMULATE_STARFIELD = True [instrument] # instrument name @@ -102,7 +104,7 @@ PIXWIDTH_BOXSIZE = 40 # the PSF model: Gauss, Moffat or MoffatGauss PSF_TYPE = Moffat # the order of the polynomials to model wavelength dependence of the PSF shape parameters -PSF_POLY_ORDER = 4 +PSF_POLY_ORDER = 2 # regularisation parameter for the chisq minimisation to extract the spectrum PSF_FIT_REG_PARAM = 0.04 # step size in pixels for the first transverse PSF1D fit diff --git a/config/default.ini b/config/default.ini index b79e9bb23..6db0988f9 100644 --- a/config/default.ini +++ b/config/default.ini @@ -21,6 +21,8 @@ SPECTRACTOR_FIT_TIMEOUT_PER_ITER = 600 SPECTRACTOR_FIT_TIMEOUT = 3600 # library to compute atmospheric transmission: none, libradtran, getobsatmo SPECTRACTOR_ATMOSPHERE_SIM = none +# simulate star field with Gaia catalog: False, True +SPECTRACTOR_SIMULATE_STARFIELD = False [instrument] # instrument name @@ -119,6 +121,8 @@ PSF_TYPE = Moffat PSF_POLY_ORDER = 2 # regularisation parameter for the chisq minimisation to extract the spectrum PSF_FIT_REG_PARAM = 0.01 +# polynomial type: must be polynomial or legendre +PSF_POLY_TYPE = "polynomial" [detection line algorithm parameters] # order of the background polynome to fit diff --git a/config/stardice.ini b/config/stardice.ini index d3864c1b6..0c62378a2 100644 --- a/config/stardice.ini +++ b/config/stardice.ini @@ -6,7 +6,7 @@ THROUGHPUT_DIR = simulation/StarDiceThroughput/ [pipeline] # method to get target centroid, choose among: guess, fit, WCS -SPECTRACTOR_FIT_TARGET_CENTROID = WCS +SPECTRACTOR_FIT_TARGET_CENTROID = fit # method to get image rotation angle: False, disperser, hessian SPECTRACTOR_COMPUTE_ROTATION_ANGLE = disperser # parameter to prevent from background subtraction @@ -19,6 +19,8 @@ SPECTRACTOR_DECONVOLUTION_FFM = True SPECTRACTOR_DECONVOLUTION_SIGMA_CLIP = 100 # library to compute atmospheric transmission: none, libradtran, getobsatmo SPECTRACTOR_ATMOSPHERE_SIM = getobsatmo +# simulate star field with Gaia catalog: False, True +SPECTRACTOR_SIMULATE_STARFIELD = False [instrument] # instrument name @@ -88,7 +90,7 @@ ROT_ANGLE_MAX = 30 [spectrum range] # minimum wavelength for spectrum extraction (in nm) -LAMBDA_MIN = 350 +LAMBDA_MIN = 330 # maximum wavelength for spectrum extraction (in nm) LAMBDA_MAX = 1000 # spectrum order to extract @@ -96,7 +98,7 @@ SPEC_ORDER = 1 [background subtraction parameters] # half transverse width of the signal rectangular window in pixels -PIXWIDTH_SIGNAL = 10 +PIXWIDTH_SIGNAL = 20 # distance from dispersion axis to analyse the background in pixels PIXDIST_BACKGROUND = 20 # transverse width of the background rectangular window in pixels @@ -108,9 +110,9 @@ PIXWIDTH_BOXSIZE = 40 # the PSF model: Gauss, Moffat or MoffatGauss PSF_TYPE = Moffat # the order of the polynomials to model wavelength dependence of the PSF shape parameters -PSF_POLY_ORDER = 4 +PSF_POLY_ORDER = 2 # regularisation parameter for the chisq minimisation to extract the spectrum -PSF_FIT_REG_PARAM = 0.1 +PSF_FIT_REG_PARAM = 1 # step size in pixels for the first transverse PSF1D fit PSF_PIXEL_STEP_TRANSVERSE_FIT = 1 # PSF is not evaluated outside a region larger than max(PIXWIDTH_SIGNAL, PSF_FWHM_CLIP*fwhm) pixels diff --git a/runAstrometry.py b/runAstrometry.py index b0255433b..e40110211 100644 --- a/runAstrometry.py +++ b/runAstrometry.py @@ -2,6 +2,7 @@ from spectractor.astrometry import Astrometry from spectractor.logbook import LogBook from spectractor.config import load_config, apply_rebinning_to_parameters +from spectractor.extractor.images import Image if __name__ == "__main__": @@ -50,7 +51,6 @@ logbook = LogBook(logbook=args.logbook) for file_name in file_names: - disperser_label = args.disperser_label if parameters.OBS_NAME == "CTIO": tag = file_name.split('/')[-1] tag = tag.replace('sim_', 'reduc_') @@ -66,8 +66,8 @@ ypos = float(ypos) guess = [xpos, ypos] target_label = args.target_label - a = Astrometry(file_name, target_label=target_label, disperser_label=disperser_label, - output_directory=args.output_directory) + image = Image(file_name, config=args.config) + a = Astrometry(image, output_directory=args.output_directory) extent = ((int(max(0, xpos - radius)), int(min(xpos + radius, parameters.CCD_IMSIZE))), (int(max(0, ypos - radius)), int(min(ypos + radius, parameters.CCD_IMSIZE)))) gaia_min_residuals = a.run_full_astrometry(extent=extent, maxiter=int(args.maxiter)) diff --git a/runImageSim.py b/runImageSim.py index 141211765..b69d65e96 100644 --- a/runImageSim.py +++ b/runImageSim.py @@ -49,4 +49,4 @@ continue image = ImageSim(file_name, spectrum_file_name, args.output_directory, A2=1, - psf_poly_params=psf_poly_params, with_stars=False) + psf_poly_params=psf_poly_params, with_starfield=False) diff --git a/runSimulator.py b/runSimulator.py index e5e7e9ca4..7fc4f204f 100644 --- a/runSimulator.py +++ b/runSimulator.py @@ -43,6 +43,6 @@ atmgrid = AtmosphereGrid(file_name) image = ImageSim(file_name, spectrum_file_name, args.output_directory, A1=1, A2=1, pwv=5, ozone=300, aerosols=0.03, - psf_poly_params=None, with_stars=True) + psf_poly_params=None, with_starfield=True) sim_file_name = args.output_directory + tag.replace('reduc_', 'sim_') Spectractor(sim_file_name, args.output_directory, target, [xpos, ypos], disperser_label, args.config) diff --git a/spectractor/_version.py b/spectractor/_version.py index dd4fc07ae..2ccb07c61 100644 --- a/spectractor/_version.py +++ b/spectractor/_version.py @@ -28,5 +28,5 @@ # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -__version__ = '3.0.3' +__version__ = '3.1.0' __version_info__ = tuple(map(int, __version__.split('.'))) diff --git a/spectractor/config.py b/spectractor/config.py index 4cba851da..e25984b7a 100644 --- a/spectractor/config.py +++ b/spectractor/config.py @@ -116,6 +116,10 @@ def load_config(config_filename, rebin=True): if parameters.PIXWIDTH_BOXSIZE > parameters.PIXWIDTH_BACKGROUND: raise ValueError(f'parameters.PIXWIDTH_BOXSIZE must be smaller than parameters.PIXWIDTH_BACKGROUND (or equal).') + # check consistency + if parameters.PSF_POLY_TYPE not in ["polynomial", "legendre"]: + raise ValueError(f'parameters.PSF_POLY_TYPE must be either "polynomial" or "legendre". Got {parameters.PSF_POLY_TYPE=}') + # check presence of atmospheric simulation packages if parameters.SPECTRACTOR_ATMOSPHERE_SIM.lower() not in ["none", "libradtran", "getobsatmo"]: raise ValueError(f'parameters.SPECTRACTOR_ATMOSPHERE_SIM must be either ["none", "libradtran", "getobsatmo"]. ' diff --git a/spectractor/extractor/background.py b/spectractor/extractor/background.py index 3647433fa..4fa382998 100644 --- a/spectractor/extractor/background.py +++ b/spectractor/extractor/background.py @@ -54,7 +54,7 @@ def make_source_mask(data, nsigma, npixels, mask=None, sigclip_sigma=3.0, Parameters ---------- - data : 2D `~numpy.ndarray` + data : np.ndarray The 2D array of the image. nsigma : float The number of standard deviations per pixel above the ``background`` @@ -236,7 +236,7 @@ def extract_spectrogram_background_sextractor(data, err, ws=(20, 30), mask_signa >>> from spectractor import parameters >>> parameters.DEBUG = True >>> psf = MoffatGauss() - >>> s0 = ChromaticPSF(psf, Nx=100, Ny=200, saturation=1000) + >>> s0 = ChromaticPSF(psf, Nx=100, Ny=300, saturation=1000) >>> params = s0.generate_test_poly_params() >>> saturation = params[-1] >>> data = s0.evaluate(s0.set_pixels(mode="1D"), poly_params=params) diff --git a/spectractor/extractor/chromaticpsf.py b/spectractor/extractor/chromaticpsf.py index 8aea658c2..7450806de 100644 --- a/spectractor/extractor/chromaticpsf.py +++ b/spectractor/extractor/chromaticpsf.py @@ -224,7 +224,7 @@ def generate_test_poly_params(self): .. doctest:: :hide: - >>> assert(np.all(np.isclose(params,[10, 50, 100, 150, 200, 0, 0, 0, 0, 5, 0, 2, 0, -0.4, -0.4,1,0,20000]))) + >>> assert(np.all(np.isclose(params,[10, 50, 100, 150, 200, 0, 0, 0, 0, 5, 0, 2, 0, -0.4, 0, 1, 0, 20000]))) """ if not isinstance(self.psf, MoffatGauss) and not isinstance(self.psf, Moffat): @@ -241,7 +241,7 @@ def generate_test_poly_params(self): params += [0.] * (self.degrees['gamma'] - 1) + [0, 5] # gamma params += [0.] * (self.degrees['alpha'] - 1) + [0, 2] # alpha if isinstance(self.psf, MoffatGauss): - params += [0.] * (self.degrees['eta_gauss'] - 1) + [-0.4, -0.4] # eta_gauss + params += [0.] * (self.degrees['eta_gauss'] - 1) + [0, -0.4] # eta_gauss params += [0.] * (self.degrees['stddev'] - 1) + [0, 1] # stddev params += [self.saturation] # saturation poly_params = np.zeros_like(params) @@ -252,7 +252,12 @@ def generate_test_poly_params(self): continue else: shift = self.degrees[name] + 1 - c = np.polynomial.legendre.poly2leg(params[index + shift:index:-1]) + if parameters.PSF_POLY_TYPE == "legendre": + c = np.polynomial.legendre.poly2leg(params[index + shift:index:-1]) + elif parameters.PSF_POLY_TYPE == "polynomial": + c = np.asarray(params[index + shift:index:-1]) + else: + raise ValueError(f"Unknown polynomial type {parameters.PSF_POLY_TYPE=}.") coeffs = np.zeros(shift) coeffs[:c.size] = c poly_params[index + 1:index + shift + 1] = coeffs @@ -613,7 +618,7 @@ def convolve_psf_cube_masked(psf_cube_masked): return psf_cube_masked @staticmethod - def get_boundaries(psf_cube_masked): + def set_rectangular_boundaries(psf_cube_masked): """Compute the ChromaticPSF computation boundaries, as a dictionnary of integers giving the `"xmin"`, `"xmax"`, `"ymin"` and `"ymax"` edges where to compute the PSF for each wavelength. True regions are rectangular after this operation. The `psf_cube_masked` cube is updated accordingly and returned. @@ -639,7 +644,7 @@ def get_boundaries(psf_cube_masked): >>> profile_params[:, 1] = np.arange(s.Nx) >>> psf_cube_masked = s.build_psf_cube_masked(s.set_pixels(mode="2D"), profile_params) >>> psf_cube_masked = s.convolve_psf_cube_masked(psf_cube_masked) - >>> boundaries, psf_cube_masked = s.get_boundaries(psf_cube_masked) + >>> boundaries, psf_cube_masked = s.set_rectangular_boundaries(psf_cube_masked) >>> boundaries["xmin"].shape (100,) >>> psf_cube_masked.shape @@ -678,14 +683,13 @@ def get_boundaries(psf_cube_masked): psf_cube_masked[k, ymin:ymax, xmin:xmax] = True return boundaries, psf_cube_masked - @staticmethod - def get_sparse_indices(psf_cube_masked): - """Methods that returns the indices to build sparse matrices from `psf_cube_masked`. + def get_sparse_indices(self, boundaries): + """Methods that returns the indices to build sparse matrices from rectangular `boundaries`. Parameters ---------- - psf_cube_masked: np.ndarray - Cube of boolean values where `psf_cube` cube is positive, eventually convolved. + boundaries: dict + The dictionnary of PSF edges per wavelength. Returns ------- @@ -702,14 +706,20 @@ def get_sparse_indices(psf_cube_masked): >>> profile_params[:, 1] = np.arange(s.Nx) >>> psf_cube_masked = s.build_psf_cube_masked(s.set_pixels(mode="2D"), profile_params) >>> psf_cube_masked = s.convolve_psf_cube_masked(psf_cube_masked) - >>> psf_cube_sparse_indices, M_sparse_indices = s.get_sparse_indices(psf_cube_masked) - >>> M_sparse_indices.shape - (72000,) - >>> len(psf_cube_sparse_indices) - 100 + >>> boundaries, psf_cube_masked = s.set_rectangular_boundaries(psf_cube_masked) + >>> psf_cube_sparse_indices, M_sparse_indices = s.get_sparse_indices(boundaries) + >>> assert M_sparse_indices.shape == np.sum(psf_cube_masked) + >>> assert len(psf_cube_sparse_indices) == s.Nx """ - wl_size = psf_cube_masked.shape[0] - psf_cube_sparse_indices = [np.where(psf_cube_masked[k].ravel() > 0)[0] for k in range(wl_size)] + wl_size = self.Nx # assuming that the number of cube layers is the number of pixel columns + psf_cube_sparse_indices = [] + for k in range(wl_size): + xmin, xmax = boundaries["xmin"][k], boundaries["xmax"][k] + if xmin == -1: + psf_cube_sparse_indices.append([]) + else: + ymin, ymax = boundaries["ymin"][k], boundaries["ymax"][k] + psf_cube_sparse_indices.append(np.concatenate([np.arange(xmin,xmax) + k * wl_size for k in range(ymin, ymax)])) M_sparse_indices = np.concatenate(psf_cube_sparse_indices) return psf_cube_sparse_indices, M_sparse_indices @@ -751,8 +761,8 @@ def build_sparse_M(self, pixels, profile_params, M_sparse_indices, boundaries, d >>> psf_cube_masked = s.build_psf_cube_masked(s.set_pixels(mode="2D"), profile_params) >>> psf_cube_masked = s.convolve_psf_cube_masked(psf_cube_masked) - >>> boundaries, psf_cube_masked = s.get_boundaries(psf_cube_masked) - >>> psf_cube_sparse_indices, M_sparse_indices = s.get_sparse_indices(psf_cube_masked) + >>> boundaries, psf_cube_masked = s.set_rectangular_boundaries(psf_cube_masked) + >>> psf_cube_sparse_indices, M_sparse_indices = s.get_sparse_indices(boundaries) >>> M = s.build_sparse_M(s.set_pixels(mode="2D"), profile_params, M_sparse_indices, boundaries, dtype="float32") >>> M.shape (2000, 100) @@ -770,8 +780,8 @@ def build_sparse_M(self, pixels, profile_params, M_sparse_indices, boundaries, d >>> psf_cube_masked = s.build_psf_cube_masked(s.set_pixels(mode="1D"), profile_params) >>> psf_cube_masked = s.convolve_psf_cube_masked(psf_cube_masked) - >>> boundaries, psf_cube_masked = s.get_boundaries(psf_cube_masked) - >>> psf_cube_sparse_indices, M_sparse_indices = s.get_sparse_indices(psf_cube_masked) + >>> boundaries, psf_cube_masked = s.set_rectangular_boundaries(psf_cube_masked) + >>> psf_cube_sparse_indices, M_sparse_indices = s.get_sparse_indices(boundaries) >>> M = s.build_sparse_M(s.set_pixels(mode="1D"), profile_params, M_sparse_indices, boundaries, dtype="float32") >>> M.shape (2000, 100) @@ -849,8 +859,8 @@ def build_psf_jacobian(self, pixels, profile_params, psf_cube_sparse_indices, bo >>> profile_params[:, 1] = np.arange(s.Nx) # PSF x_c positions >>> psf_cube_masked = s.build_psf_cube_masked(s.set_pixels(mode="2D"), profile_params) >>> psf_cube_masked = s.convolve_psf_cube_masked(psf_cube_masked) - >>> boundaries, psf_cube_masked = s.get_boundaries(psf_cube_masked) - >>> psf_cube_sparse_indices, M_sparse_indices = s.get_sparse_indices(psf_cube_masked) + >>> boundaries, psf_cube_masked = s.set_rectangular_boundaries(psf_cube_masked) + >>> psf_cube_sparse_indices, M_sparse_indices = s.get_sparse_indices(boundaries) >>> s.params.fixed[s.Nx:s.Nx+s.deg+1] = [True] * (s.deg+1) # fix all x_c parameters >>> J = s.build_psf_jacobian(s.set_pixels(mode="2D"), profile_params, psf_cube_sparse_indices, boundaries, dtype="float32") >>> J.shape @@ -879,8 +889,8 @@ def build_psf_jacobian(self, pixels, profile_params, psf_cube_sparse_indices, bo if Nx != profile_params.shape[0]: raise ValueError(f"Number of pixels along x axis must be same as profile_params table length. " f"Got {Nx=} and {profile_params.shape}.") - leg_pixels = np.linspace(-1, 1, Nx) - legs = np.zeros((self.n_poly_params-Nx, Nx), dtype=dtype) + poly_x = np.linspace(-1, 1, Nx) + polys = np.zeros((self.n_poly_params-Nx, Nx), dtype=dtype) ip = 0 repeats = [] for ipsf, label in enumerate(self.psf.params.labels): @@ -889,7 +899,10 @@ def build_psf_jacobian(self, pixels, profile_params, psf_cube_sparse_indices, bo repeats.append(nparams) for k in range(nparams): coeffs = np.eye(1, nparams, k)[0] - legs[ip] = np.polynomial.legendre.legval(leg_pixels, coeffs).astype(dtype) + if parameters.PSF_POLY_TYPE == "legendre": + polys[ip] = np.polynomial.legendre.legval(poly_x, coeffs).astype(dtype) + elif parameters.PSF_POLY_TYPE == "polynomial": + polys[ip] = np.polynomial.polynomial.polyval(poly_x, coeffs).astype(dtype) ip += 1 for ip, label in enumerate(self.psf.params.labels): if "amplitude" in label: # skip computation of ChromaticPSF jacobian for amplitude parameters @@ -905,7 +918,7 @@ def build_psf_jacobian(self, pixels, profile_params, psf_cube_sparse_indices, bo else: Jpsf = self.psf.jacobian(pixels[boundaries["ymin"][x]:boundaries["ymax"][x]], profile_params[x, :], analytical=True) - J[:, psf_cube_sparse_indices[x]] += np.repeat(Jpsf[1:], repeats, axis=0) * legs[:, x, None] # Jpsf[1:] excludes amplitude + J[:, psf_cube_sparse_indices[x]] += np.repeat(Jpsf[1:], repeats, axis=0) * polys[:, x, None] # Jpsf[1:] excludes amplitude return J def build_sparse_dM(self, pixels, profile_params, M_sparse_indices, boundaries, dtype="float32"): @@ -940,8 +953,8 @@ def build_sparse_dM(self, pixels, profile_params, M_sparse_indices, boundaries, >>> profile_params[:, 1] = np.arange(s.Nx) # PSF x_c positions >>> psf_cube_masked = s.build_psf_cube_masked(s.set_pixels(mode="2D"), profile_params) >>> psf_cube_masked = s.convolve_psf_cube_masked(psf_cube_masked) - >>> boundaries, psf_cube_masked = s.get_boundaries(psf_cube_masked) - >>> psf_cube_sparse_indices, M_sparse_indices = s.get_sparse_indices(psf_cube_masked) + >>> boundaries, psf_cube_masked = s.set_rectangular_boundaries(psf_cube_masked) + >>> psf_cube_sparse_indices, M_sparse_indices = s.get_sparse_indices(boundaries) >>> s.params.fixed[s.Nx:s.Nx+s.deg+1] = [True] * (s.deg+1) # fix all x_c parameters >>> dM = s.build_sparse_dM(s.set_pixels(mode="2D"), profile_params, M_sparse_indices, boundaries, dtype="float32") >>> len(dM), dM[0].shape @@ -971,8 +984,8 @@ def build_sparse_dM(self, pixels, profile_params, M_sparse_indices, boundaries, if Nx != profile_params.shape[0]: raise ValueError(f"Number of pixels along x axis must be same as profile_params table length. " f"Got {Nx=} and {profile_params.shape}.") - leg_pixels = np.linspace(-1, 1, Nx) - legs = np.zeros((self.n_poly_params-Nx, Nx), dtype=dtype) + poly_x = np.linspace(-1, 1, Nx) + polys = np.zeros((self.n_poly_params-Nx, Nx), dtype=dtype) ip = 0 repeats = [] for ipsf, label in enumerate(self.psf.params.labels): @@ -982,7 +995,10 @@ def build_sparse_dM(self, pixels, profile_params, M_sparse_indices, boundaries, for k in range(nparams): # psf_index.append(ipsf) coeffs = np.eye(1, nparams, k)[0] - legs[ip] = np.polynomial.legendre.legval(leg_pixels, coeffs).astype(dtype) + if parameters.PSF_POLY_TYPE == "legendre": + polys[ip] = np.polynomial.legendre.legval(poly_x, coeffs).astype(dtype) + elif parameters.PSF_POLY_TYPE == "polynomial": + polys[ip] = np.polynomial.polynomial.polyval(poly_x, coeffs).astype(dtype) ip += 1 sparse_J = np.zeros((self.n_poly_params - self.Nx, M_sparse_indices.size), dtype=dtype) indptr = np.zeros(Nx+1, dtype=int) @@ -996,7 +1012,7 @@ def build_sparse_dM(self, pixels, profile_params, M_sparse_indices, boundaries, indptr[x+1] = (boundaries["xmax"][x]-boundaries["xmin"][x])*(boundaries["ymax"][x]-boundaries["ymin"][x]) + indptr[x] if boundaries["xmin"][x] < 0: continue - sparse_J[:, indptr[x]:indptr[x+1]] += np.repeat(Jpsf[1:], repeats, axis=0) * legs[:, x, None] + sparse_J[:, indptr[x]:indptr[x + 1]] += np.repeat(Jpsf[1:], repeats, axis=0) * polys[:, x, None] dM = [sparse.csr_matrix((sparse_J[ip], M_sparse_indices, indptr), shape=(len(profile_params), pixels[0].size), dtype=dtype).T for ip in range(sparse_J.shape[0])] return dM @@ -1065,7 +1081,8 @@ def rotate_table(self, angle_degree): def from_profile_params_to_poly_params(self, profile_params, indices=None): """ Transform the profile_params array into a set of parameters for the chromatic PSF parameterisation. - Fit Legendre polynomial functions across the pixels for each PSF parameters. + Fit polynomial functions across the pixels for each PSF parameters. + Type of the polynomial function is set by parameters.PSF_POLY_TYPE. The order of the polynomial functions is given by the self.degrees array. Parameters @@ -1099,8 +1116,7 @@ def from_profile_params_to_poly_params(self, profile_params, indices=None): .. doctest:: :hide: - - >>> assert(np.all(np.isclose(profile_params[0], [10, 0, 50, 5, 2, 0, 1, 8e3]))) + >>> assert(np.all(np.isclose(profile_params[0], [10, 0, 50, 5, 2, -0.4, 1, 8e3]))) From the profile parameters to the polynomial parameters: @@ -1122,8 +1138,7 @@ def from_profile_params_to_poly_params(self, profile_params, indices=None): if amplitude is None: self.my_logger.warning('\n\tAmplitude array not initialized. ' 'Polynomial fit for shape parameters will be unweighted.') - - pixels = np.linspace(-1, 1, len(self.table))[indices] + poly_x = np.linspace(-1, 1, len(self.table))[indices] for k, name in enumerate(self.psf.params.labels): delta = 0 if name != 'amplitude': @@ -1132,8 +1147,12 @@ def from_profile_params_to_poly_params(self, profile_params, indices=None): delta = self.x0 if name == 'y_c': delta = self.y0 - fit = np.polynomial.legendre.legfit(pixels, profile_params[indices, k] - delta, - deg=self.degrees[name], w=weights) + if parameters.PSF_POLY_TYPE == "legendre": + fit = np.polynomial.legendre.legfit(poly_x, profile_params[indices, k] - delta, + deg=self.degrees[name], w=weights) + elif parameters.PSF_POLY_TYPE == "polynomial": + fit = np.polynomial.polynomial.polyfit(poly_x, profile_params[indices, k] - delta, + deg=self.degrees[name], w=weights) poly_params = np.concatenate([poly_params, fit]) return poly_params @@ -1236,8 +1255,7 @@ def from_poly_params_to_profile_params(self, poly_params, apply_bounds=False): .. doctest:: :hide: - - >>> assert np.allclose(profile_params[0], [10, 0, 50, 5, 2, -5e-3, 1, 8e3], rtol=1e-3, atol=1e-3) + >>> assert np.allclose(profile_params[0], [10, 0, 50, 5, 2, -0.4, 1, 8e3], rtol=1e-3, atol=1e-3) From the profile parameters to the polynomial parameters: @@ -1254,12 +1272,11 @@ def from_poly_params_to_profile_params(self, poly_params, apply_bounds=False): .. doctest:: :hide: - - >>> assert np.allclose(profile_params[0], [1, 0, 50, 5, 2, 0, 1, 8e3]) + >>> assert np.allclose(profile_params[0], [1, 0, 50, 5, 2, -0.4, 1, 8e3]) """ length = len(self.table) - pixels = np.linspace(-1, 1, length) + poly_x = np.linspace(-1, 1, length) profile_params = np.zeros((length, len(self.psf.params.labels))) shift = 0 for k, name in enumerate(self.psf.params.labels): @@ -1270,14 +1287,17 @@ def from_poly_params_to_profile_params(self, poly_params, apply_bounds=False): profile_params[:, k] = np.ones(length) else: if len(poly_params) > length: - profile_params[:, k] = \ - np.polynomial.legendre.legval(pixels, - poly_params[ - length + shift:length + shift + self.degrees[name] + 1]) + if parameters.PSF_POLY_TYPE == "legendre": + profile_params[:, k] = np.polynomial.legendre.legval(poly_x, poly_params[length + shift:length + shift + self.degrees[name] + 1]) + elif parameters.PSF_POLY_TYPE == "polynomial": + profile_params[:, k] = np.polynomial.polynomial.polyval(poly_x, poly_params[length + shift:length + shift + self.degrees[name] + 1]) else: p = poly_params[shift:shift + self.degrees[name] + 1] if len(p) > 0: # to avoid saturation parameters in case not set - profile_params[:, k] = np.polynomial.legendre.legval(pixels, p) + if parameters.PSF_POLY_TYPE == "legendre": + profile_params[:, k] = np.polynomial.legendre.legval(poly_x, p) + elif parameters.PSF_POLY_TYPE == "polynomial": + profile_params[:, k] = np.polynomial.polynomial.polyval(poly_x, p) shift += self.degrees[name] + 1 if name == 'x_c': profile_params[:, k] += self.x0 @@ -1337,17 +1357,31 @@ def from_profile_params_to_shape_params(self, profile_params): def set_bounds(self): """ This function returns an array of bounds for PSF polynomial parameters (no amplitude ones). - It is very touchy, change the values with caution ! Returns ------- bounds: list 2D array containing the pair of bounds for each polynomial parameters. + Examples + ________ + >>> psf = MoffatGauss() + >>> s = ChromaticPSF(psf, Nx=100, Ny=100, deg=4, saturation=8000) + >>> s.set_bounds() # doctest: +ELLIPSIS + [array([-inf, inf]), array([-inf, inf]), ... + """ bounds = [[], []] for k, name in enumerate(self.psf.params.labels): - tmp_bounds = [[-np.inf] * (1 + self.degrees[name]), [np.inf] * (1 + self.degrees[name])] + if parameters.PSF_POLY_TYPE == "legendre": + tmp_bounds = [[-np.inf] * (1 + self.degrees[name]), [np.inf] * (1 + self.degrees[name])] + elif parameters.PSF_POLY_TYPE == "polynomial": + tmp_bounds = [[self.psf.params.bounds[k][0]] + [-np.inf] * (self.degrees[name]), + [self.psf.params.bounds[k][1]] + [np.inf] * (self.degrees[name])] + # tmp_bounds = [[self.psf.params.bounds[k][0]] + [-0.5 * 2 * (self.psf.params.bounds[k][1] - self.psf.params.bounds[k][0]) for deg in range(1, self.degrees[name] + 1)], + # [self.psf.params.bounds[k][1]] + [0.5 * 2 * (self.psf.params.bounds[k][1] - self.psf.params.bounds[k][0]) for deg in range(1, self.degrees[name] + 1)]] + else: + raise ValueError(f"Unknown polynomial type {parameters.PSF_POLY_TYPE=}.") if name == "saturation": tmp_bounds = [[0], [2 * self.saturation]] elif name == "amplitude": @@ -1417,14 +1451,16 @@ def plot_summary(self, truth=None): PSF_truth[:, 1] = np.arange(self.Nx) # replace x_c all_pixels = np.arange(self.profile_params.shape[0]) for i, name in enumerate(self.psf.params.labels): - legs = [self.params.values[k] for k in range(self.params.ndim) if name in self.params.labels[k]] - pval = np.polynomial.legendre.leg2poly(legs)[::-1] + coeffs = [self.params.values[k] for k in range(self.params.ndim) if name in self.params.labels[k]] delta = 0 if name == 'x_c': delta = self.x0 if name == 'y_c': delta = self.y0 - PSF_models.append(np.polyval(pval, rescale_x_to_legendre(all_pixels)) + delta) + if parameters.PSF_POLY_TYPE == "legendre": + PSF_models.append(np.polynomial.polynomial.legval(rescale_x_to_legendre(all_pixels), coeffs) + delta) + elif parameters.PSF_POLY_TYPE == "polynomial": + PSF_models.append(np.polynomial.polynomial.polyval(rescale_x_to_legendre(all_pixels), coeffs) + delta) for i, name in enumerate(self.psf.params.labels): p = ax.plot(all_pixels, self.profile_params[:, i], marker='+', linestyle='none') ax.plot(all_pixels[self.fitted_pixels], self.profile_params[self.fitted_pixels, i], label=name, @@ -1444,7 +1480,7 @@ def plot_summary(self, truth=None): plt.show() def fit_transverse_PSF1D_profile(self, data, err, w, ws, pixel_step=1, bgd_model_func=None, saturation=None, - live_fit=False, sigma_clip=5): + live_fit=False, sigma_clip=5, mask=None): """ Fit the transverse profile of a 2D data image with a PSF profile. Loop is done on the x-axis direction. @@ -1489,6 +1525,7 @@ def fit_transverse_PSF1D_profile(self, data, err, w, ws, pixel_step=1, bgd_model >>> bgd += 1000*np.exp(-((xx-20)**2+(yy-10)**2)/(2*2)) >>> data += bgd >>> data_errors = np.sqrt(data+1) + >>> mask = bgd > np.median(bgd) Extract the background: @@ -1497,8 +1534,8 @@ def fit_transverse_PSF1D_profile(self, data, err, w, ws, pixel_step=1, bgd_model Fit the transverse profile: >>> s = ChromaticPSF(psf, Nx=100, Ny=100, deg=4, saturation=saturation) - >>> s.fit_transverse_PSF1D_profile(data, data_errors, w=20, ws=[30,50], pixel_step=5, - ... bgd_model_func=bgd_model_func, saturation=saturation, live_fit=False, sigma_clip=5) + >>> s.fit_transverse_PSF1D_profile(data, data_errors, w=20, ws=[30,50], pixel_step=5, mask=mask, + ... bgd_model_func=bgd_model_func, saturation=saturation, live_fit=False, sigma_clip=5,) >>> s.plot_summary(truth=s0) .. doctest:: @@ -1609,6 +1646,8 @@ def fit_transverse_PSF1D_profile(self, data, err, w, ws, pixel_step=1, bgd_model psf.params.bounds = bounds w = PSFFitWorkspace(psf, signal, data_errors=err[:, x], bgd_model_func=None, live_fit=False, verbose=False, jacobian_analytical=True) + if mask is not None: + w.mask = list(np.where(mask[:, x])[0]) try: run_minimisation_sigma_clipping(w, method="newton", sigma_clip=sigma_clip, niter_clip=1, verbose=False) except: @@ -1654,15 +1693,17 @@ def fit_transverse_PSF1D_profile(self, data, err, w, ws, pixel_step=1, bgd_model self.cov_matrix = np.diag(1 / np.array(self.table['flux_err']) ** 2) psf.params.bounds = initial_bounds - def fit_chromatic_psf(self, data, bgd_model_func=None, data_errors=None, mode="1D", analytical=True, + def fit_chromatic_psf(self, data, mask=None, bgd_model_func=None, data_errors=None, mode="1D", analytical=True, amplitude_priors_method="noprior", verbose=False, live_fit=False): """ Fit a chromatic PSF model on 2D data. Parameters ---------- - data: array_like + data: np.array 2D array containing the image data. + mask: np.array, optional + 2D array containing the masked pixels. bgd_model_func: callable, optional A 2D function to model the extracted background (default: None -> null background) data_errors: np.array @@ -1702,6 +1743,8 @@ def fit_chromatic_psf(self, data, bgd_model_func=None, data_errors=None, mode="1 >>> data += bgd >>> data = np.random.poisson(data) >>> data_errors = np.sqrt(np.abs(data+1)) + >>> mask = np.zeros_like(data).astype(bool) + >>> mask[10:30,20:22] = True Extract the background: @@ -1723,7 +1766,7 @@ def fit_chromatic_psf(self, data, bgd_model_func=None, data_errors=None, mode="1 Fit the data using the transverse 1D PSF model only: >>> w = s.fit_chromatic_psf(data, mode="1D", data_errors=data_errors, bgd_model_func=bgd_model_func, - ... amplitude_priors_method="noprior", verbose=True) + ... amplitude_priors_method="noprior", verbose=True, mask=mask) >>> s.plot_summary(truth=s0) >>> amplitude_residuals.append([s0.params.values[:s0.Nx], w.amplitude_params-s0.params.values[:s0.Nx], ... w.amplitude_params_err]) @@ -1740,7 +1783,7 @@ def fit_chromatic_psf(self, data, bgd_model_func=None, data_errors=None, mode="1 >>> parameters.PSF_FIT_REG_PARAM = 0.002 >>> w = s.fit_chromatic_psf(data, mode="2D", data_errors=data_errors, bgd_model_func=bgd_model_func, - ... amplitude_priors_method="psf1d", verbose=True, analytical=True) + ... amplitude_priors_method="psf1d", verbose=True, analytical=True, mask=mask) >>> s.plot_summary(truth=s0) >>> amplitude_residuals.append([s0.params.values[:s0.Nx], w.amplitude_params-s0.params.values[:s0.Nx], ... w.amplitude_params_err]) @@ -1765,13 +1808,13 @@ def fit_chromatic_psf(self, data, bgd_model_func=None, data_errors=None, mode="1 """ if mode == "1D": - w = ChromaticPSFFitWorkspace(self, data, data_errors=data_errors, mode=mode, bgd_model_func=bgd_model_func, + w = ChromaticPSFFitWorkspace(self, data, mask=mask, data_errors=data_errors, mode=mode, bgd_model_func=bgd_model_func, amplitude_priors_method=amplitude_priors_method, verbose=verbose, live_fit=live_fit, analytical=analytical) run_minimisation(w, method="newton", ftol=1 / (w.Nx * w.Ny), xtol=1e-6, niter=50, with_line_search=True) elif mode == "2D": # first shot to set the mask - w = ChromaticPSFFitWorkspace(self, data, data_errors=data_errors, mode=mode, bgd_model_func=bgd_model_func, + w = ChromaticPSFFitWorkspace(self, data, mask=mask, data_errors=data_errors, mode=mode, bgd_model_func=bgd_model_func, amplitude_priors_method=amplitude_priors_method, verbose=verbose, live_fit=live_fit, analytical=analytical) # first, fit the transverse position @@ -1840,7 +1883,7 @@ def fit_chromatic_psf(self, data, bgd_model_func=None, data_errors=None, mode="1 class ChromaticPSFFitWorkspace(FitWorkspace): - def __init__(self, chromatic_psf, data, data_errors, mode, bgd_model_func=None, file_name="", analytical=True, + def __init__(self, chromatic_psf, data, data_errors, mode, bgd_model_func=None, mask=None, file_name="", analytical=True, amplitude_priors_method="noprior", verbose=False, plot=False, live_fit=False, truth=None): if mode not in ["1D", "2D"]: raise ValueError(f"mode argument must be '1D' or '2D'. Got {mode=}.") @@ -1890,6 +1933,10 @@ def __init__(self, chromatic_psf, data, data_errors, mode, bgd_model_func=None, self.data = self.data.astype("float32").ravel() self.err = self.err.astype("float32").ravel() self.pixels = np.arange(self.data.shape[0]) + if mask is not None: + self.mask = list(np.where(mask[self.bgd_width:-self.bgd_width, :].astype(bool).ravel())[0]) + else: + self.mask = [] if mode == "1D": self.pixels = np.arange(self.Ny) @@ -1901,6 +1948,7 @@ def __init__(self, chromatic_psf, data, data_errors, mode, bgd_model_func=None, self.poly_params[self.Nx + self.y_c_0_index] -= self.bgd_width self.profile_params = self.chromatic_psf.from_poly_params_to_profile_params(self.poly_params) self.data_before_mask = np.copy(self.data) + self.mask_before_mask = list(np.copy(self.mask)) self.boundaries = None self.psf_cube_sparse_indices = None self.psf_cube_masked = None @@ -1915,8 +1963,6 @@ def __init__(self, chromatic_psf, data, data_errors, mode, bgd_model_func=None, # (which is not exactly true in rotated images) self.data_cov = sparse.diags(self.err * self.err, dtype="float32", format="dia") self.W = sparse.diags(1 / (self.err * self.err), dtype="float32", format="dia") - self.sqrtW = self.W.sqrt() - # create a mask self.W_before_mask = self.W.copy() # design matrix @@ -1933,7 +1979,7 @@ def __init__(self, chromatic_psf, data, data_errors, mode, bgd_model_func=None, self.amplitude_priors_method = amplitude_priors_method self.fwhm_priors = np.copy(self.chromatic_psf.table['fwhm']) self.reg = parameters.PSF_FIT_REG_PARAM - self.trace_r = self.Nx / np.min(self.fwhm_priors) # spectrophotometric uncertainty principle + self.trace_r = self.Nx / np.median(self.fwhm_priors) # spectrophotometric uncertainty principle self.Q = np.zeros((self.Nx, self.Nx)) self.Q_dot_A0 = np.zeros(self.Nx) if amplitude_priors_method not in self.amplitude_priors_list: @@ -2035,14 +2081,21 @@ def set_mask(self, poly_params=None): fwhmx_clip=3 * parameters.PSF_FWHM_CLIP, fwhmy_clip=parameters.PSF_FWHM_CLIP) self.psf_cube_masked = self.chromatic_psf.convolve_psf_cube_masked(psf_cube_masked) - self.boundaries, self.psf_cube_masked = self.chromatic_psf.get_boundaries(self.psf_cube_masked) - self.psf_cube_sparse_indices, self.M_sparse_indices = self.chromatic_psf.get_sparse_indices(self.psf_cube_masked) + self.boundaries, self.psf_cube_masked = self.chromatic_psf.set_rectangular_boundaries(self.psf_cube_masked) + self.psf_cube_sparse_indices, self.M_sparse_indices = self.chromatic_psf.get_sparse_indices(self.boundaries) mask = np.sum(self.psf_cube_masked.reshape(psf_cube_masked.shape[0], psf_cube_masked[0].size), axis=0) == 0 + # cumulate the boolean values as int + weight_mask = np.sum(self.psf_cube_masked, axis=0) + # look for indices with maximum weight per column (all sheets of the psf cube have contributed) + res = np.max(weight_mask, axis=0)[np.newaxis,:] * np.ones((weight_mask.shape[0],1)) + # keep only the pixels where all psf_cube sheets have contributed per column + mask = (weight_mask != res).ravel() W = np.copy(self.W_before_mask.data.ravel()) - W[mask] = 0 + self.mask = list(np.copy(self.mask_before_mask)) + self.mask += list(np.where(mask)[0]) + self.mask = list(set(self.mask)) + W[self.mask] = 0 self.W = sparse.diags(W, dtype="float32", format="dia") - self.sqrtW = self.W.sqrt() - self.mask = list(np.where(mask)[0]) def simulate(self, *shape_params): r""" @@ -2237,7 +2290,7 @@ def simulate(self, *shape_params): M = self.chromatic_psf.build_sparse_M(self.pixels, profile_params, dtype="float32", M_sparse_indices=self.M_sparse_indices, boundaries=self.boundaries) - M_dot_W = M.T @ self.sqrtW + M_dot_W = M.T @ self.W.sqrt() W_dot_data = self.W @ self.data # Compute the minimizing amplitudes if sparse_dot_mkl is None: diff --git a/spectractor/extractor/dispersers/holo4_003/NOTES b/spectractor/extractor/dispersers/holo4_003/NOTES index 9d8fb6eeb..2b1ee98e9 100644 --- a/spectractor/extractor/dispersers/holo4_003/NOTES +++ b/spectractor/extractor/dispersers/holo4_003/NOTES @@ -1,3 +1,5 @@ - transmission.txt : prediction from the chimera built with LPNHE optical test bench measurements between 430 and 1000nm, then extrapolating with an hologram efficiency model fitted on data -- ratio_order_2over1.txt : computed using separated extraction of spectrum order 1 and 2 from BG40 exposures, nights 20220608, 20220628, 20220629 and 20220630 with ratio 3/2 model, CCD_REBIN=2 with Savitsky Golay filter -- ratio_order_3over2.txt : prediction from the chimera built with LPNHE optical test bench measurements between 430 and 1000nm, then extrapolating with an hologram efficiency model fitted on data +- ratio_order_2over1.txt : computed using separated extraction of spectrum order 1 and 2 from BG40 exposures, nights 20220608, 20220628, 20220629 and 20220630 with ratio 3/2 model, CCD_REBIN=2 with Savitsky Golay filter, extrapolated fitting an hologram transmission model (see ratio_order_2over1_from_fit.txt) +- ratio_order_3over2.txt : prediction from the chimera built with LPNHE optical test bench measurements between 430 and 1000nm, rescaled with the estimate using SDSSg filter ratio of orders, extrapolated fitting an hologram transmission model (see ratio_order_2over1_from_fit.txt) +#- ratio_order_2over1.txt : computed using separated extraction of spectrum order 1 and 2 from BG40 exposures, nights 20220608, 20220628, 20220629 and 20220630 with ratio 3/2 model, CCD_REBIN=2 with Savitsky Golay filter +#- ratio_order_3over2.txt : prediction from the chimera built with LPNHE optical test bench measurements between 430 and 1000nm, rescaled with the estimate using SDSSg filter ratio of orders diff --git a/spectractor/extractor/dispersers/holo4_003/ratio_order_2over1.txt b/spectractor/extractor/dispersers/holo4_003/ratio_order_2over1.txt index 6f27e0c43..4b12af8f1 100644 --- a/spectractor/extractor/dispersers/holo4_003/ratio_order_2over1.txt +++ b/spectractor/extractor/dispersers/holo4_003/ratio_order_2over1.txt @@ -1,800 +1,800 @@ -3.000000000000000000e+02 -7.090213097062541436e+00 -3.010000000000000000e+02 -7.090213097062542325e+00 -3.020000000000000000e+02 -7.090213097062542325e+00 -3.030000000000000000e+02 -7.090213097062543213e+00 -3.040000000000000000e+02 -7.090213097062544989e+00 -3.050000000000000000e+02 -7.090213097062544989e+00 -3.060000000000000000e+02 -7.090213097062544989e+00 -3.070000000000000000e+02 -7.090213097062544989e+00 -3.080000000000000000e+02 -7.090213097062544989e+00 -3.090000000000000000e+02 -7.090213097062544989e+00 -3.100000000000000000e+02 -7.090213097062544989e+00 -3.110000000000000000e+02 -7.090213097062544989e+00 -3.120000000000000000e+02 -7.090213097062544989e+00 -3.130000000000000000e+02 -7.090213097062544989e+00 -3.140000000000000000e+02 -7.090213097062544989e+00 -3.150000000000000000e+02 -7.090213097062544989e+00 -3.160000000000000000e+02 -7.090213097062544989e+00 -3.170000000000000000e+02 -7.090213097062544989e+00 -3.180000000000000000e+02 -7.090213097062544989e+00 -3.190000000000000000e+02 -7.090213097062544989e+00 -3.200000000000000000e+02 -7.090213097062544989e+00 -3.210000000000000000e+02 -7.090213097062544989e+00 -3.220000000000000000e+02 -7.090213097062544989e+00 -3.230000000000000000e+02 -7.090213097062544989e+00 -3.240000000000000000e+02 -7.090213097062544989e+00 -3.250000000000000000e+02 -7.090213097062544989e+00 -3.260000000000000000e+02 -7.090213097062544989e+00 -3.270000000000000000e+02 -7.090213097062544989e+00 -3.280000000000000000e+02 -7.090213097062544989e+00 -3.290000000000000000e+02 -7.090213097062544989e+00 -3.300000000000000000e+02 -7.090213097062544989e+00 -3.310000000000000000e+02 -7.090213097062544989e+00 -3.320000000000000000e+02 -7.090213097062544989e+00 -3.330000000000000000e+02 -7.090213097062544989e+00 -3.340000000000000000e+02 -7.090213097062544989e+00 -3.350000000000000000e+02 -6.328803424402677180e+00 -3.360000000000000000e+02 -5.527802037939696156e+00 -3.370000000000000000e+02 -4.613243163438663252e+00 -3.380000000000000000e+02 -3.812382915170114295e+00 -3.390000000000000000e+02 -2.991109607661365910e+00 -3.400000000000000000e+02 -1.822843895112854273e+00 -3.410000000000000000e+02 -6.926260049797368090e-01 -3.420000000000000000e+02 3.870096902209335665e-01 -3.430000000000000000e+02 1.747384374344775892e+00 -3.440000000000000000e+02 2.303928005602863482e+00 -3.450000000000000000e+02 2.783002638712051446e+00 -3.460000000000000000e+02 3.136856115706376791e+00 -3.470000000000000000e+02 3.573486275341247520e+00 -3.480000000000000000e+02 3.998683400877324878e+00 -3.490000000000000000e+02 4.040869007395492929e+00 -3.500000000000000000e+02 4.153621186251155173e+00 -3.510000000000000000e+02 4.307819339879337406e+00 -3.520000000000000000e+02 4.122505813925746665e+00 -3.530000000000000000e+02 3.909383886504167016e+00 -3.540000000000000000e+02 3.698665671948257128e+00 -3.550000000000000000e+02 3.516173380005064519e+00 -3.560000000000000000e+02 3.356477995828850425e+00 -3.570000000000000000e+02 3.160081580233749854e+00 -3.580000000000000000e+02 2.984200165885861011e+00 -3.590000000000000000e+02 2.770167735908844353e+00 -3.600000000000000000e+02 2.544125745463342803e+00 -3.610000000000000000e+02 2.390559827962756234e+00 -3.620000000000000000e+02 2.312684631433588933e+00 -3.630000000000000000e+02 2.249351988051884632e+00 -3.640000000000000000e+02 2.160481333197594722e+00 -3.650000000000000000e+02 2.080340203487198281e+00 -3.660000000000000000e+02 2.036984480629119965e+00 -3.670000000000000000e+02 1.994087600564666829e+00 -3.680000000000000000e+02 1.940603736211912844e+00 -3.690000000000000000e+02 1.888583656013298029e+00 -3.700000000000000000e+02 1.790755255006616364e+00 -3.710000000000000000e+02 1.692465345587529812e+00 -3.720000000000000000e+02 1.617378317791101860e+00 -3.730000000000000000e+02 1.559343907277888075e+00 -3.740000000000000000e+02 1.511663235743319511e+00 -3.750000000000000000e+02 1.442967817317731161e+00 -3.760000000000000000e+02 1.392010166481182143e+00 -3.770000000000000000e+02 1.356970819697515651e+00 -3.780000000000000000e+02 1.315672992097228322e+00 -3.790000000000000000e+02 1.280728020654762433e+00 -3.800000000000000000e+02 1.250648336598931154e+00 -3.810000000000000000e+02 1.233236446903313910e+00 -3.820000000000000000e+02 1.201881619672994672e+00 -3.830000000000000000e+02 1.146703838483096760e+00 -3.840000000000000000e+02 1.097896025484838445e+00 -3.850000000000000000e+02 1.048476150035318355e+00 -3.860000000000000000e+02 1.017637220687949817e+00 -3.870000000000000000e+02 1.028435253921600401e+00 -3.880000000000000000e+02 1.039485602203704451e+00 -3.890000000000000000e+02 1.007069572347964126e+00 -3.900000000000000000e+02 9.727890037215338737e-01 -3.910000000000000000e+02 9.663333174638393253e-01 -3.920000000000000000e+02 9.478789831251134279e-01 -3.930000000000000000e+02 9.146401266440861155e-01 -3.940000000000000000e+02 8.964838841883382425e-01 -3.950000000000000000e+02 8.709237174070031395e-01 -3.960000000000000000e+02 8.265883653201128167e-01 -3.970000000000000000e+02 8.033407222810033943e-01 -3.980000000000000000e+02 8.118924754640002295e-01 -3.990000000000000000e+02 8.044148519649951812e-01 -4.000000000000000000e+02 7.726953097894549982e-01 -4.010000000000000000e+02 7.646660821341034753e-01 -4.020000000000000000e+02 7.743080343406182342e-01 -4.030000000000000000e+02 7.657572992398562484e-01 -4.040000000000000000e+02 7.496357501429595782e-01 -4.050000000000000000e+02 7.334880799993769296e-01 -4.060000000000000000e+02 7.164893091571650219e-01 -4.070000000000000000e+02 7.012917685380222199e-01 -4.080000000000000000e+02 6.911186014599846050e-01 -4.090000000000000000e+02 6.814727432371219251e-01 -4.100000000000000000e+02 6.712368360203043727e-01 -4.110000000000000000e+02 6.631628188627718412e-01 -4.120000000000000000e+02 6.557240173062228727e-01 -4.130000000000000000e+02 6.426077737163423675e-01 -4.140000000000000000e+02 6.306938107431300233e-01 -4.150000000000000000e+02 6.231470464372395046e-01 -4.160000000000000000e+02 6.155417585989471085e-01 -4.170000000000000000e+02 6.065583524274558158e-01 -4.180000000000000000e+02 5.973653276235721954e-01 -4.190000000000000000e+02 5.880300677074770110e-01 -4.200000000000000000e+02 5.794847797288136260e-01 -4.210000000000000000e+02 5.710896937506615423e-01 -4.220000000000000000e+02 5.649269475079771174e-01 -4.230000000000000000e+02 5.611600528314897307e-01 -4.240000000000000000e+02 5.590998265874644879e-01 -4.250000000000000000e+02 5.521542515421713482e-01 -4.260000000000000000e+02 5.347576224958094926e-01 -4.270000000000000000e+02 5.209377065831362064e-01 -4.280000000000000000e+02 5.173853413716962280e-01 -4.290000000000000000e+02 5.133642763288562838e-01 -4.300000000000000000e+02 5.031284167181094835e-01 -4.310000000000000000e+02 4.935211140689056419e-01 -4.320000000000000000e+02 4.880868077467254151e-01 -4.330000000000000000e+02 4.801128385743494986e-01 -4.340000000000000000e+02 4.717682983576887423e-01 -4.350000000000000000e+02 4.710363751507173347e-01 -4.360000000000000000e+02 4.702276890457245395e-01 -4.370000000000000000e+02 4.622921815338318918e-01 -4.380000000000000000e+02 4.547698834270983981e-01 -4.390000000000000000e+02 4.531389015741070225e-01 -4.400000000000000000e+02 4.503861585087456931e-01 -4.410000000000000000e+02 4.414805861234325501e-01 -4.420000000000000000e+02 4.325248711655828027e-01 -4.430000000000000000e+02 4.286142196459217235e-01 -4.440000000000000000e+02 4.275428105567987691e-01 -4.450000000000000000e+02 4.247827786684365003e-01 -4.460000000000000000e+02 4.209600553455061789e-01 -4.470000000000000000e+02 4.177210706210515712e-01 -4.480000000000000000e+02 4.127250600023361637e-01 -4.490000000000000000e+02 4.061739185334488078e-01 -4.500000000000000000e+02 4.011949896430181406e-01 -4.510000000000000000e+02 3.984389066119622957e-01 -4.520000000000000000e+02 3.960398812874672547e-01 -4.530000000000000000e+02 3.929348478948982426e-01 -4.540000000000000000e+02 3.886898482747888073e-01 -4.550000000000000000e+02 3.830207331471457977e-01 -4.560000000000000000e+02 3.761158173254862125e-01 -4.570000000000000000e+02 3.723824576145031151e-01 -4.580000000000000000e+02 3.715717745057048882e-01 -4.590000000000000000e+02 3.697182244393833472e-01 -4.600000000000000000e+02 3.658589993526584205e-01 -4.610000000000000000e+02 3.616719520199900839e-01 -4.620000000000000000e+02 3.576812568545735815e-01 -4.630000000000000000e+02 3.543864690911576742e-01 -4.640000000000000000e+02 3.522280955521581158e-01 -4.650000000000000000e+02 3.504491996285457045e-01 -4.660000000000000000e+02 3.462631876000078490e-01 -4.670000000000000000e+02 3.415205514492465344e-01 -4.680000000000000000e+02 3.384089465309362277e-01 -4.690000000000000000e+02 3.361808400752953618e-01 -4.700000000000000000e+02 3.338449166956842240e-01 -4.710000000000000000e+02 3.311657795290107731e-01 -4.720000000000000000e+02 3.275213049028709023e-01 -4.730000000000000000e+02 3.239354617756656785e-01 -4.740000000000000000e+02 3.208363739629827571e-01 -4.750000000000000000e+02 3.186696177888769799e-01 -4.760000000000000000e+02 3.161602865869745371e-01 -4.770000000000000000e+02 3.128410256276050738e-01 -4.780000000000000000e+02 3.104662875566143176e-01 -4.790000000000000000e+02 3.090143600831314896e-01 -4.800000000000000000e+02 3.081707598125788539e-01 -4.810000000000000000e+02 3.069198629731377248e-01 -4.820000000000000000e+02 3.019714098310701811e-01 -4.830000000000000000e+02 2.973032450354184952e-01 -4.840000000000000000e+02 2.956908062068524523e-01 -4.850000000000000000e+02 2.947100948529325914e-01 -4.860000000000000000e+02 2.939056685952170511e-01 -4.870000000000000000e+02 2.916286543564557410e-01 -4.880000000000000000e+02 2.870339431469631775e-01 -4.890000000000000000e+02 2.816971438289136986e-01 -4.900000000000000000e+02 2.791004008932900793e-01 -4.910000000000000000e+02 2.802878119207415364e-01 -4.920000000000000000e+02 2.805368097427271001e-01 -4.930000000000000000e+02 2.784182570727317119e-01 -4.940000000000000000e+02 2.753849010497286254e-01 -4.950000000000000000e+02 2.719841364541146778e-01 -4.960000000000000000e+02 2.695455429084538945e-01 -4.970000000000000000e+02 2.678427239474470145e-01 -4.980000000000000000e+02 2.665017100198022737e-01 -4.990000000000000000e+02 2.649065167667907228e-01 -5.000000000000000000e+02 2.625448971300224366e-01 -5.010000000000000000e+02 2.605327268643842786e-01 -5.020000000000000000e+02 2.588775133516937887e-01 -5.030000000000000000e+02 2.567718978178080147e-01 -5.040000000000000000e+02 2.543575805589111116e-01 -5.050000000000000000e+02 2.522306554662914202e-01 -5.060000000000000000e+02 2.508842499016156191e-01 -5.070000000000000000e+02 2.496783842260557051e-01 -5.080000000000000000e+02 2.480466856910102935e-01 -5.090000000000000000e+02 2.465207081940127831e-01 -5.100000000000000000e+02 2.449208617331634363e-01 -5.110000000000000000e+02 2.434411448417727886e-01 -5.120000000000000000e+02 2.420025343302613652e-01 -5.130000000000000000e+02 2.394674880313324705e-01 -5.140000000000000000e+02 2.367835379825995457e-01 -5.150000000000000000e+02 2.353722058444396859e-01 -5.160000000000000000e+02 2.336618640339418185e-01 -5.170000000000000000e+02 2.321268605904972526e-01 -5.180000000000000000e+02 2.304314592746790624e-01 -5.190000000000000000e+02 2.283464729493796530e-01 -5.200000000000000000e+02 2.265780891294194022e-01 -5.210000000000000000e+02 2.256899832125863758e-01 -5.220000000000000000e+02 2.250991244949594738e-01 -5.230000000000000000e+02 2.233560615211991895e-01 -5.240000000000000000e+02 2.215911662546430905e-01 -5.250000000000000000e+02 2.209070846613355177e-01 -5.260000000000000000e+02 2.197276445663630118e-01 -5.270000000000000000e+02 2.190231828766119881e-01 -5.280000000000000000e+02 2.178701800624724405e-01 -5.290000000000000000e+02 2.150125104164173628e-01 -5.300000000000000000e+02 2.125333736501849868e-01 -5.310000000000000000e+02 2.120636993767610057e-01 -5.320000000000000000e+02 2.124650126834856378e-01 -5.330000000000000000e+02 2.114997118427921485e-01 -5.340000000000000000e+02 2.094850735750174442e-01 -5.350000000000000000e+02 2.076346526871917231e-01 -5.360000000000000000e+02 2.052689544373455521e-01 -5.370000000000000000e+02 2.035871992438794964e-01 -5.380000000000000000e+02 2.030179648328740427e-01 -5.390000000000000000e+02 2.017867402520298059e-01 -5.400000000000000000e+02 1.998175876055161004e-01 -5.410000000000000000e+02 1.982126679078189679e-01 -5.420000000000000000e+02 1.968221777258057359e-01 -5.430000000000000000e+02 1.951206513723492408e-01 -5.440000000000000000e+02 1.933572413120855371e-01 -5.450000000000000000e+02 1.924033739507697016e-01 -5.460000000000000000e+02 1.912292451448932284e-01 -5.470000000000000000e+02 1.897415695859978324e-01 -5.480000000000000000e+02 1.884175909126065140e-01 -5.490000000000000000e+02 1.869666203081614686e-01 -5.500000000000000000e+02 1.855619361337265405e-01 -5.510000000000000000e+02 1.845441303939724942e-01 -5.520000000000000000e+02 1.835914214664698674e-01 -5.530000000000000000e+02 1.826191053899133276e-01 -5.540000000000000000e+02 1.814372241223501658e-01 -5.550000000000000000e+02 1.802821089549231093e-01 -5.560000000000000000e+02 1.789652630866330196e-01 -5.570000000000000000e+02 1.778285904912150217e-01 -5.580000000000000000e+02 1.768766064530321314e-01 -5.590000000000000000e+02 1.757726218800563789e-01 -5.600000000000000000e+02 1.741378226592481815e-01 -5.610000000000000000e+02 1.723288261162471136e-01 -5.620000000000000000e+02 1.707501802187501305e-01 -5.630000000000000000e+02 1.696560826079121231e-01 -5.640000000000000000e+02 1.688866431451916950e-01 -5.650000000000000000e+02 1.676131424568440831e-01 -5.660000000000000000e+02 1.660828506312333475e-01 -5.670000000000000000e+02 1.646337159350181323e-01 -5.680000000000000000e+02 1.632198378269752725e-01 -5.690000000000000000e+02 1.623592743612009281e-01 -5.700000000000000000e+02 1.617382098917645727e-01 -5.710000000000000000e+02 1.607528905989208667e-01 -5.720000000000000000e+02 1.594418388929920716e-01 -5.730000000000000000e+02 1.581722095854678212e-01 -5.740000000000000000e+02 1.569735905444122337e-01 -5.750000000000000000e+02 1.559091853012824491e-01 -5.760000000000000000e+02 1.549316713274414004e-01 -5.770000000000000000e+02 1.535227930799748230e-01 -5.780000000000000000e+02 1.519361704420207348e-01 -5.790000000000000000e+02 1.506882691193676127e-01 -5.800000000000000000e+02 1.491550228204485962e-01 -5.810000000000000000e+02 1.472755598602591975e-01 -5.820000000000000000e+02 1.458910722211179678e-01 -5.830000000000000000e+02 1.445061541950944106e-01 -5.840000000000000000e+02 1.432251686690005632e-01 -5.850000000000000000e+02 1.417824358351622016e-01 -5.860000000000000000e+02 1.407177299135873028e-01 -5.870000000000000000e+02 1.395365186160640036e-01 -5.880000000000000000e+02 1.386613500714227454e-01 -5.890000000000000000e+02 1.376856108123127864e-01 -5.900000000000000000e+02 1.371074581111847712e-01 -5.910000000000000000e+02 1.358785692803984035e-01 -5.920000000000000000e+02 1.347587844386158584e-01 -5.930000000000000000e+02 1.339446389066242249e-01 -5.940000000000000000e+02 1.328714086248795612e-01 -5.950000000000000000e+02 1.303082016745845950e-01 -5.960000000000000000e+02 1.280845601150825963e-01 -5.970000000000000000e+02 1.257039358822217012e-01 -5.980000000000000000e+02 1.232436776011627821e-01 -5.990000000000000000e+02 1.205046803707603698e-01 -6.000000000000000000e+02 1.182720193486171689e-01 -6.010000000000000000e+02 1.160052597216233439e-01 -6.020000000000000000e+02 1.129659906267471703e-01 -6.030000000000000000e+02 1.106328400783497257e-01 -6.040000000000000000e+02 1.097242059362349836e-01 -6.050000000000000000e+02 1.081873105499707999e-01 -6.060000000000000000e+02 1.057636530345747450e-01 -6.070000000000000000e+02 1.053256949202308473e-01 -6.080000000000000000e+02 1.042384655554098039e-01 -6.090000000000000000e+02 1.014123589208693055e-01 -6.100000000000000000e+02 1.002267225271305517e-01 -6.110000000000000000e+02 9.796249555250345631e-02 -6.120000000000000000e+02 9.572763560385537385e-02 -6.130000000000000000e+02 9.376457849802230515e-02 -6.140000000000000000e+02 9.194063446381861571e-02 -6.150000000000000000e+02 9.018079583129121057e-02 -6.160000000000000000e+02 8.684672437258034172e-02 -6.170000000000000000e+02 8.513035175552598199e-02 -6.180000000000000000e+02 8.457769811552133532e-02 -6.190000000000000000e+02 8.124867691737501507e-02 -6.200000000000000000e+02 8.083303141529971092e-02 -6.210000000000000000e+02 7.969580623993287316e-02 -6.220000000000000000e+02 7.807788370960067059e-02 -6.230000000000000000e+02 7.588536004885376718e-02 -6.240000000000000000e+02 7.465648723171451617e-02 -6.250000000000000000e+02 7.293219633282768677e-02 -6.260000000000000000e+02 7.102910568592249452e-02 -6.270000000000000000e+02 6.823992446657642374e-02 -6.280000000000000000e+02 6.729404339639416532e-02 -6.290000000000000000e+02 6.570446276328731350e-02 -6.300000000000000000e+02 6.389084977333474302e-02 -6.310000000000000000e+02 6.167264304752995835e-02 -6.320000000000000000e+02 6.168744106786816506e-02 -6.330000000000000000e+02 6.149270221404462555e-02 -6.340000000000000000e+02 6.018832858602345126e-02 -6.350000000000000000e+02 5.800737047095026050e-02 -6.360000000000000000e+02 5.912179117724896543e-02 -6.370000000000000000e+02 5.654270805248425708e-02 -6.380000000000000000e+02 5.412364314191689396e-02 -6.390000000000000000e+02 5.066405966988099530e-02 -6.400000000000000000e+02 4.870174645719493878e-02 -6.410000000000000000e+02 4.809799948468499592e-02 -6.420000000000000000e+02 4.775645758073446961e-02 -6.430000000000000000e+02 5.032795678436362968e-02 -6.440000000000000000e+02 5.380941097176278332e-02 -6.450000000000000000e+02 5.003574563882724757e-02 -6.460000000000000000e+02 4.687504817622907549e-02 -6.470000000000000000e+02 4.278333113019516104e-02 -6.480000000000000000e+02 4.038501734549286570e-02 -6.490000000000000000e+02 3.734994413927558016e-02 -6.500000000000000000e+02 3.159026823157892738e-02 -6.510000000000000000e+02 2.552501180555797472e-02 -6.520000000000000000e+02 1.840569895823435803e-02 -6.530000000000000000e+02 1.095708058464484394e-02 -6.540000000000000000e+02 8.546557230822095577e-03 -6.550000000000000000e+02 8.958049086387047735e-03 -6.560000000000000000e+02 9.449554893691874610e-03 -6.570000000000000000e+02 9.882699255074307160e-03 -6.580000000000000000e+02 1.053704001307656860e-02 -6.590000000000000000e+02 1.126777823618900325e-02 -6.600000000000000000e+02 1.222589539075055742e-02 -6.610000000000000000e+02 1.334616941659527885e-02 -6.620000000000000000e+02 1.414199728570622941e-02 -6.630000000000000000e+02 1.523066274219376376e-02 -6.640000000000000000e+02 1.656803737484623118e-02 -6.650000000000000000e+02 1.791816523222217183e-02 -6.660000000000000000e+02 1.946047719303312801e-02 -6.670000000000000000e+02 2.016747267923760939e-02 -6.680000000000000000e+02 2.075530070851973330e-02 -6.690000000000000000e+02 2.207424218040054606e-02 -6.700000000000000000e+02 2.347914200244569094e-02 -6.710000000000000000e+02 2.611735269247505986e-02 -6.720000000000000000e+02 3.115979221791311329e-02 -6.730000000000000000e+02 3.542261050738817335e-02 -6.740000000000000000e+02 3.838780755210113166e-02 -6.750000000000000000e+02 4.342362526503897036e-02 -6.760000000000000000e+02 4.939630041023400364e-02 -6.770000000000000000e+02 5.373615578630489692e-02 -6.780000000000000000e+02 5.592804575849290305e-02 -6.790000000000000000e+02 5.499742458285750840e-02 -6.800000000000000000e+02 6.175563369688819026e-02 -6.810000000000000000e+02 6.054550042609304489e-02 -6.820000000000000000e+02 5.932669376852171828e-02 -6.830000000000000000e+02 6.079455649472691181e-02 -6.840000000000000000e+02 1.053535976490686116e-02 -6.850000000000000000e+02 -3.669168823655337419e-02 -6.860000000000000000e+02 -8.564000370867089207e-02 -6.870000000000000000e+02 -1.335350554003449097e-01 -6.880000000000000000e+02 -1.784736175504070266e-01 -6.890000000000000000e+02 -2.322038120760240298e-01 -6.900000000000000000e+02 -2.806830911676423401e-01 -6.910000000000000000e+02 -3.284996786866697938e-01 -6.920000000000000000e+02 -3.778162718497888317e-01 -6.930000000000000000e+02 -3.776943659534208186e-01 -6.940000000000000000e+02 -3.809622962482322461e-01 -6.950000000000000000e+02 -3.809622962482322461e-01 -6.960000000000000000e+02 -3.809622962482322461e-01 -6.970000000000000000e+02 -3.809622962482322461e-01 -6.980000000000000000e+02 -3.809622962482322461e-01 -6.990000000000000000e+02 -3.809622962482322461e-01 -7.000000000000000000e+02 -3.809622962482322461e-01 -7.010000000000000000e+02 -3.809622962482322461e-01 -7.020000000000000000e+02 -3.809622962482322461e-01 -7.030000000000000000e+02 -3.809622962482322461e-01 -7.040000000000000000e+02 -3.809622962482322461e-01 -7.050000000000000000e+02 -3.809622962482322461e-01 -7.060000000000000000e+02 -3.809622962482322461e-01 -7.070000000000000000e+02 -3.809622962482322461e-01 -7.080000000000000000e+02 -3.809622962482322461e-01 -7.090000000000000000e+02 -3.809622962482322461e-01 -7.100000000000000000e+02 -3.809622962482322461e-01 -7.110000000000000000e+02 -3.809622962482322461e-01 -7.120000000000000000e+02 -3.809622962482322461e-01 -7.130000000000000000e+02 -3.809622962482322461e-01 -7.140000000000000000e+02 -3.809622962482322461e-01 -7.150000000000000000e+02 -3.809622962482322461e-01 -7.160000000000000000e+02 -3.809622962482322461e-01 -7.170000000000000000e+02 -3.809622962482322461e-01 -7.180000000000000000e+02 -3.809622962482322461e-01 -7.190000000000000000e+02 -3.809622962482322461e-01 -7.200000000000000000e+02 -3.809622962482322461e-01 -7.210000000000000000e+02 -3.809622962482322461e-01 -7.220000000000000000e+02 -3.809622962482322461e-01 -7.230000000000000000e+02 -3.809622962482322461e-01 -7.240000000000000000e+02 -3.809622962482322461e-01 -7.250000000000000000e+02 -3.809622962482322461e-01 -7.260000000000000000e+02 -3.809622962482322461e-01 -7.270000000000000000e+02 -3.809622962482322461e-01 -7.280000000000000000e+02 -3.809622962482322461e-01 -7.290000000000000000e+02 -3.809622962482322461e-01 -7.300000000000000000e+02 -3.809622962482322461e-01 -7.310000000000000000e+02 -3.809622962482322461e-01 -7.320000000000000000e+02 -3.809622962482322461e-01 -7.330000000000000000e+02 -3.809622962482322461e-01 -7.340000000000000000e+02 -3.809622962482322461e-01 -7.350000000000000000e+02 -3.809622962482322461e-01 -7.360000000000000000e+02 -3.809622962482322461e-01 -7.370000000000000000e+02 -3.809622962482322461e-01 -7.380000000000000000e+02 -3.809622962482322461e-01 -7.390000000000000000e+02 -3.809622962482322461e-01 -7.400000000000000000e+02 -3.809622962482322461e-01 -7.410000000000000000e+02 -3.809622962482322461e-01 -7.420000000000000000e+02 -3.809622962482322461e-01 -7.430000000000000000e+02 -3.809622962482322461e-01 -7.440000000000000000e+02 -3.809622962482322461e-01 -7.450000000000000000e+02 -3.809622962482322461e-01 -7.460000000000000000e+02 -3.809622962482322461e-01 -7.470000000000000000e+02 -3.809622962482322461e-01 -7.480000000000000000e+02 -3.809622962482322461e-01 -7.490000000000000000e+02 -3.809622962482322461e-01 -7.500000000000000000e+02 -3.809622962482322461e-01 -7.510000000000000000e+02 -3.809622962482322461e-01 -7.520000000000000000e+02 -3.809622962482322461e-01 -7.530000000000000000e+02 -3.809622962482322461e-01 -7.540000000000000000e+02 -3.809622962482322461e-01 -7.550000000000000000e+02 -3.809622962482322461e-01 -7.560000000000000000e+02 -3.809622962482322461e-01 -7.570000000000000000e+02 -3.809622962482322461e-01 -7.580000000000000000e+02 -3.809622962482322461e-01 -7.590000000000000000e+02 -3.809622962482322461e-01 -7.600000000000000000e+02 -3.809622962482322461e-01 -7.610000000000000000e+02 -3.809622962482322461e-01 -7.620000000000000000e+02 -3.809622962482322461e-01 -7.630000000000000000e+02 -3.809622962482322461e-01 -7.640000000000000000e+02 -3.809622962482322461e-01 -7.650000000000000000e+02 -3.809622962482322461e-01 -7.660000000000000000e+02 -3.809622962482322461e-01 -7.670000000000000000e+02 -3.809622962482322461e-01 -7.680000000000000000e+02 -3.809622962482322461e-01 -7.690000000000000000e+02 -3.809622962482322461e-01 -7.700000000000000000e+02 -3.809622962482322461e-01 -7.710000000000000000e+02 -3.809622962482322461e-01 -7.720000000000000000e+02 -3.809622962482322461e-01 -7.730000000000000000e+02 -3.809622962482322461e-01 -7.740000000000000000e+02 -3.809622962482322461e-01 -7.750000000000000000e+02 -3.809622962482322461e-01 -7.760000000000000000e+02 -3.809622962482322461e-01 -7.770000000000000000e+02 -3.809622962482322461e-01 -7.780000000000000000e+02 -3.809622962482322461e-01 -7.790000000000000000e+02 -3.809622962482322461e-01 -7.800000000000000000e+02 -3.809622962482322461e-01 -7.810000000000000000e+02 -3.809622962482322461e-01 -7.820000000000000000e+02 -3.809622962482322461e-01 -7.830000000000000000e+02 -3.809622962482322461e-01 -7.840000000000000000e+02 -3.809622962482322461e-01 -7.850000000000000000e+02 -3.809622962482322461e-01 -7.860000000000000000e+02 -3.809622962482322461e-01 -7.870000000000000000e+02 -3.809622962482322461e-01 -7.880000000000000000e+02 -3.809622962482322461e-01 -7.890000000000000000e+02 -3.809622962482322461e-01 -7.900000000000000000e+02 -3.809622962482322461e-01 -7.910000000000000000e+02 -3.809622962482322461e-01 -7.920000000000000000e+02 -3.809622962482322461e-01 -7.930000000000000000e+02 -3.809622962482322461e-01 -7.940000000000000000e+02 -3.809622962482322461e-01 -7.950000000000000000e+02 -3.809622962482322461e-01 -7.960000000000000000e+02 -3.809622962482322461e-01 -7.970000000000000000e+02 -3.809622962482322461e-01 -7.980000000000000000e+02 -3.809622962482322461e-01 -7.990000000000000000e+02 -3.809622962482322461e-01 -8.000000000000000000e+02 -3.809622962482322461e-01 -8.010000000000000000e+02 -3.809622962482322461e-01 -8.020000000000000000e+02 -3.809622962482322461e-01 -8.030000000000000000e+02 -3.809622962482322461e-01 -8.040000000000000000e+02 -3.809622962482322461e-01 -8.050000000000000000e+02 -3.809622962482322461e-01 -8.060000000000000000e+02 -3.809622962482322461e-01 -8.070000000000000000e+02 -3.809622962482322461e-01 -8.080000000000000000e+02 -3.809622962482322461e-01 -8.090000000000000000e+02 -3.809622962482322461e-01 -8.100000000000000000e+02 -3.809622962482322461e-01 -8.110000000000000000e+02 -3.809622962482322461e-01 -8.120000000000000000e+02 -3.809622962482322461e-01 -8.130000000000000000e+02 -3.809622962482322461e-01 -8.140000000000000000e+02 -3.809622962482322461e-01 -8.150000000000000000e+02 -3.809622962482322461e-01 -8.160000000000000000e+02 -3.809622962482322461e-01 -8.170000000000000000e+02 -3.809622962482322461e-01 -8.180000000000000000e+02 -3.809622962482322461e-01 -8.190000000000000000e+02 -3.809622962482322461e-01 -8.200000000000000000e+02 -3.809622962482322461e-01 -8.210000000000000000e+02 -3.809622962482322461e-01 -8.220000000000000000e+02 -3.809622962482322461e-01 -8.230000000000000000e+02 -3.809622962482322461e-01 -8.240000000000000000e+02 -3.809622962482322461e-01 -8.250000000000000000e+02 -3.809622962482322461e-01 -8.260000000000000000e+02 -3.809622962482322461e-01 -8.270000000000000000e+02 -3.809622962482322461e-01 -8.280000000000000000e+02 -3.809622962482322461e-01 -8.290000000000000000e+02 -3.809622962482322461e-01 -8.300000000000000000e+02 -3.809622962482322461e-01 -8.310000000000000000e+02 -3.809622962482322461e-01 -8.320000000000000000e+02 -3.809622962482322461e-01 -8.330000000000000000e+02 -3.809622962482322461e-01 -8.340000000000000000e+02 -3.809622962482322461e-01 -8.350000000000000000e+02 -3.809622962482322461e-01 -8.360000000000000000e+02 -3.809622962482322461e-01 -8.370000000000000000e+02 -3.809622962482322461e-01 -8.380000000000000000e+02 -3.809622962482322461e-01 -8.390000000000000000e+02 -3.809622962482322461e-01 -8.400000000000000000e+02 -3.809622962482322461e-01 -8.410000000000000000e+02 -3.809622962482322461e-01 -8.420000000000000000e+02 -3.809622962482322461e-01 -8.430000000000000000e+02 -3.809622962482322461e-01 -8.440000000000000000e+02 -3.809622962482322461e-01 -8.450000000000000000e+02 -3.809622962482322461e-01 -8.460000000000000000e+02 -3.809622962482322461e-01 -8.470000000000000000e+02 -3.809622962482322461e-01 -8.480000000000000000e+02 -3.809622962482322461e-01 -8.490000000000000000e+02 -3.809622962482322461e-01 -8.500000000000000000e+02 -3.809622962482322461e-01 -8.510000000000000000e+02 -3.809622962482322461e-01 -8.520000000000000000e+02 -3.809622962482322461e-01 -8.530000000000000000e+02 -3.809622962482322461e-01 -8.540000000000000000e+02 -3.809622962482322461e-01 -8.550000000000000000e+02 -3.809622962482322461e-01 -8.560000000000000000e+02 -3.809622962482322461e-01 -8.570000000000000000e+02 -3.809622962482322461e-01 -8.580000000000000000e+02 -3.809622962482322461e-01 -8.590000000000000000e+02 -3.809622962482322461e-01 -8.600000000000000000e+02 -3.809622962482322461e-01 -8.610000000000000000e+02 -3.809622962482322461e-01 -8.620000000000000000e+02 -3.809622962482322461e-01 -8.630000000000000000e+02 -3.809622962482322461e-01 -8.640000000000000000e+02 -3.809622962482322461e-01 -8.650000000000000000e+02 -3.809622962482322461e-01 -8.660000000000000000e+02 -3.809622962482322461e-01 -8.670000000000000000e+02 -3.809622962482322461e-01 -8.680000000000000000e+02 -3.809622962482322461e-01 -8.690000000000000000e+02 -3.809622962482322461e-01 -8.700000000000000000e+02 -3.809622962482322461e-01 -8.710000000000000000e+02 -3.809622962482322461e-01 -8.720000000000000000e+02 -3.809622962482322461e-01 -8.730000000000000000e+02 -3.809622962482322461e-01 -8.740000000000000000e+02 -3.809622962482322461e-01 -8.750000000000000000e+02 -3.809622962482322461e-01 -8.760000000000000000e+02 -3.809622962482322461e-01 -8.770000000000000000e+02 -3.809622962482322461e-01 -8.780000000000000000e+02 -3.809622962482322461e-01 -8.790000000000000000e+02 -3.809622962482322461e-01 -8.800000000000000000e+02 -3.809622962482322461e-01 -8.810000000000000000e+02 -3.809622962482322461e-01 -8.820000000000000000e+02 -3.809622962482322461e-01 -8.830000000000000000e+02 -3.809622962482322461e-01 -8.840000000000000000e+02 -3.809622962482322461e-01 -8.850000000000000000e+02 -3.809622962482322461e-01 -8.860000000000000000e+02 -3.809622962482322461e-01 -8.870000000000000000e+02 -3.809622962482322461e-01 -8.880000000000000000e+02 -3.809622962482322461e-01 -8.890000000000000000e+02 -3.809622962482322461e-01 -8.900000000000000000e+02 -3.809622962482322461e-01 -8.910000000000000000e+02 -3.809622962482322461e-01 -8.920000000000000000e+02 -3.809622962482322461e-01 -8.930000000000000000e+02 -3.809622962482322461e-01 -8.940000000000000000e+02 -3.809622962482322461e-01 -8.950000000000000000e+02 -3.809622962482322461e-01 -8.960000000000000000e+02 -3.809622962482322461e-01 -8.970000000000000000e+02 -3.809622962482322461e-01 -8.980000000000000000e+02 -3.809622962482322461e-01 -8.990000000000000000e+02 -3.809622962482322461e-01 -9.000000000000000000e+02 -3.809622962482322461e-01 -9.010000000000000000e+02 -3.809622962482322461e-01 -9.020000000000000000e+02 -3.809622962482322461e-01 -9.030000000000000000e+02 -3.809622962482322461e-01 -9.040000000000000000e+02 -3.809622962482322461e-01 -9.050000000000000000e+02 -3.809622962482322461e-01 -9.060000000000000000e+02 -3.809622962482322461e-01 -9.070000000000000000e+02 -3.809622962482322461e-01 -9.080000000000000000e+02 -3.809622962482322461e-01 -9.090000000000000000e+02 -3.809622962482322461e-01 -9.100000000000000000e+02 -3.809622962482322461e-01 -9.110000000000000000e+02 -3.809622962482322461e-01 -9.120000000000000000e+02 -3.809622962482322461e-01 -9.130000000000000000e+02 -3.809622962482322461e-01 -9.140000000000000000e+02 -3.809622962482322461e-01 -9.150000000000000000e+02 -3.809622962482322461e-01 -9.160000000000000000e+02 -3.809622962482322461e-01 -9.170000000000000000e+02 -3.809622962482322461e-01 -9.180000000000000000e+02 -3.809622962482322461e-01 -9.190000000000000000e+02 -3.809622962482322461e-01 -9.200000000000000000e+02 -3.809622962482322461e-01 -9.210000000000000000e+02 -3.809622962482322461e-01 -9.220000000000000000e+02 -3.809622962482322461e-01 -9.230000000000000000e+02 -3.809622962482322461e-01 -9.240000000000000000e+02 -3.809622962482322461e-01 -9.250000000000000000e+02 -3.809622962482322461e-01 -9.260000000000000000e+02 -3.809622962482322461e-01 -9.270000000000000000e+02 -3.809622962482322461e-01 -9.280000000000000000e+02 -3.809622962482322461e-01 -9.290000000000000000e+02 -3.809622962482322461e-01 -9.300000000000000000e+02 -3.809622962482322461e-01 -9.310000000000000000e+02 -3.809622962482322461e-01 -9.320000000000000000e+02 -3.809622962482322461e-01 -9.330000000000000000e+02 -3.809622962482322461e-01 -9.340000000000000000e+02 -3.809622962482322461e-01 -9.350000000000000000e+02 -3.809622962482322461e-01 -9.360000000000000000e+02 -3.809622962482322461e-01 -9.370000000000000000e+02 -3.809622962482322461e-01 -9.380000000000000000e+02 -3.809622962482322461e-01 -9.390000000000000000e+02 -3.809622962482322461e-01 -9.400000000000000000e+02 -3.809622962482322461e-01 -9.410000000000000000e+02 -3.809622962482322461e-01 -9.420000000000000000e+02 -3.809622962482322461e-01 -9.430000000000000000e+02 -3.809622962482322461e-01 -9.440000000000000000e+02 -3.809622962482322461e-01 -9.450000000000000000e+02 -3.809622962482322461e-01 -9.460000000000000000e+02 -3.809622962482322461e-01 -9.470000000000000000e+02 -3.809622962482322461e-01 -9.480000000000000000e+02 -3.809622962482322461e-01 -9.490000000000000000e+02 -3.809622962482322461e-01 -9.500000000000000000e+02 -3.809622962482322461e-01 -9.510000000000000000e+02 -3.809622962482322461e-01 -9.520000000000000000e+02 -3.809622962482322461e-01 -9.530000000000000000e+02 -3.809622962482322461e-01 -9.540000000000000000e+02 -3.809622962482322461e-01 -9.550000000000000000e+02 -3.809622962482322461e-01 -9.560000000000000000e+02 -3.809622962482322461e-01 -9.570000000000000000e+02 -3.809622962482322461e-01 -9.580000000000000000e+02 -3.809622962482322461e-01 -9.590000000000000000e+02 -3.809622962482322461e-01 -9.600000000000000000e+02 -3.809622962482322461e-01 -9.610000000000000000e+02 -3.809622962482322461e-01 -9.620000000000000000e+02 -3.809622962482322461e-01 -9.630000000000000000e+02 -3.809622962482322461e-01 -9.640000000000000000e+02 -3.809622962482322461e-01 -9.650000000000000000e+02 -3.809622962482322461e-01 -9.660000000000000000e+02 -3.809622962482322461e-01 -9.670000000000000000e+02 -3.809622962482322461e-01 -9.680000000000000000e+02 -3.809622962482322461e-01 -9.690000000000000000e+02 -3.809622962482322461e-01 -9.700000000000000000e+02 -3.809622962482322461e-01 -9.710000000000000000e+02 -3.809622962482322461e-01 -9.720000000000000000e+02 -3.809622962482322461e-01 -9.730000000000000000e+02 -3.809622962482322461e-01 -9.740000000000000000e+02 -3.809622962482322461e-01 -9.750000000000000000e+02 -3.809622962482322461e-01 -9.760000000000000000e+02 -3.809622962482322461e-01 -9.770000000000000000e+02 -3.809622962482322461e-01 -9.780000000000000000e+02 -3.809622962482322461e-01 -9.790000000000000000e+02 -3.809622962482322461e-01 -9.800000000000000000e+02 -3.809622962482322461e-01 -9.810000000000000000e+02 -3.809622962482322461e-01 -9.820000000000000000e+02 -3.809622962482322461e-01 -9.830000000000000000e+02 -3.809622962482322461e-01 -9.840000000000000000e+02 -3.809622962482322461e-01 -9.850000000000000000e+02 -3.809622962482322461e-01 -9.860000000000000000e+02 -3.809622962482322461e-01 -9.870000000000000000e+02 -3.809622962482322461e-01 -9.880000000000000000e+02 -3.809622962482322461e-01 -9.890000000000000000e+02 -3.809622962482322461e-01 -9.900000000000000000e+02 -3.809622962482322461e-01 -9.910000000000000000e+02 -3.809622962482322461e-01 -9.920000000000000000e+02 -3.809622962482322461e-01 -9.930000000000000000e+02 -3.809622962482322461e-01 -9.940000000000000000e+02 -3.809622962482322461e-01 -9.950000000000000000e+02 -3.809622962482322461e-01 -9.960000000000000000e+02 -3.809622962482322461e-01 -9.970000000000000000e+02 -3.809622962482322461e-01 -9.980000000000000000e+02 -3.809622962482322461e-01 -9.990000000000000000e+02 -3.809622962482322461e-01 -1.000000000000000000e+03 -3.809622962482322461e-01 -1.001000000000000000e+03 -3.809622962482322461e-01 -1.002000000000000000e+03 -3.809622962482322461e-01 -1.003000000000000000e+03 -3.809622962482322461e-01 -1.004000000000000000e+03 -3.809622962482322461e-01 -1.005000000000000000e+03 -3.809622962482322461e-01 -1.006000000000000000e+03 -3.809622962482322461e-01 -1.007000000000000000e+03 -3.809622962482322461e-01 -1.008000000000000000e+03 -3.809622962482322461e-01 -1.009000000000000000e+03 -3.809622962482322461e-01 -1.010000000000000000e+03 -3.809622962482322461e-01 -1.011000000000000000e+03 -3.809622962482322461e-01 -1.012000000000000000e+03 -3.809622962482322461e-01 -1.013000000000000000e+03 -3.809622962482322461e-01 -1.014000000000000000e+03 -3.809622962482322461e-01 -1.015000000000000000e+03 -3.809622962482322461e-01 -1.016000000000000000e+03 -3.809622962482322461e-01 -1.017000000000000000e+03 -3.809622962482322461e-01 -1.018000000000000000e+03 -3.809622962482322461e-01 -1.019000000000000000e+03 -3.809622962482322461e-01 -1.020000000000000000e+03 -3.809622962482322461e-01 -1.021000000000000000e+03 -3.809622962482322461e-01 -1.022000000000000000e+03 -3.809622962482322461e-01 -1.023000000000000000e+03 -3.809622962482322461e-01 -1.024000000000000000e+03 -3.809622962482322461e-01 -1.025000000000000000e+03 -3.809622962482322461e-01 -1.026000000000000000e+03 -3.809622962482322461e-01 -1.027000000000000000e+03 -3.809622962482322461e-01 -1.028000000000000000e+03 -3.809622962482322461e-01 -1.029000000000000000e+03 -3.809622962482322461e-01 -1.030000000000000000e+03 -3.809622962482322461e-01 -1.031000000000000000e+03 -3.809622962482322461e-01 -1.032000000000000000e+03 -3.809622962482322461e-01 -1.033000000000000000e+03 -3.809622962482322461e-01 -1.034000000000000000e+03 -3.809622962482322461e-01 -1.035000000000000000e+03 -3.809622962482322461e-01 -1.036000000000000000e+03 -3.809622962482322461e-01 -1.037000000000000000e+03 -3.809622962482322461e-01 -1.038000000000000000e+03 -3.809622962482322461e-01 -1.039000000000000000e+03 -3.809622962482322461e-01 -1.040000000000000000e+03 -3.809622962482322461e-01 -1.041000000000000000e+03 -3.809622962482322461e-01 -1.042000000000000000e+03 -3.809622962482322461e-01 -1.043000000000000000e+03 -3.809622962482322461e-01 -1.044000000000000000e+03 -3.809622962482322461e-01 -1.045000000000000000e+03 -3.809622962482322461e-01 -1.046000000000000000e+03 -3.809622962482322461e-01 -1.047000000000000000e+03 -3.809622962482322461e-01 -1.048000000000000000e+03 -3.809622962482322461e-01 -1.049000000000000000e+03 -3.809622962482322461e-01 -1.050000000000000000e+03 -3.809622962482322461e-01 -1.051000000000000000e+03 -3.809622962482322461e-01 -1.052000000000000000e+03 -3.809622962482322461e-01 -1.053000000000000000e+03 -3.809622962482322461e-01 -1.054000000000000000e+03 -3.809622962482322461e-01 -1.055000000000000000e+03 -3.809622962482322461e-01 -1.056000000000000000e+03 -3.809622962482322461e-01 -1.057000000000000000e+03 -3.809622962482322461e-01 -1.058000000000000000e+03 -3.809622962482322461e-01 -1.059000000000000000e+03 -3.809622962482322461e-01 -1.060000000000000000e+03 -3.809622962482322461e-01 -1.061000000000000000e+03 -3.809622962482322461e-01 -1.062000000000000000e+03 -3.809622962482322461e-01 -1.063000000000000000e+03 -3.809622962482322461e-01 -1.064000000000000000e+03 -3.809622962482322461e-01 -1.065000000000000000e+03 -3.809622962482322461e-01 -1.066000000000000000e+03 -3.809622962482322461e-01 -1.067000000000000000e+03 -3.809622962482322461e-01 -1.068000000000000000e+03 -3.809622962482322461e-01 -1.069000000000000000e+03 -3.809622962482322461e-01 -1.070000000000000000e+03 -3.809622962482322461e-01 -1.071000000000000000e+03 -3.809622962482322461e-01 -1.072000000000000000e+03 -3.809622962482322461e-01 -1.073000000000000000e+03 -3.809622962482322461e-01 -1.074000000000000000e+03 -3.809622962482322461e-01 -1.075000000000000000e+03 -3.809622962482322461e-01 -1.076000000000000000e+03 -3.809622962482322461e-01 -1.077000000000000000e+03 -3.809622962482322461e-01 -1.078000000000000000e+03 -3.809622962482322461e-01 -1.079000000000000000e+03 -3.809622962482322461e-01 -1.080000000000000000e+03 -3.809622962482322461e-01 -1.081000000000000000e+03 -3.809622962482322461e-01 -1.082000000000000000e+03 -3.809622962482322461e-01 -1.083000000000000000e+03 -3.809622962482322461e-01 -1.084000000000000000e+03 -3.809622962482322461e-01 -1.085000000000000000e+03 -3.809622962482322461e-01 -1.086000000000000000e+03 -3.809622962482322461e-01 -1.087000000000000000e+03 -3.809622962482322461e-01 -1.088000000000000000e+03 -3.809622962482322461e-01 -1.089000000000000000e+03 -3.809622962482322461e-01 -1.090000000000000000e+03 -3.809622962482322461e-01 -1.091000000000000000e+03 -3.809622962482322461e-01 -1.092000000000000000e+03 -3.809622962482322461e-01 -1.093000000000000000e+03 -3.809622962482322461e-01 -1.094000000000000000e+03 -3.809622962482322461e-01 -1.095000000000000000e+03 -3.809622962482322461e-01 -1.096000000000000000e+03 -3.809622962482319686e-01 -1.097000000000000000e+03 -3.809622962482319686e-01 -1.098000000000000000e+03 -3.809622962482319686e-01 -1.099000000000000000e+03 -3.809622962482319686e-01 +3.000000000000000000e+02 1.375196993384676658e-01 +3.010000000000000000e+02 1.148794318163027517e-01 +3.020000000000000000e+02 9.490222350357831183e-02 +3.030000000000000000e+02 7.735086209745876962e-02 +3.040000000000000000e+02 6.204249593194603035e-02 +3.050000000000000000e+02 4.884053055081664929e-02 +3.060000000000000000e+02 3.764863700539566871e-02 +3.070000000000000000e+02 2.840642566497900492e-02 +3.080000000000000000e+02 2.108646405197598522e-02 +3.090000000000000000e+02 1.569240891423372142e-02 +3.100000000000000000e+02 1.225809106846927933e-02 +3.110000000000000000e+02 1.084744315406127764e-02 +3.120000000000000000e+02 1.155519988046073768e-02 +3.130000000000000000e+02 1.450833065473079546e-02 +3.140000000000000000e+02 1.986818747794508871e-02 +3.150000000000000000e+02 2.783336754907148047e-02 +3.160000000000000000e+02 3.864330002388263741e-02 +3.170000000000000000e+02 5.258256875017554288e-02 +3.180000000000000000e+02 6.998597524809667403e-02 +3.190000000000000000e+02 9.124432491347865548e-02 +3.200000000000000000e+02 1.168108785874574784e-01 +3.210000000000000000e+02 1.472083428297892016e-01 +3.220000000000000000e+02 1.830361636383368018e-01 +3.230000000000000000e+02 2.249777239274205198e-01 +3.240000000000000000e+02 2.738068038371947455e-01 +3.250000000000000000e+02 3.303923188433796621e-01 +3.260000000000000000e+02 3.956998737968978608e-01 +3.270000000000000000e+02 4.707880318944210885e-01 +3.280000000000000000e+02 5.567963764265303483e-01 +3.290000000000000000e+02 6.549214486136448743e-01 +3.300000000000000000e+02 7.663755463830008718e-01 +3.310000000000000000e+02 8.923223478884041437e-01 +3.320000000000000000e+02 1.033782743649253488e+00 +3.330000000000000000e+02 1.191504747417050591e+00 +3.340000000000000000e+02 1.365793844438335514e+00 +3.350000000000000000e+02 1.556305812750571782e+00 +3.360000000000000000e+02 1.761814046349465590e+00 +3.370000000000000000e+02 1.979978076965569489e+00 +3.380000000000000000e+02 2.207157762071574769e+00 +3.390000000000000000e+02 2.438333688155275958e+00 +3.400000000000000000e+02 2.667200261324630173e+00 +3.410000000000000000e+02 2.886483478563668381e+00 +3.420000000000000000e+02 3.088493799912809479e+00 +3.430000000000000000e+02 3.265860129939112788e+00 +3.440000000000000000e+02 3.412323289469711529e+00 +3.450000000000000000e+02 3.523426536989169300e+00 +3.460000000000000000e+02 3.596951493602348560e+00 +3.470000000000000000e+02 3.633012480717904946e+00 +3.480000000000000000e+02 3.633815578688332160e+00 +3.490000000000000000e+02 3.603171672419537952e+00 +3.500000000000000000e+02 3.545895217416231038e+00 +3.510000000000000000e+02 3.467215628879384060e+00 +3.520000000000000000e+02 3.372290487892572575e+00 +3.530000000000000000e+02 3.265861698961923576e+00 +3.540000000000000000e+02 3.152055284182587069e+00 +3.550000000000000000e+02 3.034300699151680103e+00 +3.560000000000000000e+02 2.915335977922085764e+00 +3.570000000000000000e+02 2.797266005484678963e+00 +3.580000000000000000e+02 2.681647557543167082e+00 +3.590000000000000000e+02 2.569582530867592585e+00 +3.600000000000000000e+02 2.461807804650376852e+00 +3.610000000000000000e+02 2.358775552840453926e+00 +3.620000000000000000e+02 2.260721498246372807e+00 +3.630000000000000000e+02 2.167720853860855890e+00 +3.640000000000000000e+02 2.079732922657751892e+00 +3.650000000000000000e+02 1.996635874843193603e+00 +3.660000000000000000e+02 1.918253360365562710e+00 +3.670000000000000000e+02 1.844374530598193340e+00 +3.680000000000000000e+02 1.774768855344367013e+00 +3.690000000000000000e+02 1.709196900025830690e+00 +3.700000000000000000e+02 1.647418011294166762e+00 +3.710000000000000000e+02 1.589195665544876679e+00 +3.720000000000000000e+02 1.534301070485480034e+00 +3.730000000000000000e+02 1.482515475295091534e+00 +3.740000000000000000e+02 1.433631537264090428e+00 +3.750000000000000000e+02 1.387454008208677925e+00 +3.760000000000000000e+02 1.343799938341827538e+00 +3.770000000000000000e+02 1.302498544902949806e+00 +3.780000000000000000e+02 1.263390854475725300e+00 +3.790000000000000000e+02 1.226329198890880878e+00 +3.800000000000000000e+02 1.191176622770828697e+00 +3.810000000000000000e+02 1.157806244429178344e+00 +3.820000000000000000e+02 1.126100599671812530e+00 +3.830000000000000000e+02 1.095950989035169965e+00 +3.840000000000000000e+02 1.067256842364508573e+00 +3.850000000000000000e+02 1.039925109782515511e+00 +3.860000000000000000e+02 1.013869684581203190e+00 +3.870000000000000000e+02 9.890108610420870194e-01 +3.880000000000000000e+02 9.652748284003803692e-01 +3.890000000000000000e+02 9.425932009233340958e-01 +3.900000000000000000e+02 9.209025832257614619e-01 +3.910000000000000000e+02 9.001441693940476219e-01 +3.920000000000000000e+02 8.802633741475212048e-01 +3.930000000000000000e+02 8.612094940778729502e-01 +3.940000000000000000e+02 8.429353969263738700e-01 +3.950000000000000000e+02 8.253972368534254755e-01 +3.960000000000000000e+02 8.085541937005903401e-01 +3.970000000000000000e+02 7.923682343256113203e-01 +3.980000000000000000e+02 7.768038941903562256e-01 +3.990000000000000000e+02 7.618280774948955614e-01 +4.000000000000000000e+02 7.474098742678558782e-01 +4.010000000000000000e+02 7.335203929410564205e-01 +4.020000000000000000e+02 7.201326070526395950e-01 +4.030000000000000000e+02 7.072212148329793946e-01 +4.040000000000000000e+02 6.947625105339171325e-01 +4.050000000000000000e+02 6.827342664594757693e-01 +4.060000000000000000e+02 6.711156247489294957e-01 +4.070000000000000000e+02 6.598869980471987473e-01 +4.080000000000000000e+02 6.490299782761819181e-01 +4.090000000000000000e+02 6.385272527920262675e-01 +4.100000000000000000e+02 6.283625272786078630e-01 +4.110000000000000000e+02 6.185204547874053604e-01 +4.120000000000000000e+02 6.089865703880761316e-01 +4.130000000000000000e+02 5.997472309431893800e-01 +4.140000000000000000e+02 5.907895595655281440e-01 +4.150000000000000000e+02 5.821013943568177362e-01 +4.160000000000000000e+02 5.736712410634341452e-01 +4.170000000000000000e+02 5.654882293179414043e-01 +4.180000000000000000e+02 5.575420721653520095e-01 +4.190000000000000000e+02 5.498230286005463263e-01 +4.200000000000000000e+02 5.423218688674458221e-01 +4.210000000000000000e+02 5.350298422933366105e-01 +4.220000000000000000e+02 5.279386474518455996e-01 +4.230000000000000000e+02 5.210404044660734701e-01 +4.240000000000000000e+02 5.143276292804849215e-01 +4.250000000000000000e+02 5.077932097447476201e-01 +4.260000000000000000e+02 5.014303833665973986e-01 +4.270000000000000000e+02 4.952327166030171535e-01 +4.280000000000000000e+02 4.891940855703422741e-01 +4.290000000000000000e+02 4.833086580639807672e-01 +4.300000000000000000e+02 4.775708767877461236e-01 +4.310000000000000000e+02 4.719754437012009252e-01 +4.320000000000000000e+02 4.665173054010368081e-01 +4.330000000000000000e+02 4.611916394594177682e-01 +4.340000000000000000e+02 4.559938416486444823e-01 +4.350000000000000000e+02 4.509195139872385072e-01 +4.360000000000000000e+02 4.459644535476448013e-01 +4.370000000000000000e+02 4.411246419708694799e-01 +4.380000000000000000e+02 4.363962356373117801e-01 +4.390000000000000000e+02 4.317755564475641572e-01 +4.400000000000000000e+02 4.272590831700543434e-01 +4.410000000000000000e+02 4.228434433161886163e-01 +4.420000000000000000e+02 4.185254055065021350e-01 +4.430000000000000000e+02 4.143018722940978171e-01 +4.440000000000000000e+02 4.101698734143596203e-01 +4.450000000000000000e+02 4.061265594321264993e-01 +4.460000000000000000e+02 4.021691957597747780e-01 +4.470000000000000000e+02 3.982951570215663151e-01 +4.480000000000000000e+02 3.945019217415195456e-01 +4.490000000000000000e+02 3.907870673336293899e-01 +4.500000000000000000e+02 3.871482653748795633e-01 +4.510000000000000000e+02 3.835832771428268617e-01 +4.520000000000000000e+02 3.800899494009965518e-01 +4.530000000000000000e+02 3.766662104162896152e-01 +4.540000000000000000e+02 3.733100661939305898e-01 +4.550000000000000000e+02 3.700195969163551646e-01 +4.560000000000000000e+02 3.667929535734908431e-01 +4.570000000000000000e+02 3.636283547726303356e-01 +4.580000000000000000e+02 3.605240837170427537e-01 +4.590000000000000000e+02 3.574784853431044462e-01 +4.600000000000000000e+02 3.544899636064058335e-01 +4.610000000000000000e+02 3.515569789080635887e-01 +4.620000000000000000e+02 3.486780456529197103e-01 +4.630000000000000000e+02 3.458517299319014970e-01 +4.640000000000000000e+02 3.430766473212945589e-01 +4.650000000000000000e+02 3.403514607922722979e-01 +4.660000000000000000e+02 3.376748787242742078e-01 +4.670000000000000000e+02 3.350456530163856694e-01 +4.680000000000000000e+02 3.324625772911450339e-01 +4.690000000000000000e+02 3.299244851856524829e-01 +4.700000000000000000e+02 3.274302487250633220e-01 +4.710000000000000000e+02 3.249787767739680810e-01 +4.720000000000000000e+02 3.225690135613545895e-01 +4.730000000000000000e+02 3.201999372751603845e-01 +4.740000000000000000e+02 3.178705587226478002e-01 +4.750000000000000000e+02 3.155799200530782223e-01 +4.760000000000000000e+02 3.133270935393506207e-01 +4.770000000000000000e+02 3.111111804154868543e-01 +4.780000000000000000e+02 3.089313097670201014e-01 +4.790000000000000000e+02 3.067866374715769728e-01 +4.800000000000000000e+02 3.046763451869432537e-01 +4.810000000000000000e+02 3.025996393842827481e-01 +4.820000000000000000e+02 3.005557504241232469e-01 +4.830000000000000000e+02 2.985439316729701642e-01 +4.840000000000000000e+02 2.965634586584907639e-01 +4.850000000000000000e+02 2.946136282613167068e-01 +4.860000000000000000e+02 2.926937579416843960e-01 +4.870000000000000000e+02 2.908031849991328799e-01 +4.880000000000000000e+02 2.889412658636900111e-01 +4.890000000000000000e+02 2.871073754169614078e-01 +4.900000000000000000e+02 2.853009063417092928e-01 +4.910000000000000000e+02 2.835212684985126685e-01 +4.920000000000000000e+02 2.817678883282564439e-01 +4.930000000000000000e+02 2.800402082791625946e-01 +4.940000000000000000e+02 2.783376862572609078e-01 +4.950000000000000000e+02 2.766597950991546151e-01 +4.960000000000000000e+02 2.750060220660593413e-01 +4.970000000000000000e+02 2.733758683581199445e-01 +4.980000000000000000e+02 2.717688486480933086e-01 +4.990000000000000000e+02 2.701844906334607277e-01 +5.000000000000000000e+02 2.686223346061878958e-01 +5.010000000000000000e+02 2.670819330392825708e-01 +5.020000000000000000e+02 2.655628501894329307e-01 +5.030000000000000000e+02 2.640646617149829400e-01 +5.040000000000000000e+02 2.625869543085715407e-01 +5.050000000000000000e+02 2.611293253437843576e-01 +5.060000000000000000e+02 2.596913825352153982e-01 +5.070000000000000000e+02 2.582727436113309016e-01 +5.080000000000000000e+02 2.568730359995868850e-01 +5.090000000000000000e+02 2.554918965232875205e-01 +5.100000000000000000e+02 2.541289711096627602e-01 +5.110000000000000000e+02 2.527839145086937522e-01 +5.120000000000000000e+02 2.514563900222213100e-01 +5.130000000000000000e+02 2.501460692429048338e-01 +5.140000000000000000e+02 2.488526318026602346e-01 +5.150000000000000000e+02 2.475757651300865558e-01 +5.160000000000000000e+02 2.463151642166299671e-01 +5.170000000000000000e+02 2.450705313910027938e-01 +5.180000000000000000e+02 2.438415761016357597e-01 +5.190000000000000000e+02 2.426280147067272908e-01 +5.200000000000000000e+02 2.414295702716698078e-01 +5.210000000000000000e+02 2.402459723734994834e-01 +5.220000000000000000e+02 2.390769569121214688e-01 +5.230000000000000000e+02 2.379222659279945085e-01 +5.240000000000000000e+02 2.367816474261073556e-01 +5.250000000000000000e+02 2.356548552058783941e-01 +5.260000000000000000e+02 2.345416486968476544e-01 +5.270000000000000000e+02 2.334417927998909958e-01 +5.280000000000000000e+02 2.323550577337347989e-01 +5.290000000000000000e+02 2.312812188865958907e-01 +5.300000000000000000e+02 2.302200566727157782e-01 +5.310000000000000000e+02 2.291713563936337017e-01 +5.320000000000000000e+02 2.281349081040016658e-01 +5.330000000000000000e+02 2.271105064817594554e-01 +5.340000000000000000e+02 2.260979507025354940e-01 +5.350000000000000000e+02 2.250970443180893843e-01 +5.360000000000000000e+02 2.241075951386504728e-01 +5.370000000000000000e+02 2.231294151190162389e-01 +5.380000000000000000e+02 2.221623202482787551e-01 +5.390000000000000000e+02 2.212061304430074093e-01 +5.400000000000000000e+02 2.202606694438176416e-01 +5.410000000000000000e+02 2.193257647151560519e-01 +5.420000000000000000e+02 2.184012473482151162e-01 +5.430000000000000000e+02 2.174869519668403695e-01 +5.440000000000000000e+02 2.165827166363491763e-01 +5.450000000000000000e+02 2.156883827751495675e-01 +5.460000000000000000e+02 2.148037950690249442e-01 +5.470000000000000000e+02 2.139288013880628614e-01 +5.480000000000000000e+02 2.130632527060586923e-01 +5.490000000000000000e+02 2.122070030223569270e-01 +5.500000000000000000e+02 2.113599092860327378e-01 +5.510000000000000000e+02 2.105218313223237991e-01 +5.520000000000000000e+02 2.096926317612486379e-01 +5.530000000000000000e+02 2.088721759683206114e-01 +5.540000000000000000e+02 2.080603319772994231e-01 +5.550000000000000000e+02 2.072569704249176969e-01 +5.560000000000000000e+02 2.064619644874903792e-01 +5.570000000000000000e+02 2.056751898193578953e-01 +5.580000000000000000e+02 2.048965244931146568e-01 +5.590000000000000000e+02 2.041258489415463395e-01 +5.600000000000000000e+02 2.033630459012148728e-01 +5.610000000000000000e+02 2.026080003576562205e-01 +5.620000000000000000e+02 2.018605994921285063e-01 +5.630000000000000000e+02 2.011207326298440901e-01 +5.640000000000000000e+02 2.003882911896737729e-01 +5.650000000000000000e+02 1.996631686352361712e-01 +5.660000000000000000e+02 1.989452604273535263e-01 +5.670000000000000000e+02 1.982344639778164663e-01 +5.680000000000000000e+02 1.975306786044317420e-01 +5.690000000000000000e+02 1.968338054872833531e-01 +5.700000000000000000e+02 1.961437476262080093e-01 +5.710000000000000000e+02 1.954604097994022405e-01 +5.720000000000000000e+02 1.947836985231734819e-01 +5.730000000000000000e+02 1.941135220127536698e-01 +5.740000000000000000e+02 1.934497901441677992e-01 +5.750000000000000000e+02 1.927924144171384302e-01 +5.760000000000000000e+02 1.921413079189405460e-01 +5.770000000000000000e+02 1.914963852892475060e-01 +5.780000000000000000e+02 1.908575626858804164e-01 +5.790000000000000000e+02 1.902247577514702692e-01 +5.800000000000000000e+02 1.895978895809742881e-01 +5.810000000000000000e+02 1.889768786900545006e-01 +5.820000000000000000e+02 1.883616469842668839e-01 +5.830000000000000000e+02 1.877521177290443766e-01 +5.840000000000000000e+02 1.871482155204517717e-01 +5.850000000000000000e+02 1.865498662566866805e-01 +5.860000000000000000e+02 1.859569971103169073e-01 +5.870000000000000000e+02 1.853695365012026919e-01 +5.880000000000000000e+02 1.847874140701262768e-01 +5.890000000000000000e+02 1.842105606530616557e-01 +5.900000000000000000e+02 1.836389082561044050e-01 +5.910000000000000000e+02 1.830723900310256558e-01 +5.920000000000000000e+02 1.825109402514278889e-01 +5.930000000000000000e+02 1.819544942894908701e-01 +5.940000000000000000e+02 1.814029885932988695e-01 +5.950000000000000000e+02 1.808563606647166366e-01 +5.960000000000000000e+02 1.803145490378097460e-01 +5.970000000000000000e+02 1.797774932577902163e-01 +5.980000000000000000e+02 1.792451338604707789e-01 +5.990000000000000000e+02 1.787174123522242697e-01 +6.000000000000000000e+02 1.781942711904106469e-01 +6.010000000000000000e+02 1.776756537642888711e-01 +6.020000000000000000e+02 1.771615043435660064e-01 +6.030000000000000000e+02 1.766517681917462446e-01 +6.040000000000000000e+02 1.761463913827418515e-01 +6.050000000000000000e+02 1.756453207867278987e-01 +6.060000000000000000e+02 1.751485042140254467e-01 +6.070000000000000000e+02 1.746558902689490100e-01 +6.080000000000000000e+02 1.741674283661302780e-01 +6.090000000000000000e+02 1.736830687147430941e-01 +6.100000000000000000e+02 1.732027623030943653e-01 +6.110000000000000000e+02 1.727264608835598625e-01 +6.120000000000000000e+02 1.722541169578780673e-01 +6.130000000000000000e+02 1.717856837627745048e-01 +6.140000000000000000e+02 1.713211152559170058e-01 +6.150000000000000000e+02 1.708603661021853293e-01 +6.160000000000000000e+02 1.704033916602639420e-01 +6.170000000000000000e+02 1.699501479695191275e-01 +6.180000000000000000e+02 1.695005917371882054e-01 +6.190000000000000000e+02 1.690546803258453357e-01 +6.200000000000000000e+02 1.686123717411563694e-01 +6.210000000000000000e+02 1.681736246198889118e-01 +6.220000000000000000e+02 1.677383982182137079e-01 +6.230000000000000000e+02 1.673066524002369548e-01 +6.240000000000000000e+02 1.668783476268080046e-01 +6.250000000000000000e+02 1.664534449445581321e-01 +6.260000000000000000e+02 1.660319059751846904e-01 +6.270000000000000000e+02 1.656136929049655537e-01 +6.280000000000000000e+02 1.651987684745031826e-01 +6.290000000000000000e+02 1.647870959686940084e-01 +6.300000000000000000e+02 1.643786392069029323e-01 +6.310000000000000000e+02 1.639733625333615885e-01 +6.320000000000000000e+02 1.635712308077605370e-01 +6.330000000000000000e+02 1.631722093960533970e-01 +6.340000000000000000e+02 1.627762641614442785e-01 +6.350000000000000000e+02 1.623833614555767191e-01 +6.360000000000000000e+02 1.619934681099056972e-01 +6.370000000000000000e+02 1.616065514272382597e-01 +6.380000000000000000e+02 1.612225791734774594e-01 +6.390000000000000000e+02 1.608415195695130917e-01 +6.400000000000000000e+02 1.604633412832952855e-01 +6.410000000000000000e+02 1.600880134220697970e-01 +6.420000000000000000e+02 1.597155055247714561e-01 +6.430000000000000000e+02 1.593457875545740698e-01 +6.440000000000000000e+02 1.589788298916008091e-01 +6.450000000000000000e+02 1.586146033257733734e-01 +6.460000000000000000e+02 1.582530790498115625e-01 +6.470000000000000000e+02 1.578942286523798422e-01 +6.480000000000000000e+02 1.575380241113608637e-01 +6.490000000000000000e+02 1.571844377872793352e-01 +6.500000000000000000e+02 1.568334424168470187e-01 +6.510000000000000000e+02 1.564850111066434790e-01 +6.520000000000000000e+02 1.561391173269168764e-01 +6.530000000000000000e+02 1.557957349055201779e-01 +6.540000000000000000e+02 1.554548380219512305e-01 +6.550000000000000000e+02 1.551164012015274762e-01 +6.560000000000000000e+02 1.547803993096629471e-01 +6.570000000000000000e+02 1.544468075462648027e-01 +6.580000000000000000e+02 1.541156014402393082e-01 +6.590000000000000000e+02 1.537867568440994259e-01 +6.600000000000000000e+02 1.534602499286881194e-01 +6.610000000000000000e+02 1.531360571779925017e-01 +6.620000000000000000e+02 1.528141553840649813e-01 +6.630000000000000000e+02 1.524945216420463545e-01 +6.640000000000000000e+02 1.521771333452694164e-01 +6.650000000000000000e+02 1.518619681804810606e-01 +6.660000000000000000e+02 1.515490041231268015e-01 +6.670000000000000000e+02 1.512382194327490104e-01 +6.680000000000000000e+02 1.509295926484607586e-01 +6.690000000000000000e+02 1.506231025845105598e-01 +6.700000000000000000e+02 1.503187283259222740e-01 +6.710000000000000000e+02 1.500164492242310188e-01 +6.720000000000000000e+02 1.497162448932860546e-01 +6.730000000000000000e+02 1.494180952051416267e-01 +6.740000000000000000e+02 1.491219802860143107e-01 +6.750000000000000000e+02 1.488278805123304516e-01 +6.760000000000000000e+02 1.485357765068309466e-01 +6.770000000000000000e+02 1.482456491347580174e-01 +6.780000000000000000e+02 1.479574795001100673e-01 +6.790000000000000000e+02 1.476712489419663155e-01 +6.800000000000000000e+02 1.473869390308726324e-01 +6.810000000000000000e+02 1.471045315653030650e-01 +6.820000000000000000e+02 1.468240085681773444e-01 +6.830000000000000000e+02 1.465453522834480604e-01 +6.840000000000000000e+02 1.462685451727469277e-01 +6.850000000000000000e+02 1.459935699120862851e-01 +6.860000000000000000e+02 1.457204093886343144e-01 +6.870000000000000000e+02 1.454490466975295604e-01 +6.880000000000000000e+02 1.451794651387686153e-01 +6.890000000000000000e+02 1.449116482141396545e-01 +6.900000000000000000e+02 1.446455796242149261e-01 +6.910000000000000000e+02 1.443812432653953093e-01 +6.920000000000000000e+02 1.441186232270041945e-01 +6.930000000000000000e+02 1.438577037884403720e-01 +6.940000000000000000e+02 1.435984694163715825e-01 +6.950000000000000000e+02 1.433409047619862153e-01 +6.960000000000000000e+02 1.430849946582856691e-01 +6.970000000000000000e+02 1.428307241174262832e-01 +6.980000000000000000e+02 1.425780783281141439e-01 +6.990000000000000000e+02 1.423270426530306443e-01 +7.000000000000000000e+02 1.420776026263178560e-01 +7.010000000000000000e+02 1.418297439510987079e-01 +7.020000000000000000e+02 1.415834524970389086e-01 +7.030000000000000000e+02 1.413387142979579958e-01 +7.040000000000000000e+02 1.410955155494731383e-01 +7.050000000000000000e+02 1.408538426066892890e-01 +7.060000000000000000e+02 1.406136819819222561e-01 +7.070000000000000000e+02 1.403750203424682375e-01 +7.080000000000000000e+02 1.401378445084048019e-01 +7.090000000000000000e+02 1.399021414504308669e-01 +7.100000000000000000e+02 1.396678982877458952e-01 +7.110000000000000000e+02 1.394351022859569855e-01 +7.120000000000000000e+02 1.392037408550322874e-01 +7.130000000000000000e+02 1.389738015472771759e-01 +7.140000000000000000e+02 1.387452720553528640e-01 +7.150000000000000000e+02 1.385181402103203563e-01 +7.160000000000000000e+02 1.382923939797251200e-01 +7.170000000000000000e+02 1.380680214657072358e-01 +7.180000000000000000e+02 1.378450109031419957e-01 +7.190000000000000000e+02 1.376233506578171950e-01 +7.200000000000000000e+02 1.374030292246330165e-01 +7.210000000000000000e+02 1.371840352258389684e-01 +7.220000000000000000e+02 1.369663574092904734e-01 +7.230000000000000000e+02 1.367499846467421509e-01 +7.240000000000000000e+02 1.365349059321644964e-01 +7.250000000000000000e+02 1.363211103800867352e-01 +7.260000000000000000e+02 1.361085872239716776e-01 +7.270000000000000000e+02 1.358973258146107255e-01 +7.280000000000000000e+02 1.356873156185454399e-01 +7.290000000000000000e+02 1.354785462165191412e-01 +7.300000000000000000e+02 1.352710073019500470e-01 +7.310000000000000000e+02 1.350646886794264756e-01 +7.320000000000000000e+02 1.348595802632291674e-01 +7.330000000000000000e+02 1.346556720758768644e-01 +7.340000000000000000e+02 1.344529542466919025e-01 +7.350000000000000000e+02 1.342514170103931148e-01 +7.360000000000000000e+02 1.340510507057060263e-01 +7.370000000000000000e+02 1.338518457739976686e-01 +7.380000000000000000e+02 1.336537927579313778e-01 +7.390000000000000000e+02 1.334568823001454352e-01 +7.400000000000000000e+02 1.332611051419475001e-01 +7.410000000000000000e+02 1.330664521220330521e-01 +7.420000000000000000e+02 1.328729141752216514e-01 +7.430000000000000000e+02 1.326804823312139614e-01 +7.440000000000000000e+02 1.324891477133673112e-01 +7.450000000000000000e+02 1.322989015374920752e-01 +7.460000000000000000e+02 1.321097351106583495e-01 +7.470000000000000000e+02 1.319216398300366300e-01 +7.480000000000000000e+02 1.317346071817368236e-01 +7.490000000000000000e+02 1.315486287396825937e-01 +7.500000000000000000e+02 1.313636961644892853e-01 +7.510000000000000000e+02 1.311798012023666360e-01 +7.520000000000000000e+02 1.309969356840380017e-01 +7.530000000000000000e+02 1.308150915236682699e-01 +7.540000000000000000e+02 1.306342607178183901e-01 +7.550000000000000000e+02 1.304544353444075100e-01 +7.560000000000000000e+02 1.302756075616954834e-01 +7.570000000000000000e+02 1.300977696072762868e-01 +7.580000000000000000e+02 1.299209137970908645e-01 +7.590000000000000000e+02 1.297450325244504654e-01 +7.600000000000000000e+02 1.295701182590793532e-01 +7.610000000000000000e+02 1.293961635461650939e-01 +7.620000000000000000e+02 1.292231610054299651e-01 +7.630000000000000000e+02 1.290511033302104704e-01 +7.640000000000000000e+02 1.288799832865510919e-01 +7.650000000000000000e+02 1.287097937123174718e-01 +7.660000000000000000e+02 1.285405275163115646e-01 +7.670000000000000000e+02 1.283721776774102985e-01 +7.680000000000000000e+02 1.282047372437107036e-01 +7.690000000000000000e+02 1.280381993316879186e-01 +7.700000000000000000e+02 1.278725571253688242e-01 +7.710000000000000000e+02 1.277078038755122547e-01 +7.720000000000000000e+02 1.275439328988054732e-01 +7.730000000000000000e+02 1.273809375770720564e-01 +7.740000000000000000e+02 1.272188113564852174e-01 +7.750000000000000000e+02 1.270575477468026127e-01 +7.760000000000000000e+02 1.268971403206005655e-01 +7.770000000000000000e+02 1.267375827125301058e-01 +7.780000000000000000e+02 1.265788686185743694e-01 +7.790000000000000000e+02 1.264209917953211526e-01 +7.800000000000000000e+02 1.262639460592484830e-01 +7.810000000000000000e+02 1.261077252860119124e-01 +7.820000000000000000e+02 1.259523234097486566e-01 +7.830000000000000000e+02 1.257977344223920324e-01 +7.840000000000000000e+02 1.256439523729893926e-01 +7.850000000000000000e+02 1.254909713670352700e-01 +7.860000000000000000e+02 1.253387855658114891e-01 +7.870000000000000000e+02 1.251873891857347154e-01 +7.880000000000000000e+02 1.250367764977200480e-01 +7.890000000000000000e+02 1.248869418265423359e-01 +7.900000000000000000e+02 1.247378795502165627e-01 +7.910000000000000000e+02 1.245895840993819365e-01 +7.920000000000000000e+02 1.244420499566942090e-01 +7.930000000000000000e+02 1.242952716562259613e-01 +7.940000000000000000e+02 1.241492437828803086e-01 +7.950000000000000000e+02 1.240039609718049246e-01 +7.960000000000000000e+02 1.238594179078202906e-01 +7.970000000000000000e+02 1.237156093248517608e-01 +7.980000000000000000e+02 1.235725300053710229e-01 +7.990000000000000000e+02 1.234301747798454418e-01 +8.000000000000000000e+02 1.232885385261939526e-01 +8.010000000000000000e+02 1.231476161692508092e-01 +8.020000000000000000e+02 1.230074026802350229e-01 +8.030000000000000000e+02 1.228678930762312493e-01 +8.040000000000000000e+02 1.227290824196717867e-01 +8.050000000000000000e+02 1.225909658178292172e-01 +8.060000000000000000e+02 1.224535384223158357e-01 +8.070000000000000000e+02 1.223167954285864500e-01 +8.080000000000000000e+02 1.221807320754543513e-01 +8.090000000000000000e+02 1.220453436446048839e-01 +8.100000000000000000e+02 1.219106254601221018e-01 +8.110000000000000000e+02 1.217765728880213644e-01 +8.120000000000000000e+02 1.216431813357826131e-01 +8.130000000000000000e+02 1.215104462518972472e-01 +8.140000000000000000e+02 1.213783631254127249e-01 +8.150000000000000000e+02 1.212469274854940937e-01 +8.160000000000000000e+02 1.211161349009783755e-01 +8.170000000000000000e+02 1.209859809799447711e-01 +8.180000000000000000e+02 1.208564613692843792e-01 +8.190000000000000000e+02 1.207275717542811572e-01 +8.200000000000000000e+02 1.205993078581916039e-01 +8.210000000000000000e+02 1.204716654418368504e-01 +8.220000000000000000e+02 1.203446403031917661e-01 +8.230000000000000000e+02 1.202182282769889698e-01 +8.240000000000000000e+02 1.200924252343202325e-01 +8.250000000000000000e+02 1.199672270822458447e-01 +8.260000000000000000e+02 1.198426297634096749e-01 +8.270000000000000000e+02 1.197186292556593340e-01 +8.280000000000000000e+02 1.195952215716679506e-01 +8.290000000000000000e+02 1.194724027585634535e-01 +8.300000000000000000e+02 1.193501688975628638e-01 +8.310000000000000000e+02 1.192285161036113345e-01 +8.320000000000000000e+02 1.191074405250234086e-01 +8.330000000000000000e+02 1.189869383431292338e-01 +8.340000000000000000e+02 1.188670057719286438e-01 +8.350000000000000000e+02 1.187476390577470314e-01 +8.360000000000000000e+02 1.186288344788918869e-01 +8.370000000000000000e+02 1.185105883453243109e-01 +8.380000000000000000e+02 1.183928969983197715e-01 +8.390000000000000000e+02 1.182757568101472367e-01 +8.400000000000000000e+02 1.181591641837432677e-01 +8.410000000000000000e+02 1.180431155523922887e-01 +8.420000000000000000e+02 1.179276073794141844e-01 +8.430000000000000000e+02 1.178126361578502035e-01 +8.440000000000000000e+02 1.176981984101587025e-01 +8.450000000000000000e+02 1.175842906879083216e-01 +8.460000000000000000e+02 1.174709095714794732e-01 +8.470000000000000000e+02 1.173580516697685372e-01 +8.480000000000000000e+02 1.172457136198948729e-01 +8.490000000000000000e+02 1.171338920869120920e-01 +8.500000000000000000e+02 1.170225837635221894e-01 +8.510000000000000000e+02 1.169117853697922427e-01 +8.520000000000000000e+02 1.168014936528796455e-01 +8.530000000000000000e+02 1.166917053867518178e-01 +8.540000000000000000e+02 1.165824173719189477e-01 +8.550000000000000000e+02 1.164736264351621947e-01 +8.560000000000000000e+02 1.163653294292692486e-01 +8.570000000000000000e+02 1.162575232327723584e-01 +8.580000000000000000e+02 1.161502047496897339e-01 +8.590000000000000000e+02 1.160433709092682786e-01 +8.600000000000000000e+02 1.159370186657307233e-01 +8.610000000000000000e+02 1.158311449980273383e-01 +8.620000000000000000e+02 1.157257469095881036e-01 +8.630000000000000000e+02 1.156208214280777524e-01 +8.640000000000000000e+02 1.155163656051554077e-01 +8.650000000000000000e+02 1.154123765190639694e-01 +8.660000000000000000e+02 1.153088512630748436e-01 +8.670000000000000000e+02 1.152057869622507003e-01 +8.680000000000000000e+02 1.151031807618744379e-01 +8.690000000000000000e+02 1.150010298300601086e-01 +8.700000000000000000e+02 1.148993313575267239e-01 +8.710000000000000000e+02 1.147980825573793051e-01 +8.720000000000000000e+02 1.146972806648860199e-01 +8.730000000000000000e+02 1.145969229372656856e-01 +8.740000000000000000e+02 1.144970066534688052e-01 +8.750000000000000000e+02 1.143975291112577647e-01 +8.760000000000000000e+02 1.142984876378518588e-01 +8.770000000000000000e+02 1.141998795734209676e-01 +8.780000000000000000e+02 1.141017022817588239e-01 +8.790000000000000000e+02 1.140039531473567985e-01 +8.800000000000000000e+02 1.139066295752069607e-01 +8.810000000000000000e+02 1.138097289906028348e-01 +8.820000000000000000e+02 1.137132488389436674e-01 +8.830000000000000000e+02 1.136171865855429841e-01 +8.840000000000000000e+02 1.135215397154349798e-01 +8.850000000000000000e+02 1.134263057331900415e-01 +8.860000000000000000e+02 1.133314821627231100e-01 +8.870000000000000000e+02 1.132370665471139487e-01 +8.880000000000000000e+02 1.131430564484220691e-01 +8.890000000000000000e+02 1.130494494475066530e-01 +8.900000000000000000e+02 1.129562431438497910e-01 +8.910000000000000000e+02 1.128634351553777365e-01 +8.920000000000000000e+02 1.127710231182890571e-01 +8.930000000000000000e+02 1.126790046868823558e-01 +8.940000000000000000e+02 1.125873775333833121e-01 +8.950000000000000000e+02 1.124961393477777044e-01 +8.960000000000000000e+02 1.124052878376476799e-01 +8.970000000000000000e+02 1.123148207280011135e-01 +8.980000000000000000e+02 1.122247357611138863e-01 +8.990000000000000000e+02 1.121350306963663362e-01 +9.000000000000000000e+02 1.120457033100843575e-01 +9.010000000000000000e+02 1.119567513953821786e-01 +9.020000000000000000e+02 1.118681727620066818e-01 +9.030000000000000000e+02 1.117799652361824297e-01 +9.040000000000000000e+02 1.116921266604606888e-01 +9.050000000000000000e+02 1.116046548935675092e-01 +9.060000000000000000e+02 1.115175478102545109e-01 +9.070000000000000000e+02 1.114308033011527782e-01 +9.080000000000000000e+02 1.113444192726263104e-01 +9.090000000000000000e+02 1.112583936466275264e-01 +9.100000000000000000e+02 1.111727243605556553e-01 +9.110000000000000000e+02 1.110874093671137819e-01 +9.120000000000000000e+02 1.110024466341708316e-01 +9.130000000000000000e+02 1.109178341446235977e-01 +9.140000000000000000e+02 1.108335698962584909e-01 +9.150000000000000000e+02 1.107496519016191172e-01 +9.160000000000000000e+02 1.106660781878698319e-01 +9.170000000000000000e+02 1.105828467966657458e-01 +9.180000000000000000e+02 1.104999557840209007e-01 +9.190000000000000000e+02 1.104174032201786920e-01 +9.200000000000000000e+02 1.103351871894839020e-01 +9.210000000000000000e+02 1.102533057902584657e-01 +9.220000000000000000e+02 1.101717571346719354e-01 +9.230000000000000000e+02 1.100905393486206613e-01 +9.240000000000000000e+02 1.100096505716040840e-01 +9.250000000000000000e+02 1.099290889566041929e-01 +9.260000000000000000e+02 1.098488526699644974e-01 +9.270000000000000000e+02 1.097689398912720243e-01 +9.280000000000000000e+02 1.096893488132392597e-01 +9.290000000000000000e+02 1.096100776415877831e-01 +9.300000000000000000e+02 1.095311245949342899e-01 +9.310000000000000000e+02 1.094524879046762239e-01 +9.320000000000000000e+02 1.093741658148773138e-01 +9.330000000000000000e+02 1.092961565821597286e-01 +9.340000000000000000e+02 1.092184584755904742e-01 +9.350000000000000000e+02 1.091410697765749366e-01 +9.360000000000000000e+02 1.090639887787455964e-01 +9.370000000000000000e+02 1.089872137878586250e-01 +9.380000000000000000e+02 1.089107431216855965e-01 +9.390000000000000000e+02 1.088345751099099173e-01 +9.400000000000000000e+02 1.087587080940246032e-01 +9.410000000000000000e+02 1.086831404272250029e-01 +9.420000000000000000e+02 1.086078704743134171e-01 +9.430000000000000000e+02 1.085328966115946953e-01 +9.440000000000000000e+02 1.084582172267784250e-01 +9.450000000000000000e+02 1.083838307188786793e-01 +9.460000000000000000e+02 1.083097354981193278e-01 +9.470000000000000000e+02 1.082359299858364071e-01 +9.480000000000000000e+02 1.081624126143817394e-01 +9.490000000000000000e+02 1.080891818270307420e-01 +9.500000000000000000e+02 1.080162360778867542e-01 +9.510000000000000000e+02 1.079435738317899574e-01 +9.520000000000000000e+02 1.078711935642250597e-01 +9.530000000000000000e+02 1.077990937612315625e-01 +9.540000000000000000e+02 1.077272729193125556e-01 +9.550000000000000000e+02 1.076557295453476337e-01 +9.560000000000000000e+02 1.075844621565031217e-01 +9.570000000000000000e+02 1.075134692801473502e-01 +9.580000000000000000e+02 1.074427494537623234e-01 +9.590000000000000000e+02 1.073723012248589820e-01 +9.600000000000000000e+02 1.073021231508945322e-01 +9.610000000000000000e+02 1.072322137991859187e-01 +9.620000000000000000e+02 1.071625717468284444e-01 +9.630000000000000000e+02 1.070931955806155161e-01 +9.640000000000000000e+02 1.070240838969546970e-01 +9.650000000000000000e+02 1.069552353017884511e-01 +9.660000000000000000e+02 1.068866484105159831e-01 +9.670000000000000000e+02 1.068183218479119290e-01 +9.680000000000000000e+02 1.067502542480503469e-01 +9.690000000000000000e+02 1.066824442542275569e-01 +9.700000000000000000e+02 1.066148905188842033e-01 +9.710000000000000000e+02 1.065475917035315218e-01 +9.720000000000000000e+02 1.064805464786740541e-01 +9.730000000000000000e+02 1.064137535237385385e-01 +9.740000000000000000e+02 1.063472115269971374e-01 +9.750000000000000000e+02 1.062809191854974522e-01 +9.760000000000000000e+02 1.062148752049877493e-01 +9.770000000000000000e+02 1.061490782998490701e-01 +9.780000000000000000e+02 1.060835271930218177e-01 +9.790000000000000000e+02 1.060182206159362012e-01 +9.800000000000000000e+02 1.059531573084446648e-01 +9.810000000000000000e+02 1.058883360187504313e-01 +9.820000000000000000e+02 1.058237555033426230e-01 +9.830000000000000000e+02 1.057594145269267483e-01 +9.840000000000000000e+02 1.056953118623597948e-01 +9.850000000000000000e+02 1.056314462905811602e-01 +9.860000000000000000e+02 1.055678166005525470e-01 +9.870000000000000000e+02 1.055044215891875609e-01 +9.880000000000000000e+02 1.054412600612911616e-01 +9.890000000000000000e+02 1.053783308294948540e-01 +9.900000000000000000e+02 1.053156327141946957e-01 +9.910000000000000000e+02 1.052531645434879454e-01 +9.920000000000000000e+02 1.051909251531117362e-01 +9.930000000000000000e+02 1.051289133863819170e-01 +9.940000000000000000e+02 1.050671280941335023e-01 +9.950000000000000000e+02 1.050055681346592079e-01 +9.960000000000000000e+02 1.049442323736501925e-01 +9.970000000000000000e+02 1.048831196841388536e-01 +9.980000000000000000e+02 1.048222289464388335e-01 +9.990000000000000000e+02 1.047615590480883013e-01 +1.000000000000000000e+03 1.047011088837912635e-01 +1.001000000000000000e+03 1.046408773553645644e-01 +1.002000000000000000e+03 1.045808633716757835e-01 +1.003000000000000000e+03 1.045210658485939970e-01 +1.004000000000000000e+03 1.044614837089305054e-01 +1.005000000000000000e+03 1.044021158823859041e-01 +1.006000000000000000e+03 1.043429613054957100e-01 +1.007000000000000000e+03 1.042840189215769597e-01 +1.008000000000000000e+03 1.042252876806749745e-01 +1.009000000000000000e+03 1.041667665395101389e-01 +1.010000000000000000e+03 1.041084544614278573e-01 +1.011000000000000000e+03 1.040503504163457910e-01 +1.012000000000000000e+03 1.039924533807007057e-01 +1.013000000000000000e+03 1.039347623374024393e-01 +1.014000000000000000e+03 1.038772762757792512e-01 +1.015000000000000000e+03 1.038199941915297769e-01 +1.016000000000000000e+03 1.037629150866763994e-01 +1.017000000000000000e+03 1.037060379695105838e-01 +1.018000000000000000e+03 1.036493618545506062e-01 +1.019000000000000000e+03 1.035928857624903304e-01 +1.020000000000000000e+03 1.035366087201513852e-01 +1.021000000000000000e+03 1.034805297604388941e-01 +1.022000000000000000e+03 1.034246479222913767e-01 +1.023000000000000000e+03 1.033689622506376027e-01 +1.024000000000000000e+03 1.033134717963493238e-01 +1.025000000000000000e+03 1.032581756161953107e-01 +1.026000000000000000e+03 1.032030727727980546e-01 +1.027000000000000000e+03 1.031481623345881088e-01 +1.028000000000000000e+03 1.030934433757606239e-01 +1.029000000000000000e+03 1.030389149762310774e-01 +1.030000000000000000e+03 1.029845762215917393e-01 +1.031000000000000000e+03 1.029304262030692890e-01 +1.032000000000000000e+03 1.028764640174829326e-01 +1.033000000000000000e+03 1.028226887671999518e-01 +1.034000000000000000e+03 1.027690995600967772e-01 +1.035000000000000000e+03 1.027156955095145097e-01 +1.036000000000000000e+03 1.026624757342202710e-01 +1.037000000000000000e+03 1.026094393583663472e-01 +1.038000000000000000e+03 1.025565855114477232e-01 +1.039000000000000000e+03 1.025039133282645287e-01 +1.040000000000000000e+03 1.024514219488819045e-01 +1.041000000000000000e+03 1.023991105185886874e-01 +1.042000000000000000e+03 1.023469781878613150e-01 +1.043000000000000000e+03 1.022950241123237042e-01 +1.044000000000000000e+03 1.022432474527099205e-01 +1.045000000000000000e+03 1.021916473748243348e-01 +1.046000000000000000e+03 1.021402230495066232e-01 +1.047000000000000000e+03 1.020889736525931596e-01 +1.048000000000000000e+03 1.020378983648797117e-01 +1.049000000000000000e+03 1.019869963720854145e-01 +1.050000000000000000e+03 1.019362668648176734e-01 +1.051000000000000000e+03 1.018857090385330427e-01 +1.052000000000000000e+03 1.018353220935056258e-01 +1.053000000000000000e+03 1.017851052347886476e-01 +1.054000000000000000e+03 1.017350576721808841e-01 +1.055000000000000000e+03 1.016851786201908719e-01 +1.056000000000000000e+03 1.016354672980036983e-01 +1.057000000000000000e+03 1.015859229294466815e-01 +1.058000000000000000e+03 1.015365447429553009e-01 +1.059000000000000000e+03 1.014873319715386413e-01 +1.060000000000000000e+03 1.014382838527483482e-01 +1.061000000000000000e+03 1.013893996286432259e-01 +1.062000000000000000e+03 1.013406785457594550e-01 +1.063000000000000000e+03 1.012921198550748303e-01 +1.064000000000000000e+03 1.012437228119800470e-01 +1.065000000000000000e+03 1.011954866762433819e-01 +1.066000000000000000e+03 1.011474107119828131e-01 +1.067000000000000000e+03 1.010994941876316722e-01 +1.068000000000000000e+03 1.010517363759091680e-01 +1.069000000000000000e+03 1.010041365537898972e-01 +1.070000000000000000e+03 1.009566940024713977e-01 +1.071000000000000000e+03 1.009094080073463240e-01 +1.072000000000000000e+03 1.008622778579714996e-01 +1.073000000000000000e+03 1.008153028480373026e-01 +1.074000000000000000e+03 1.007684822753396048e-01 +1.075000000000000000e+03 1.007218154417496153e-01 +1.076000000000000000e+03 1.006753016531853756e-01 +1.077000000000000000e+03 1.006289402195831434e-01 +1.078000000000000000e+03 1.005827304548678608e-01 +1.079000000000000000e+03 1.005366716769261343e-01 +1.080000000000000000e+03 1.004907632075771329e-01 +1.081000000000000000e+03 1.004450043725472613e-01 +1.082000000000000000e+03 1.003993945014384631e-01 +1.083000000000000000e+03 1.003539329277049613e-01 +1.084000000000000000e+03 1.003086189886229079e-01 +1.085000000000000000e+03 1.002634520252660283e-01 +1.086000000000000000e+03 1.002184313824786566e-01 +1.087000000000000000e+03 1.001735564088459679e-01 +1.088000000000000000e+03 1.001288264566743968e-01 +1.089000000000000000e+03 1.000842408819575258e-01 +1.090000000000000000e+03 1.000397990443580853e-01 +1.091000000000000000e+03 9.999550030717636873e-02 +1.092000000000000000e+03 9.995134403732905404e-02 +1.093000000000000000e+03 9.990732960532092144e-02 +1.094000000000000000e+03 9.986345638522189927e-02 +1.095000000000000000e+03 9.981972375464288894e-02 +1.096000000000000000e+03 9.977613109470875874e-02 +1.097000000000000000e+03 9.973267779003605615e-02 +1.098000000000000000e+03 9.968936322870819433e-02 +1.099000000000000000e+03 9.964618680225158232e-02 diff --git a/spectractor/extractor/dispersers/holo4_003/ratio_order_3over2.txt b/spectractor/extractor/dispersers/holo4_003/ratio_order_3over2.txt index dda2e3d92..de6d05742 100644 --- a/spectractor/extractor/dispersers/holo4_003/ratio_order_3over2.txt +++ b/spectractor/extractor/dispersers/holo4_003/ratio_order_3over2.txt @@ -1,800 +1,800 @@ -3.000000000000000000e+02 6.509725923171346018e+00 -3.010000000000000000e+02 1.156983590235709514e+01 -3.020000000000000000e+02 2.065892767125739837e+01 -3.030000000000000000e+02 3.266384599854518456e+01 -3.040000000000000000e+02 3.688427015932408182e+01 -3.050000000000000000e+02 2.955846253730900131e+01 -3.060000000000000000e+02 2.086079963948771621e+01 -3.070000000000000000e+02 1.483391093997127363e+01 -3.080000000000000000e+02 1.101253581269824622e+01 -3.090000000000000000e+02 8.543345874672958473e+00 -3.100000000000000000e+02 6.879515790464199476e+00 -3.110000000000000000e+02 5.709608451523049411e+00 -3.120000000000000000e+02 4.855338801222115030e+00 -3.130000000000000000e+02 4.211091270164593503e+00 -3.140000000000000000e+02 3.711767709806035320e+00 -3.150000000000000000e+02 3.315685161054438446e+00 -3.160000000000000000e+02 2.995214546596440375e+00 -3.170000000000000000e+02 2.731470209997443721e+00 -3.180000000000000000e+02 2.511187170917052569e+00 -3.190000000000000000e+02 2.324821673858040505e+00 -3.200000000000000000e+02 2.165359445266830996e+00 -3.210000000000000000e+02 2.027546656272186887e+00 -3.220000000000000000e+02 1.907380888083412884e+00 -3.230000000000000000e+02 1.801766370524660932e+00 -3.240000000000000000e+02 1.708275577335355067e+00 -3.250000000000000000e+02 1.624981230221655082e+00 -3.260000000000000000e+02 1.550335869337169825e+00 -3.270000000000000000e+02 1.483084159928695689e+00 -3.280000000000000000e+02 1.422198114662133195e+00 -3.290000000000000000e+02 1.366828609434258768e+00 -3.300000000000000000e+02 1.316268651832293690e+00 -3.310000000000000000e+02 1.269925240112287579e+00 -3.320000000000000000e+02 1.227297578953946422e+00 -3.330000000000000000e+02 1.187960052992033333e+00 -3.340000000000000000e+02 1.151548799291647995e+00 -3.350000000000000000e+02 1.117751029224237636e+00 -3.360000000000000000e+02 1.086296470221350230e+00 -3.370000000000000000e+02 1.056950456212043310e+00 -3.380000000000000000e+02 1.029508310721562347e+00 -3.390000000000000000e+02 1.003790751240222878e+00 -3.400000000000000000e+02 9.796401062565228690e-01 -3.410000000000000000e+02 9.569171833460039522e-01 -3.420000000000000000e+02 9.354986621867263930e-01 -3.430000000000000000e+02 9.152749133711250984e-01 -3.440000000000000000e+02 8.961481645859491474e-01 -3.450000000000000000e+02 8.780309517196009939e-01 -3.460000000000000000e+02 8.608448048873430514e-01 -3.470000000000000000e+02 8.445191290942747342e-01 -3.480000000000000000e+02 8.289902469153803688e-01 -3.490000000000000000e+02 8.142005766414438517e-01 -3.500000000000000000e+02 8.000979241709312850e-01 -3.510000000000000000e+02 7.866348707990169498e-01 -3.520000000000000000e+02 7.737682421688460987e-01 -3.530000000000000000e+02 7.614586461696587483e-01 -3.540000000000000000e+02 7.496700696129982022e-01 -3.550000000000000000e+02 7.383695251887274491e-01 -3.560000000000000000e+02 7.275267415721883291e-01 -3.570000000000000000e+02 7.171138906805679669e-01 -3.580000000000000000e+02 7.071053470080953529e-01 -3.590000000000000000e+02 6.974774747419761889e-01 -3.600000000000000000e+02 6.882084390034897137e-01 -3.610000000000000000e+02 6.792780380986728206e-01 -3.620000000000000000e+02 6.706675541072550928e-01 -3.630000000000000000e+02 6.623596195251194585e-01 -3.640000000000000000e+02 6.543380979885390358e-01 -3.650000000000000000e+02 6.465879773821993082e-01 -3.660000000000000000e+02 6.390952738614180673e-01 -3.670000000000000000e+02 6.318469455143372882e-01 -3.680000000000000000e+02 6.248308145566628946e-01 -3.690000000000000000e+02 6.180354970939593295e-01 -3.700000000000000000e+02 6.114503396089747689e-01 -3.710000000000000000e+02 6.050653614366442445e-01 -3.720000000000000000e+02 5.988712025800647654e-01 -3.730000000000000000e+02 5.928590762992315133e-01 -3.740000000000000000e+02 5.870207259720922055e-01 -3.750000000000000000e+02 5.813483857864492066e-01 -3.760000000000000000e+02 5.758347448724864259e-01 -3.770000000000000000e+02 5.704729145303520932e-01 -3.780000000000000000e+02 5.652563982462379677e-01 -3.790000000000000000e+02 5.601790642245236818e-01 -3.800000000000000000e+02 5.552351201935545877e-01 -3.810000000000000000e+02 5.504190902687762232e-01 -3.820000000000000000e+02 5.457257936802333287e-01 -3.830000000000000000e+02 5.411503251916882640e-01 -3.840000000000000000e+02 5.366880370567861380e-01 -3.850000000000000000e+02 5.323345223733942921e-01 -3.860000000000000000e+02 5.280855997116135070e-01 -3.870000000000000000e+02 5.239372989032440309e-01 -3.880000000000000000e+02 5.198858478917152137e-01 -3.890000000000000000e+02 5.159276605514671044e-01 -3.900000000000000000e+02 5.120593253943732659e-01 -3.910000000000000000e+02 5.082775950889130145e-01 -3.920000000000000000e+02 5.045793767246775641e-01 -3.930000000000000000e+02 5.009617227611485868e-01 -3.940000000000000000e+02 4.974218226053315761e-01 -3.950000000000000000e+02 4.939569947679042228e-01 -3.960000000000000000e+02 4.905646795520252623e-01 -3.970000000000000000e+02 4.872424322331894153e-01 -3.980000000000000000e+02 4.839879166919889286e-01 -3.990000000000000000e+02 4.807988994651667958e-01 -4.000000000000000000e+02 4.776732441832539644e-01 -4.010000000000000000e+02 4.746089063657677465e-01 -4.020000000000000000e+02 4.716039285475141507e-01 -4.030000000000000000e+02 4.686564357116038138e-01 -4.040000000000000000e+02 4.657646310069922246e-01 -4.050000000000000000e+02 4.629267917299948465e-01 -4.060000000000000000e+02 4.601412655510689342e-01 -4.070000000000000000e+02 4.574064669695095398e-01 -4.080000000000000000e+02 4.547208739802010569e-01 -4.090000000000000000e+02 4.520830249377760790e-01 -4.100000000000000000e+02 4.494915156046404570e-01 -4.110000000000000000e+02 4.469449963704413276e-01 -4.120000000000000000e+02 4.444421696314884707e-01 -4.130000000000000000e+02 4.419817873194388791e-01 -4.140000000000000000e+02 4.395626485694713037e-01 -4.150000000000000000e+02 4.371835975188317347e-01 -4.160000000000000000e+02 4.348435212273337735e-01 -4.170000000000000000e+02 4.325413477119841033e-01 -4.180000000000000000e+02 4.302760440884981774e-01 -4.190000000000000000e+02 4.280466148130216975e-01 -4.200000000000000000e+02 4.258521000177492022e-01 -4.210000000000000000e+02 4.236915739346737708e-01 -4.220000000000000000e+02 4.215641434020956368e-01 -4.230000000000000000e+02 4.194689464488028929e-01 -4.240000000000000000e+02 4.174051509513057034e-01 -4.250000000000000000e+02 4.153719533597377556e-01 -4.260000000000000000e+02 4.133685774883759656e-01 -4.270000000000000000e+02 4.113942733669674334e-01 -4.280000000000000000e+02 4.094483161493540080e-01 -4.290000000000000000e+02 4.075300050760630177e-01 -4.300000000000000000e+02 4.056386624877854619e-01 -4.310000000000000000e+02 4.013912009558592842e-01 -4.320000000000000000e+02 3.971192247879613002e-01 -4.330000000000000000e+02 3.929431662759431121e-01 -4.340000000000000000e+02 3.887877778006299523e-01 -4.350000000000000000e+02 3.847991905271044843e-01 -4.360000000000000000e+02 3.808899497092754771e-01 -4.370000000000000000e+02 3.770321205610598914e-01 -4.380000000000000000e+02 3.732521381443776876e-01 -4.390000000000000000e+02 3.694158397025473217e-01 -4.400000000000000000e+02 3.656361642969984116e-01 -4.410000000000000000e+02 3.637041215579885356e-01 -4.420000000000000000e+02 3.618050021278039763e-01 -4.430000000000000000e+02 3.599573466274055278e-01 -4.440000000000000000e+02 3.581622953562234035e-01 -4.450000000000000000e+02 3.563475298726105911e-01 -4.460000000000000000e+02 3.546131012783114156e-01 -4.470000000000000000e+02 3.529171425161061748e-01 -4.480000000000000000e+02 3.511600645287158429e-01 -4.490000000000000000e+02 3.495001340366898912e-01 -4.500000000000000000e+02 3.478342642145098584e-01 -4.510000000000000000e+02 3.464230590325684256e-01 -4.520000000000000000e+02 3.448679466138410143e-01 -4.530000000000000000e+02 3.432877541094727092e-01 -4.540000000000000000e+02 3.419279637498306990e-01 -4.550000000000000000e+02 3.403899632567217726e-01 -4.560000000000000000e+02 3.388281057218366921e-01 -4.570000000000000000e+02 3.374509332583289223e-01 -4.580000000000000000e+02 3.360451544967197890e-01 -4.590000000000000000e+02 3.346336262677152562e-01 -4.600000000000000000e+02 3.331518803143234675e-01 -4.610000000000000000e+02 3.322999523736291372e-01 -4.620000000000000000e+02 3.314413399858454623e-01 -4.630000000000000000e+02 3.305725970739325503e-01 -4.640000000000000000e+02 3.297325016120075669e-01 -4.650000000000000000e+02 3.288405527362059932e-01 -4.660000000000000000e+02 3.280349124410171235e-01 -4.670000000000000000e+02 3.272181645157655749e-01 -4.680000000000000000e+02 3.264107816982220744e-01 -4.690000000000000000e+02 3.256138361259974801e-01 -4.700000000000000000e+02 3.248861836773703771e-01 -4.710000000000000000e+02 3.236703958241508583e-01 -4.720000000000000000e+02 3.224004875302849960e-01 -4.730000000000000000e+02 3.212142588947224375e-01 -4.740000000000000000e+02 3.201511185091803768e-01 -4.750000000000000000e+02 3.189554620501165449e-01 -4.760000000000000000e+02 3.178098233543905082e-01 -4.770000000000000000e+02 3.167221172560253373e-01 -4.780000000000000000e+02 3.157016581654958909e-01 -4.790000000000000000e+02 3.145593782471240440e-01 -4.800000000000000000e+02 3.134509493041701123e-01 -4.810000000000000000e+02 3.121425769791167926e-01 -4.820000000000000000e+02 3.108784129001939678e-01 -4.830000000000000000e+02 3.096797605619626692e-01 -4.840000000000000000e+02 3.085392244289119623e-01 -4.850000000000000000e+02 3.074820466880909264e-01 -4.860000000000000000e+02 3.064652653738632604e-01 -4.870000000000000000e+02 3.053357684427669416e-01 -4.880000000000000000e+02 3.043780287842099974e-01 -4.890000000000000000e+02 3.033467242744036785e-01 -4.900000000000000000e+02 3.023931681866862675e-01 -4.910000000000000000e+02 3.014207182671409524e-01 -4.920000000000000000e+02 3.004620052485332260e-01 -4.930000000000000000e+02 2.995395110481065548e-01 -4.940000000000000000e+02 2.986801932647105695e-01 -4.950000000000000000e+02 2.978709237690262412e-01 -4.960000000000000000e+02 2.970468427189997818e-01 -4.970000000000000000e+02 2.963053479931697654e-01 -4.980000000000000000e+02 2.955473664731924632e-01 -4.990000000000000000e+02 2.947567652016332418e-01 -5.000000000000000000e+02 2.941277613234809518e-01 -5.010000000000000000e+02 2.934817548728843040e-01 -5.020000000000000000e+02 2.928781479379820585e-01 -5.030000000000000000e+02 2.922706048624220676e-01 -5.040000000000000000e+02 2.916459244383286520e-01 -5.050000000000000000e+02 2.912236565535889499e-01 -5.060000000000000000e+02 2.907475290896360254e-01 -5.070000000000000000e+02 2.902677375099961266e-01 -5.080000000000000000e+02 2.897676634669539841e-01 -5.090000000000000000e+02 2.893731430640880120e-01 -5.100000000000000000e+02 2.889589445163627812e-01 -5.110000000000000000e+02 2.881700181111551684e-01 -5.120000000000000000e+02 2.873480520316719078e-01 -5.130000000000000000e+02 2.865151935771834135e-01 -5.140000000000000000e+02 2.856811667792410470e-01 -5.150000000000000000e+02 2.849473062224541775e-01 -5.160000000000000000e+02 2.840788906049899754e-01 -5.170000000000000000e+02 2.833928994179065741e-01 -5.180000000000000000e+02 2.827039766186793535e-01 -5.190000000000000000e+02 2.819754817033529593e-01 -5.200000000000000000e+02 2.812482993192523262e-01 -5.210000000000000000e+02 2.809187193137456240e-01 -5.220000000000000000e+02 2.806119449158293033e-01 -5.230000000000000000e+02 2.803365836900778563e-01 -5.240000000000000000e+02 2.800123081838547523e-01 -5.250000000000000000e+02 2.797458103743233893e-01 -5.260000000000000000e+02 2.795503012147202426e-01 -5.270000000000000000e+02 2.793651617083823813e-01 -5.280000000000000000e+02 2.791742447571493035e-01 -5.290000000000000000e+02 2.790152870372823446e-01 -5.300000000000000000e+02 2.787765316151872286e-01 -5.310000000000000000e+02 2.782614025891858578e-01 -5.320000000000000000e+02 2.777553322218797582e-01 -5.330000000000000000e+02 2.772724584393295721e-01 -5.340000000000000000e+02 2.767805116406394927e-01 -5.350000000000000000e+02 2.763191815102425952e-01 -5.360000000000000000e+02 2.758573178654324942e-01 -5.370000000000000000e+02 2.754049108370179577e-01 -5.380000000000000000e+02 2.749522072559143493e-01 -5.390000000000000000e+02 2.745113907245025353e-01 -5.400000000000000000e+02 2.740557320472344904e-01 -5.410000000000000000e+02 2.738357205008694062e-01 -5.420000000000000000e+02 2.736625084758002036e-01 -5.430000000000000000e+02 2.734110728475184771e-01 -5.440000000000000000e+02 2.731982861589927758e-01 -5.450000000000000000e+02 2.729718221333193306e-01 -5.460000000000000000e+02 2.728511995680704683e-01 -5.470000000000000000e+02 2.726255409409779062e-01 -5.480000000000000000e+02 2.725091758002506914e-01 -5.490000000000000000e+02 2.723876843379202661e-01 -5.500000000000000000e+02 2.722399028653252340e-01 -5.510000000000000000e+02 2.715911952691412168e-01 -5.520000000000000000e+02 2.709460720857740923e-01 -5.530000000000000000e+02 2.703044947435113143e-01 -5.540000000000000000e+02 2.696664253031139102e-01 -5.550000000000000000e+02 2.690318264447055796e-01 -5.560000000000000000e+02 2.684006614549652170e-01 -5.570000000000000000e+02 2.677728942146391788e-01 -5.580000000000000000e+02 2.671484891863595834e-01 -5.590000000000000000e+02 2.665274114027597063e-01 -5.600000000000000000e+02 2.659096264548642674e-01 -5.610000000000000000e+02 2.652951004807700963e-01 -5.620000000000000000e+02 2.646838001546008567e-01 -5.630000000000000000e+02 2.640756926757049650e-01 -5.640000000000000000e+02 2.634707457581375589e-01 -5.650000000000000000e+02 2.628689276203737268e-01 -5.660000000000000000e+02 2.622702069752671505e-01 -5.670000000000000000e+02 2.616745530202487235e-01 -5.680000000000000000e+02 2.610819354277570947e-01 -5.690000000000000000e+02 2.604923243358777674e-01 -5.700000000000000000e+02 2.599056903392269469e-01 -5.710000000000000000e+02 2.593220044800134683e-01 -5.720000000000000000e+02 2.587412382393369792e-01 -5.730000000000000000e+02 2.581633635286694761e-01 -5.740000000000000000e+02 2.575883526815297420e-01 -5.750000000000000000e+02 2.570161784453716680e-01 -5.760000000000000000e+02 2.564468139736207908e-01 -5.770000000000000000e+02 2.558802328179256569e-01 -5.780000000000000000e+02 2.553164089205607334e-01 -5.790000000000000000e+02 2.547553166070181674e-01 -5.800000000000000000e+02 2.541969305787496469e-01 -5.810000000000000000e+02 2.536412259060807917e-01 -5.820000000000000000e+02 2.530881780567449391e-01 -5.830000000000000000e+02 2.525377627468738395e-01 -5.840000000000000000e+02 2.519899561483122663e-01 -5.850000000000000000e+02 2.514447347391092213e-01 -5.860000000000000000e+02 2.509020753330470366e-01 -5.870000000000000000e+02 2.503619550399095450e-01 -5.880000000000000000e+02 2.498243513939016058e-01 -5.890000000000000000e+02 2.492892421454347696e-01 -5.900000000000000000e+02 2.487566053905642949e-01 -5.910000000000000000e+02 2.482264195314022592e-01 -5.920000000000000000e+02 2.476986632705741043e-01 -5.930000000000000000e+02 2.471733156057744074e-01 -5.940000000000000000e+02 2.466503558244548810e-01 -5.950000000000000000e+02 2.461297634986228111e-01 -5.960000000000000000e+02 2.456115184797426632e-01 -5.970000000000000000e+02 2.450956008937515973e-01 -5.980000000000000000e+02 2.445819911361842014e-01 -5.990000000000000000e+02 2.440706698673940078e-01 -6.000000000000000000e+02 2.435616180078764292e-01 -6.010000000000000000e+02 2.430548167336908649e-01 -6.020000000000000000e+02 2.425502474719749280e-01 -6.030000000000000000e+02 2.420478918965666137e-01 -6.040000000000000000e+02 2.415477319236925824e-01 -6.050000000000000000e+02 2.410497497077650209e-01 -6.060000000000000000e+02 2.405539276372625490e-01 -6.070000000000000000e+02 2.400602483306865376e-01 -6.080000000000000000e+02 2.395686946326125166e-01 -6.090000000000000000e+02 2.390792496098067821e-01 -6.100000000000000000e+02 2.385918965474450038e-01 -6.110000000000000000e+02 2.381066189453825144e-01 -6.120000000000000000e+02 2.376234005145202166e-01 -6.130000000000000000e+02 2.371422251732272779e-01 -6.140000000000000000e+02 2.366630770438537534e-01 -6.150000000000000000e+02 2.361859404492911152e-01 -6.160000000000000000e+02 2.357107999096284823e-01 -6.170000000000000000e+02 2.352376401388481530e-01 -6.180000000000000000e+02 2.347664460416065690e-01 -6.190000000000000000e+02 2.342972027100732046e-01 -6.200000000000000000e+02 2.338298954208279934e-01 -6.210000000000000000e+02 2.333645096318186229e-01 -6.220000000000000000e+02 2.329010309793958511e-01 -6.230000000000000000e+02 2.324394452753779650e-01 -6.240000000000000000e+02 2.319797385041930393e-01 -6.250000000000000000e+02 2.315218968200772609e-01 -6.260000000000000000e+02 2.310659065443141091e-01 -6.270000000000000000e+02 2.306117541625375411e-01 -6.280000000000000000e+02 2.301594263220834435e-01 -6.290000000000000000e+02 2.297089098293993159e-01 -6.300000000000000000e+02 2.292601916474861501e-01 -6.310000000000000000e+02 2.288132588934114198e-01 -6.320000000000000000e+02 2.283680988358526565e-01 -6.330000000000000000e+02 2.279246988926959816e-01 -6.340000000000000000e+02 2.274830466286782149e-01 -6.350000000000000000e+02 2.270431297530706993e-01 -6.360000000000000000e+02 2.266049361174183041e-01 -6.370000000000000000e+02 2.261684537132997164e-01 -6.380000000000000000e+02 2.257336706701522644e-01 -6.390000000000000000e+02 2.253005752531235806e-01 -6.400000000000000000e+02 2.248691558609697549e-01 -6.410000000000000000e+02 2.244394010239880444e-01 -6.420000000000000000e+02 2.240112994019895776e-01 -6.430000000000000000e+02 2.235848397823104738e-01 -6.440000000000000000e+02 2.231600110778641233e-01 -6.450000000000000000e+02 2.227368023252197793e-01 -6.460000000000000000e+02 2.223152026827190930e-01 -6.470000000000000000e+02 2.218952014286380836e-01 -6.480000000000000000e+02 2.214767879593616262e-01 -6.490000000000000000e+02 2.210599517876132847e-01 -6.500000000000000000e+02 2.206446825407070711e-01 -6.510000000000000000e+02 2.202309699588207714e-01 -6.520000000000000000e+02 2.198188038933247268e-01 -6.530000000000000000e+02 2.194081743051159161e-01 -6.540000000000000000e+02 2.189990712630012493e-01 -6.550000000000000000e+02 2.185914849420922679e-01 -6.560000000000000000e+02 2.181854056222474192e-01 -6.570000000000000000e+02 2.177808236865258207e-01 -6.580000000000000000e+02 2.173777296196790776e-01 -6.590000000000000000e+02 2.169761140066586436e-01 -6.600000000000000000e+02 2.165759675311676735e-01 -6.610000000000000000e+02 2.161772809742177892e-01 -6.620000000000000000e+02 2.157800452127254520e-01 -6.630000000000000000e+02 2.153842512181299573e-01 -6.640000000000000000e+02 2.149898900550256398e-01 -6.650000000000000000e+02 2.145969528798400972e-01 -6.660000000000000000e+02 2.142054309395081124e-01 -6.670000000000000000e+02 2.138153155701894848e-01 -6.680000000000000000e+02 2.134265981959994340e-01 -6.690000000000000000e+02 2.130392703277668165e-01 -6.700000000000000000e+02 2.126533235618015827e-01 -6.710000000000000000e+02 2.122687495787007605e-01 -6.720000000000000000e+02 2.118855401421630702e-01 -6.730000000000000000e+02 2.115036870978229122e-01 -6.740000000000000000e+02 2.111231823721143319e-01 -6.750000000000000000e+02 2.107440179711427275e-01 -6.760000000000000000e+02 2.103661859795838140e-01 -6.770000000000000000e+02 2.099896785595972704e-01 -6.780000000000000000e+02 2.096144879497590652e-01 -6.790000000000000000e+02 2.092406064640178198e-01 -6.800000000000000000e+02 2.088680264906531692e-01 -6.810000000000000000e+02 2.084967404912727307e-01 -6.820000000000000000e+02 2.081267409998037721e-01 -6.830000000000000000e+02 2.077580206215242642e-01 -6.840000000000000000e+02 2.073905720320884938e-01 -6.850000000000000000e+02 2.070243879765835127e-01 -6.860000000000000000e+02 2.066594612685986321e-01 -6.870000000000000000e+02 2.062957847893023000e-01 -6.880000000000000000e+02 2.059333514865440695e-01 -6.890000000000000000e+02 2.055721543739636448e-01 -6.900000000000000000e+02 2.052121865301247128e-01 -6.910000000000000000e+02 2.048534410976490527e-01 -6.920000000000000000e+02 2.044959112823747094e-01 -6.930000000000000000e+02 2.041395903525253519e-01 -6.940000000000000000e+02 2.037844716378908461e-01 -6.950000000000000000e+02 2.034305485290265891e-01 -6.960000000000000000e+02 2.030778144764594784e-01 -6.970000000000000000e+02 2.027262629899092006e-01 -6.980000000000000000e+02 2.023758876375233162e-01 -6.990000000000000000e+02 2.020266820451206424e-01 -7.000000000000000000e+02 2.016786398954537873e-01 -7.010000000000000000e+02 2.013317549274782348e-01 -7.020000000000000000e+02 2.009860209356282568e-01 -7.030000000000000000e+02 2.006414317691171401e-01 -7.040000000000000000e+02 2.002979813312388280e-01 -7.050000000000000000e+02 1.999556635786803871e-01 -7.060000000000000000e+02 1.996144725208495729e-01 -7.070000000000000000e+02 1.992744022192144138e-01 -7.080000000000000000e+02 1.989354467866432108e-01 -7.090000000000000000e+02 1.985976003867695738e-01 -7.100000000000000000e+02 1.982608572333535712e-01 -7.110000000000000000e+02 1.979252115896589503e-01 -7.120000000000000000e+02 1.975906577678417098e-01 -7.130000000000000000e+02 1.972571901283477480e-01 -7.140000000000000000e+02 1.969248030793145365e-01 -7.150000000000000000e+02 1.965934910759837284e-01 -7.160000000000000000e+02 1.962632486266521481e-01 -7.170000000000000000e+02 1.959340702659196076e-01 -7.180000000000000000e+02 1.956059505935459353e-01 -7.190000000000000000e+02 1.952788842475245701e-01 -7.200000000000000000e+02 1.949528659101645856e-01 -7.210000000000000000e+02 1.946278903075495947e-01 -7.220000000000000000e+02 1.943039522090126980e-01 -7.230000000000000000e+02 1.939810464266206180e-01 -7.240000000000000000e+02 1.936591678146649953e-01 -7.250000000000000000e+02 1.933383112691586525e-01 -7.260000000000000000e+02 1.930184717273383255e-01 -7.270000000000000000e+02 1.926996441671788018e-01 -7.280000000000000000e+02 1.923818236069127496e-01 -7.290000000000000000e+02 1.920650051045573736e-01 -7.300000000000000000e+02 1.917491837574481495e-01 -7.310000000000000000e+02 1.914343547017823277e-01 -7.320000000000000000e+02 1.911205131121570255e-01 -7.330000000000000000e+02 1.908076542011389876e-01 -7.340000000000000000e+02 1.904957732188080066e-01 -7.350000000000000000e+02 1.901848654523400350e-01 -7.360000000000000000e+02 1.898749262255676751e-01 -7.370000000000000000e+02 1.895659508985683972e-01 -7.380000000000000000e+02 1.892579348672460138e-01 -7.390000000000000000e+02 1.889508735629232272e-01 -7.400000000000000000e+02 1.886447624519428656e-01 -7.410000000000000000e+02 1.883395970352690352e-01 -7.420000000000000000e+02 1.880353728480916031e-01 -7.430000000000000000e+02 1.877320854594486943e-01 -7.440000000000000000e+02 1.874297304676837694e-01 -7.450000000000000000e+02 1.871283035167833897e-01 -7.460000000000000000e+02 1.868278002708305685e-01 -7.470000000000000000e+02 1.865282164305049062e-01 -7.480000000000000000e+02 1.862295477284785505e-01 -7.490000000000000000e+02 1.859317899290809373e-01 -7.500000000000000000e+02 1.856349388279329160e-01 -7.510000000000000000e+02 1.853389902516112964e-01 -7.520000000000000000e+02 1.850439400573179460e-01 -7.530000000000000000e+02 1.847497841325274892e-01 -7.540000000000000000e+02 1.844565183946765274e-01 -7.550000000000000000e+02 1.841641387908259930e-01 -7.560000000000000000e+02 1.838726412973519520e-01 -7.570000000000000000e+02 1.835820219196187264e-01 -7.580000000000000000e+02 1.832922766916768587e-01 -7.590000000000000000e+02 1.830034016759543858e-01 -7.600000000000000000e+02 1.827153929629482532e-01 -7.610000000000000000e+02 1.824282466709342965e-01 -7.620000000000000000e+02 1.821419589456655663e-01 -7.630000000000000000e+02 1.818565259600903039e-01 -7.640000000000000000e+02 1.815719439140544011e-01 -7.650000000000000000e+02 1.812882090340306451e-01 -7.660000000000000000e+02 1.810053175728312536e-01 -7.670000000000000000e+02 1.807232658093354816e-01 -7.680000000000000000e+02 1.804420500482230294e-01 -7.690000000000000000e+02 1.801616666197011218e-01 -7.700000000000000000e+02 1.798821118792424678e-01 -7.710000000000000000e+02 1.796033822073268282e-01 -7.720000000000000000e+02 1.793254740091770050e-01 -7.730000000000000000e+02 1.790483837145204760e-01 -7.740000000000000000e+02 1.787721077773175293e-01 -7.750000000000000000e+02 1.784966426755400792e-01 -7.760000000000000000e+02 1.782219849109021037e-01 -7.770000000000000000e+02 1.779481310086448720e-01 -7.780000000000000000e+02 1.776750775172805386e-01 -7.790000000000000000e+02 1.774028210083636037e-01 -7.800000000000000000e+02 1.771313580762706452e-01 -7.810000000000000000e+02 1.768606853379534605e-01 -7.820000000000000000e+02 1.765907994327330643e-01 -7.830000000000000000e+02 1.763216970220653768e-01 -7.840000000000000000e+02 1.760533747893261169e-01 -7.850000000000000000e+02 1.757858294395991117e-01 -7.860000000000000000e+02 1.755190576994557772e-01 -7.870000000000000000e+02 1.752530563167477573e-01 -7.880000000000000000e+02 1.749878220603999501e-01 -7.890000000000000000e+02 1.747233517202063102e-01 -7.900000000000000000e+02 1.744596421066213210e-01 -7.910000000000000000e+02 1.741966900505709792e-01 -7.920000000000000000e+02 1.739344924032440176e-01 -7.930000000000000000e+02 1.736730460359040829e-01 -7.940000000000000000e+02 1.734123478396928930e-01 -7.950000000000000000e+02 1.731523947254474949e-01 -7.960000000000000000e+02 1.728931836235040598e-01 -7.970000000000000000e+02 1.726347114835185270e-01 -7.980000000000000000e+02 1.723769752742830286e-01 -7.990000000000000000e+02 1.721199719835446451e-01 -8.000000000000000000e+02 1.718636986178233017e-01 -8.010000000000000000e+02 1.716081522022455674e-01 -8.020000000000000000e+02 1.713533297803551958e-01 -8.030000000000000000e+02 1.710992284139661035e-01 -8.040000000000000000e+02 1.708458451829648339e-01 -8.050000000000000000e+02 1.705931771851603995e-01 -8.060000000000000000e+02 1.703412215361158055e-01 -8.070000000000000000e+02 1.700899753689843197e-01 -8.080000000000000000e+02 1.698394358343452148e-01 -8.090000000000000000e+02 1.695896001000487541e-01 -8.100000000000000000e+02 1.693404653510564017e-01 -8.110000000000000000e+02 1.690920287892863638e-01 -8.120000000000000000e+02 1.688442876334581011e-01 -8.130000000000000000e+02 1.685972391189455299e-01 -8.140000000000000000e+02 1.683508804976205087e-01 -8.150000000000000000e+02 1.681052090377070374e-01 -8.160000000000000000e+02 1.678602220236431464e-01 -8.170000000000000000e+02 1.676159167559223562e-01 -8.180000000000000000e+02 1.673722905509618664e-01 -8.190000000000000000e+02 1.671293407409534248e-01 -8.200000000000000000e+02 1.668870646737345698e-01 -8.210000000000000000e+02 1.666454597126409143e-01 -8.220000000000000000e+02 1.664045232363741689e-01 -8.230000000000000000e+02 1.661642526388682484e-01 -8.240000000000000000e+02 1.659246453291537693e-01 -8.250000000000000000e+02 1.656856987312289031e-01 -8.260000000000000000e+02 1.654474102839309790e-01 -8.270000000000000000e+02 1.652097774408066155e-01 -8.280000000000000000e+02 1.649727976699829068e-01 -8.290000000000000000e+02 1.647364684540476298e-01 -8.300000000000000000e+02 1.645007872899181545e-01 -8.310000000000000000e+02 1.642657516887252311e-01 -8.320000000000000000e+02 1.640313591756905609e-01 -8.330000000000000000e+02 1.637976072900084734e-01 -8.340000000000000000e+02 1.635644935847182513e-01 -8.350000000000000000e+02 1.633320156266034329e-01 -8.360000000000000000e+02 1.631001709960651080e-01 -8.370000000000000000e+02 1.628689572870125335e-01 -8.380000000000000000e+02 1.626383721067453936e-01 -8.390000000000000000e+02 1.624084130758482736e-01 -8.400000000000000000e+02 1.621790778280755296e-01 -8.410000000000000000e+02 1.619503640102446240e-01 -8.420000000000000000e+02 1.617222692821323748e-01 -8.430000000000000000e+02 1.614947913163576332e-01 -8.440000000000000000e+02 1.612679277982875803e-01 -8.450000000000000000e+02 1.610416764259272326e-01 -8.460000000000000000e+02 1.608160349098172459e-01 -8.470000000000000000e+02 1.605910009729304699e-01 -8.480000000000000000e+02 1.603665723505774410e-01 -8.490000000000000000e+02 1.601427467903011326e-01 -8.500000000000000000e+02 1.599195220517799498e-01 -8.510000000000000000e+02 1.596968959067274485e-01 -8.520000000000000000e+02 1.594748661388046829e-01 -8.530000000000000000e+02 1.592534305435133468e-01 -8.540000000000000000e+02 1.590325869281131177e-01 -8.550000000000000000e+02 1.588123331115195436e-01 -8.560000000000000000e+02 1.585926669242151421e-01 -8.570000000000000000e+02 1.583735862081580015e-01 -8.580000000000000000e+02 1.581550888166957658e-01 -8.590000000000000000e+02 1.579371726144669363e-01 -8.600000000000000000e+02 1.577198354773206301e-01 -8.610000000000000000e+02 1.575030752922284283e-01 -8.620000000000000000e+02 1.572868899571963908e-01 -8.630000000000000000e+02 1.570712773811751839e-01 -8.640000000000000000e+02 1.568562354839878881e-01 -8.650000000000000000e+02 1.566417621962336304e-01 -8.660000000000000000e+02 1.564278554592107573e-01 -8.670000000000000000e+02 1.562145132248342894e-01 -8.680000000000000000e+02 1.560017334555549029e-01 -8.690000000000000000e+02 1.557895141242813808e-01 -8.700000000000000000e+02 1.555778532142964576e-01 -8.710000000000000000e+02 1.553667487191800478e-01 -8.720000000000000000e+02 1.551561986427322515e-01 -8.730000000000000000e+02 1.549462009989035216e-01 -8.740000000000000000e+02 1.547367538117028762e-01 -8.750000000000000000e+02 1.545278551151350876e-01 -8.760000000000000000e+02 1.543195029531224949e-01 -8.770000000000000000e+02 1.541116953794353095e-01 -8.780000000000000000e+02 1.539044304576116795e-01 -8.790000000000000000e+02 1.536977062608885503e-01 -8.800000000000000000e+02 1.534915208721329694e-01 -8.810000000000000000e+02 1.532858723837701720e-01 -8.820000000000000000e+02 1.530807588977079747e-01 -8.830000000000000000e+02 1.528761785252807925e-01 -8.840000000000000000e+02 1.526721293871620977e-01 -8.850000000000000000e+02 1.524686096133157365e-01 -8.860000000000000000e+02 1.522656173429173809e-01 -8.870000000000000000e+02 1.520631507242903302e-01 -8.880000000000000000e+02 1.518612079148390914e-01 -8.890000000000000000e+02 1.516597870809909543e-01 -8.900000000000000000e+02 1.514588863981203293e-01 -8.910000000000000000e+02 1.512585040504949851e-01 -8.920000000000000000e+02 1.510586382312030795e-01 -8.930000000000000000e+02 1.508592871421043369e-01 -8.940000000000000000e+02 1.506604489937514169e-01 -8.950000000000000000e+02 1.504621220053430630e-01 -8.960000000000000000e+02 1.502643044046546028e-01 -8.970000000000000000e+02 1.500669944279820200e-01 -8.980000000000000000e+02 1.498701903200784780e-01 -8.990000000000000000e+02 1.496738903341030824e-01 -9.000000000000000000e+02 1.494780927315501329e-01 -9.010000000000000000e+02 1.492827957822062956e-01 -9.020000000000000000e+02 1.490879977640773291e-01 -9.030000000000000000e+02 1.488936969633467555e-01 -9.040000000000000000e+02 1.486998916743114685e-01 -9.050000000000000000e+02 1.485065801993235846e-01 -9.060000000000000000e+02 1.483137608487412606e-01 -9.070000000000000000e+02 1.481214319408722668e-01 -9.080000000000000000e+02 1.479295918019182809e-01 -9.090000000000000000e+02 1.477382387659270380e-01 -9.100000000000000000e+02 1.475473711747292971e-01 -9.110000000000000000e+02 1.473569873778970418e-01 -9.120000000000000000e+02 1.471670857326824733e-01 -9.130000000000000000e+02 1.469776646039736012e-01 -9.140000000000000000e+02 1.467887223642389827e-01 -9.150000000000000000e+02 1.466002573934792330e-01 -9.160000000000000000e+02 1.464122680791772602e-01 -9.170000000000000000e+02 1.462247528162418098e-01 -9.180000000000000000e+02 1.460377100069734368e-01 -9.190000000000000000e+02 1.458511380610005848e-01 -9.200000000000000000e+02 1.456650353952339827e-01 -9.210000000000000000e+02 1.454794004338342273e-01 -9.220000000000000000e+02 1.452942316081404783e-01 -9.230000000000000000e+02 1.451095273566402610e-01 -9.240000000000000000e+02 1.449252861249199775e-01 -9.250000000000000000e+02 1.447415063656136980e-01 -9.260000000000000000e+02 1.445581865383607223e-01 -9.270000000000000000e+02 1.443753251097650570e-01 -9.280000000000000000e+02 1.441929205533447889e-01 -9.290000000000000000e+02 1.440109713494855948e-01 -9.300000000000000000e+02 1.438294759854008842e-01 -9.310000000000000000e+02 1.436484329550934413e-01 -9.320000000000000000e+02 1.434678407592990534e-01 -9.330000000000000000e+02 1.432876979054597266e-01 -9.340000000000000000e+02 1.431080029076605975e-01 -9.350000000000000000e+02 1.429287542866095329e-01 -9.360000000000000000e+02 1.427499505695824511e-01 -9.370000000000000000e+02 1.425715902903854915e-01 -9.380000000000000000e+02 1.423936719893119374e-01 -9.390000000000000000e+02 1.422161942131080214e-01 -9.400000000000000000e+02 1.420391555149262408e-01 -9.410000000000000000e+02 1.418625544542850281e-01 -9.420000000000000000e+02 1.416863895970347786e-01 -9.430000000000000000e+02 1.415106595153154956e-01 -9.440000000000000000e+02 1.413353627875172103e-01 -9.450000000000000000e+02 1.411604979982417074e-01 -9.460000000000000000e+02 1.409860637382658599e-01 -9.470000000000000000e+02 1.408120586045039091e-01 -9.480000000000000000e+02 1.406384811999666640e-01 -9.490000000000000000e+02 1.404653301337304150e-01 -9.500000000000000000e+02 1.402926040208922198e-01 -9.510000000000000000e+02 1.401203014825386228e-01 -9.520000000000000000e+02 1.399484211457112381e-01 -9.530000000000000000e+02 1.397769616433654771e-01 -9.540000000000000000e+02 1.396059216143341053e-01 -9.550000000000000000e+02 1.394352997033027897e-01 -9.560000000000000000e+02 1.392650945607592228e-01 -9.570000000000000000e+02 1.390953048429723615e-01 -9.580000000000000000e+02 1.389259292119498224e-01 -9.590000000000000000e+02 1.387569663354068783e-01 -9.600000000000000000e+02 1.385884148867320420e-01 -9.610000000000000000e+02 1.384202735449500676e-01 -9.620000000000000000e+02 1.382525409946983586e-01 -9.630000000000000000e+02 1.380852159261809764e-01 -9.640000000000000000e+02 1.379182970351448267e-01 -9.650000000000000000e+02 1.377517830228466855e-01 -9.660000000000000000e+02 1.375856725960163951e-01 -9.670000000000000000e+02 1.374199644668294418e-01 -9.680000000000000000e+02 1.372546573528691805e-01 -9.690000000000000000e+02 1.370897499771081551e-01 -9.700000000000000000e+02 1.369252410678593879e-01 -9.710000000000000000e+02 1.367611293587581434e-01 -9.720000000000000000e+02 1.365974135887278729e-01 -9.730000000000000000e+02 1.364340925019515149e-01 -9.740000000000000000e+02 1.362711648478356352e-01 -9.750000000000000000e+02 1.361086293809845860e-01 -9.760000000000000000e+02 1.359464848611711407e-01 -9.770000000000000000e+02 1.357847300533093771e-01 -9.780000000000000000e+02 1.356233637274189829e-01 -9.790000000000000000e+02 1.354623846585962799e-01 -9.800000000000000000e+02 1.353017916269985965e-01 -9.810000000000000000e+02 1.351415834177943087e-01 -9.820000000000000000e+02 1.349817588211591479e-01 -9.830000000000000000e+02 1.348223166322229105e-01 -9.840000000000000000e+02 1.346632556510622969e-01 -9.850000000000000000e+02 1.345045746826611932e-01 -9.860000000000000000e+02 1.343462725368876065e-01 -9.870000000000000000e+02 1.341883480615597701e-01 -9.880000000000000000e+02 1.340308000100528529e-01 -9.890000000000000000e+02 1.338736272398056149e-01 -9.900000000000000000e+02 1.337168285799549550e-01 -9.910000000000000000e+02 1.335604028643794794e-01 -9.920000000000000000e+02 1.334043489316852071e-01 -9.930000000000000000e+02 1.332486656251746504e-01 -9.940000000000000000e+02 1.330933517596697702e-01 -9.950000000000000000e+02 1.329384062540855949e-01 -9.960000000000000000e+02 1.327838279325198600e-01 -9.970000000000000000e+02 1.326296156568088636e-01 -9.980000000000000000e+02 1.324757682933597747e-01 -9.990000000000000000e+02 1.323222847131252378e-01 -1.000000000000000000e+03 1.321691637915768103e-01 -1.001000000000000000e+03 1.320164044086875599e-01 -1.002000000000000000e+03 1.318640054489006730e-01 -1.003000000000000000e+03 1.317119658011041139e-01 -1.004000000000000000e+03 1.315602843586153869e-01 -1.005000000000000000e+03 1.314089600191504226e-01 -1.006000000000000000e+03 1.312579916848016226e-01 -1.007000000000000000e+03 1.311073782620212347e-01 -1.008000000000000000e+03 1.309571186615844929e-01 -1.009000000000000000e+03 1.308072117985737415e-01 -1.010000000000000000e+03 1.306576565923632527e-01 -1.011000000000000000e+03 1.305084519665871690e-01 -1.012000000000000000e+03 1.303595968491136625e-01 -1.013000000000000000e+03 1.302110901720373859e-01 -1.014000000000000000e+03 1.300629308716407251e-01 -1.015000000000000000e+03 1.299151178883825863e-01 -1.016000000000000000e+03 1.297676501668720561e-01 -1.017000000000000000e+03 1.296205266558471958e-01 -1.018000000000000000e+03 1.294737463081559459e-01 -1.019000000000000000e+03 1.293273080807343656e-01 -1.020000000000000000e+03 1.291812109345764348e-01 -1.021000000000000000e+03 1.290354538347310565e-01 -1.022000000000000000e+03 1.288900357502606731e-01 -1.023000000000000000e+03 1.287449556542367146e-01 -1.024000000000000000e+03 1.286002125237113713e-01 -1.025000000000000000e+03 1.284558053396971655e-01 -1.026000000000000000e+03 1.283117330871465511e-01 -1.027000000000000000e+03 1.281679947549354548e-01 -1.028000000000000000e+03 1.280245893358402387e-01 -1.029000000000000000e+03 1.278815158265200203e-01 -1.030000000000000000e+03 1.277387732274901377e-01 -1.031000000000000000e+03 1.275963605431077452e-01 -1.032000000000000000e+03 1.274542767815606825e-01 -1.033000000000000000e+03 1.273125209548309766e-01 -1.034000000000000000e+03 1.271710920786854604e-01 -1.035000000000000000e+03 1.270299891726599240e-01 -1.036000000000000000e+03 1.268892112600283895e-01 -1.037000000000000000e+03 1.267487573677982815e-01 -1.038000000000000000e+03 1.266086265266815614e-01 -1.039000000000000000e+03 1.264688177710780737e-01 -1.040000000000000000e+03 1.263293301390636669e-01 -1.041000000000000000e+03 1.261901626723622161e-01 -1.042000000000000000e+03 1.260513144163321331e-01 -1.043000000000000000e+03 1.259127844199509350e-01 -1.044000000000000000e+03 1.257745717357948156e-01 -1.045000000000000000e+03 1.256366754200144431e-01 -1.046000000000000000e+03 1.254990945323299356e-01 -1.047000000000000000e+03 1.253618281360048825e-01 -1.048000000000000000e+03 1.252248752978292745e-01 -1.049000000000000000e+03 1.250882350881037663e-01 -1.050000000000000000e+03 1.249519065806236479e-01 -1.051000000000000000e+03 1.248158888526591098e-01 -1.052000000000000000e+03 1.246801809849393816e-01 -1.053000000000000000e+03 1.245447820616378681e-01 -1.054000000000000000e+03 1.244096911703505004e-01 -1.055000000000000000e+03 1.242749074020829819e-01 -1.056000000000000000e+03 1.241404298512330112e-01 -1.057000000000000000e+03 1.240062576155750995e-01 -1.058000000000000000e+03 1.238723897962429737e-01 -1.059000000000000000e+03 1.237388254977097868e-01 -1.060000000000000000e+03 1.236055638277841762e-01 -1.061000000000000000e+03 1.234726038975752782e-01 -1.062000000000000000e+03 1.233399448214995836e-01 -1.063000000000000000e+03 1.232075857172361122e-01 -1.064000000000000000e+03 1.230755257057444263e-01 -1.065000000000000000e+03 1.229437639112212627e-01 -1.066000000000000000e+03 1.228122994611028224e-01 -1.067000000000000000e+03 1.226811314860330876e-01 -1.068000000000000000e+03 1.225502591198685542e-01 -1.069000000000000000e+03 1.224196814996454802e-01 -1.070000000000000000e+03 1.222893977655738068e-01 -1.071000000000000000e+03 1.221594070610183269e-01 -1.072000000000000000e+03 1.220297085324840297e-01 -1.073000000000000000e+03 1.219003013296086069e-01 -1.074000000000000000e+03 1.217711846051361124e-01 -1.075000000000000000e+03 1.216423575149093717e-01 -1.076000000000000000e+03 1.215138192178531612e-01 -1.077000000000000000e+03 1.213855688759627321e-01 -1.078000000000000000e+03 1.212576056542851444e-01 -1.079000000000000000e+03 1.211299287209078035e-01 -1.080000000000000000e+03 1.210025372469445554e-01 -1.081000000000000000e+03 1.208754304065162571e-01 -1.082000000000000000e+03 1.207486073767464752e-01 -1.083000000000000000e+03 1.206220673377426111e-01 -1.084000000000000000e+03 1.204958094725742113e-01 -1.085000000000000000e+03 1.203698329672737016e-01 -1.086000000000000000e+03 1.202441370108142116e-01 -1.087000000000000000e+03 1.201187207950938918e-01 -1.088000000000000000e+03 1.199935835149330970e-01 -1.089000000000000000e+03 1.198687243680439246e-01 -1.090000000000000000e+03 1.197441425550360011e-01 -1.091000000000000000e+03 1.196198372793898096e-01 -1.092000000000000000e+03 1.194958077474480018e-01 -1.093000000000000000e+03 1.193720531684009240e-01 -1.094000000000000000e+03 1.192485727542798996e-01 -1.095000000000000000e+03 1.191253657199293631e-01 -1.096000000000000000e+03 1.190024312830151171e-01 -1.097000000000000000e+03 1.188797686639917334e-01 -1.098000000000000000e+03 1.187573770861034689e-01 -1.099000000000000000e+03 1.186352557753638376e-01 +3.000000000000000000e+02 7.961299851462676214e-02 +3.010000000000000000e+02 1.332288155026307430e-01 +3.020000000000000000e+02 2.140794239934083465e-01 +3.030000000000000000e+02 3.358020697199494697e-01 +3.040000000000000000e+02 5.203650267662797146e-01 +3.050000000000000000e+02 8.039346299497034387e-01 +3.060000000000000000e+02 1.246857969960517787e+00 +3.070000000000000000e+02 1.948756173976117223e+00 +3.080000000000000000e+02 3.061564326085904231e+00 +3.090000000000000000e+02 4.754068346658284483e+00 +3.100000000000000000e+02 6.980099788528115745e+00 +3.110000000000000000e+02 8.989994104067182690e+00 +3.120000000000000000e+02 9.568274014305636399e+00 +3.130000000000000000e+02 8.602215291399884833e+00 +3.140000000000000000e+02 7.064599362725426879e+00 +3.150000000000000000e+02 5.654047497876379502e+00 +3.160000000000000000e+02 4.554202335271595459e+00 +3.170000000000000000e+02 3.734874132958712512e+00 +3.180000000000000000e+02 3.125853968470231337e+00 +3.190000000000000000e+02 2.666882617112256604e+00 +3.200000000000000000e+02 2.314416691882152044e+00 +3.210000000000000000e+02 2.038406572548078888e+00 +3.220000000000000000e+02 1.818230229845627210e+00 +3.230000000000000000e+02 1.639595893845350316e+00 +3.240000000000000000e+02 1.492441797633357714e+00 +3.250000000000000000e+02 1.369558229931185922e+00 +3.260000000000000000e+02 1.265686753132716502e+00 +3.270000000000000000e+02 1.176926314575905907e+00 +3.280000000000000000e+02 1.100336288900929382e+00 +3.290000000000000000e+02 1.033666940003522106e+00 +3.300000000000000000e+02 9.751734048420805934e-01 +3.310000000000000000e+02 9.234852495649015225e-01 +3.320000000000000000e+02 8.775135804346393398e-01 +3.330000000000000000e+02 8.363839278155630330e-01 +3.340000000000000000e+02 7.993870835692526988e-01 +3.350000000000000000e+02 7.659426242203544177e-01 +3.360000000000000000e+02 7.355715196817254053e-01 +3.370000000000000000e+02 7.078753324939935920e-01 +3.380000000000000000e+02 6.825202553748643819e-01 +3.390000000000000000e+02 6.592247409811804459e-01 +3.400000000000000000e+02 6.377498271070528579e-01 +3.410000000000000000e+02 6.178915046436176395e-01 +3.420000000000000000e+02 5.994746482197726989e-01 +3.430000000000000000e+02 5.823481528430023424e-01 +3.440000000000000000e+02 5.663810090244997264e-01 +3.450000000000000000e+02 5.514591139482380999e-01 +3.460000000000000000e+02 5.374826641907224367e-01 +3.470000000000000000e+02 5.243640111435605711e-01 +3.480000000000000000e+02 5.120258870188540978e-01 +3.490000000000000000e+02 5.003999295189858199e-01 +3.500000000000000000e+02 4.894254486430644757e-01 +3.510000000000000000e+02 4.790483909090546000e-01 +3.520000000000000000e+02 4.692204653945375448e-01 +3.530000000000000000e+02 4.598984030952154023e-01 +3.540000000000000000e+02 4.510433266541649666e-01 +3.550000000000000000e+02 4.426202118881453762e-01 +3.560000000000000000e+02 4.345974260009224932e-01 +3.570000000000000000e+02 4.269463301312558245e-01 +3.580000000000000000e+02 4.196409360911090292e-01 +3.590000000000000000e+02 4.126576089255324931e-01 +3.600000000000000000e+02 4.059748083617220060e-01 +3.610000000000000000e+02 3.995728633805583629e-01 +3.620000000000000000e+02 3.934337750951352741e-01 +3.630000000000000000e+02 3.875410439001367724e-01 +3.640000000000000000e+02 3.818795174965109451e-01 +3.650000000000000000e+02 3.764352569253868741e-01 +3.660000000000000000e+02 3.711954181837090472e-01 +3.670000000000000000e+02 3.661481473589716096e-01 +3.680000000000000000e+02 3.612824875251964829e-01 +3.690000000000000000e+02 3.565882958973327632e-01 +3.700000000000000000e+02 3.520561699557953061e-01 +3.710000000000000000e+02 3.476773814336127644e-01 +3.720000000000000000e+02 3.434438172114515075e-01 +3.730000000000000000e+02 3.393479262955031439e-01 +3.740000000000000000e+02 3.353826721633714203e-01 +3.750000000000000000e+02 3.315414898571716340e-01 +3.760000000000000000e+02 3.278182472833725547e-01 +3.770000000000000000e+02 3.242072102478924522e-01 +3.780000000000000000e+02 3.207030108140977442e-01 +3.790000000000000000e+02 3.173006186224021641e-01 +3.800000000000000000e+02 3.139953148542299344e-01 +3.810000000000000000e+02 3.107826685611519424e-01 +3.820000000000000000e+02 3.076585151131501772e-01 +3.830000000000000000e+02 3.046189365486084988e-01 +3.840000000000000000e+02 3.016602436337605386e-01 +3.850000000000000000e+02 2.987789594610280042e-01 +3.860000000000000000e+02 2.959718044349548549e-01 +3.870000000000000000e+02 2.932356825109964649e-01 +3.880000000000000000e+02 2.905676685672203274e-01 +3.890000000000000000e+02 2.879649968019114548e-01 +3.900000000000000000e+02 2.854250500613068620e-01 +3.910000000000000000e+02 2.829453500119029075e-01 +3.920000000000000000e+02 2.805235480805149395e-01 +3.930000000000000000e+02 2.781574170931823686e-01 +3.940000000000000000e+02 2.758448435509671670e-01 +3.950000000000000000e+02 2.735838204868805135e-01 +3.960000000000000000e+02 2.713724408536276611e-01 +3.970000000000000000e+02 2.692088913968753716e-01 +3.980000000000000000e+02 2.670914469729461227e-01 +3.990000000000000000e+02 2.650184652738983848e-01 +4.000000000000000000e+02 2.629883819263793554e-01 +4.010000000000000000e+02 2.609997059337193503e-01 +4.020000000000000000e+02 2.590510154336600479e-01 +4.030000000000000000e+02 2.571409537464698358e-01 +4.040000000000000000e+02 2.552682256906250169e-01 +4.050000000000000000e+02 2.534315941451266152e-01 +4.060000000000000000e+02 2.516298768394835683e-01 +4.070000000000000000e+02 2.498619433539414070e-01 +4.080000000000000000e+02 2.481267123141129294e-01 +4.090000000000000000e+02 2.464231487654904296e-01 +4.100000000000000000e+02 2.447502617145134174e-01 +4.110000000000000000e+02 2.431071018240412718e-01 +4.120000000000000000e+02 2.414927592520367816e-01 +4.130000000000000000e+02 2.399063616231849327e-01 +4.140000000000000000e+02 2.383470721240262269e-01 +4.150000000000000000e+02 2.368140877129318866e-01 +4.160000000000000000e+02 2.353066374369191249e-01 +4.170000000000000000e+02 2.338239808479604664e-01 +4.180000000000000000e+02 2.323654065119738765e-01 +4.190000000000000000e+02 2.309302306042842479e-01 +4.200000000000000000e+02 2.295177955857041763e-01 +4.210000000000000000e+02 2.281274689539329326e-01 +4.220000000000000000e+02 2.267586420653266988e-01 +4.230000000000000000e+02 2.254107290224274251e-01 +4.240000000000000000e+02 2.240831656230506952e-01 +4.250000000000000000e+02 2.227754083669700180e-01 +4.260000000000000000e+02 2.214869335165711162e-01 +4.270000000000000000e+02 2.202172362080710710e-01 +4.280000000000000000e+02 2.189658296101751611e-01 +4.290000000000000000e+02 2.177322441272342146e-01 +4.300000000000000000e+02 2.165160266441842063e-01 +4.310000000000000000e+02 2.153167398107430908e-01 +4.320000000000000000e+02 2.141339613625038996e-01 +4.330000000000000000e+02 2.129672834767183942e-01 +4.340000000000000000e+02 2.118163121607318511e-01 +4.350000000000000000e+02 2.106806666711602549e-01 +4.360000000000000000e+02 2.095599789620027076e-01 +4.370000000000000000e+02 2.084538931600571632e-01 +4.380000000000000000e+02 2.073620650660302211e-01 +4.390000000000000000e+02 2.062841616799475086e-01 +4.400000000000000000e+02 2.052198607494348237e-01 +4.410000000000000000e+02 2.041688503396373866e-01 +4.420000000000000000e+02 2.031308284235689432e-01 +4.430000000000000000e+02 2.021055024917489673e-01 +4.440000000000000000e+02 2.010925891801146337e-01 +4.450000000000000000e+02 2.000918139151833253e-01 +4.460000000000000000e+02 1.991029105755633688e-01 +4.470000000000000000e+02 1.981256211689262081e-01 +4.480000000000000000e+02 1.971596955236434578e-01 +4.490000000000000000e+02 1.962048909942987196e-01 +4.500000000000000000e+02 1.952609721803653386e-01 +4.510000000000000000e+02 1.943277106573545743e-01 +4.520000000000000000e+02 1.934048847198230336e-01 +4.530000000000000000e+02 1.924922791356010188e-01 +4.540000000000000000e+02 1.915896849107006916e-01 +4.550000000000000000e+02 1.906968990643508333e-01 +4.560000000000000000e+02 1.898137244136666735e-01 +4.570000000000000000e+02 1.889399693674656822e-01 +4.580000000000000000e+02 1.880754477287910620e-01 +4.590000000000000000e+02 1.872199785057147292e-01 +4.600000000000000000e+02 1.863733857300050589e-01 +4.610000000000000000e+02 1.855354982833024580e-01 +4.620000000000000000e+02 1.847061497304345323e-01 +4.630000000000000000e+02 1.838851781595266521e-01 +4.640000000000000000e+02 1.830724260285875316e-01 +4.650000000000000000e+02 1.822677400182809437e-01 +4.660000000000000000e+02 1.814709708905761498e-01 +4.670000000000000000e+02 1.806819733530212746e-01 +4.680000000000000000e+02 1.799006059283672354e-01 +4.690000000000000000e+02 1.791267308293136296e-01 +4.700000000000000000e+02 1.783602138381267521e-01 +4.710000000000000000e+02 1.776009241909256298e-01 +4.720000000000000000e+02 1.768487344664192995e-01 +4.730000000000000000e+02 1.761035204788990172e-01 +4.740000000000000000e+02 1.753651611752923556e-01 +4.750000000000000000e+02 1.746335385361159898e-01 +4.760000000000000000e+02 1.739085374801370154e-01 +4.770000000000000000e+02 1.731900457725939479e-01 +4.780000000000000000e+02 1.724779539368175296e-01 +4.790000000000000000e+02 1.717721551691251125e-01 +4.800000000000000000e+02 1.710725452568100935e-01 +4.810000000000000000e+02 1.703790224991346414e-01 +4.820000000000000000e+02 1.696914876311798881e-01 +4.830000000000000000e+02 1.690098437504338191e-01 +4.840000000000000000e+02 1.683339962460135286e-01 +4.850000000000000000e+02 1.676638527303926374e-01 +4.860000000000000000e+02 1.669993229735621254e-01 +4.870000000000000000e+02 1.663403188394913523e-01 +4.880000000000000000e+02 1.656867542248213754e-01 +4.890000000000000000e+02 1.650385449996839560e-01 +4.900000000000000000e+02 1.643956089505726470e-01 +4.910000000000000000e+02 1.637578657251728687e-01 +4.920000000000000000e+02 1.631252367790876068e-01 +4.930000000000000000e+02 1.624976453243637819e-01 +4.940000000000000000e+02 1.618750162797696068e-01 +4.950000000000000000e+02 1.612572762227393597e-01 +4.960000000000000000e+02 1.606443533429307291e-01 +4.970000000000000000e+02 1.600361773973174306e-01 +4.980000000000000000e+02 1.594326796667862034e-01 +4.990000000000000000e+02 1.588337929141440674e-01 +5.000000000000000000e+02 1.582394513435155803e-01 +5.010000000000000000e+02 1.576495905610547088e-01 +5.020000000000000000e+02 1.570641475369312923e-01 +5.030000000000000000e+02 1.564830605685475218e-01 +5.040000000000000000e+02 1.559062692449307008e-01 +5.050000000000000000e+02 1.553337144122596547e-01 +5.060000000000000000e+02 1.547653381404952011e-01 +5.070000000000000000e+02 1.542010836910570060e-01 +5.080000000000000000e+02 1.536408954855126019e-01 +5.090000000000000000e+02 1.530847190752566700e-01 +5.100000000000000000e+02 1.525325011121264895e-01 +5.110000000000000000e+02 1.519841893199313232e-01 +5.120000000000000000e+02 1.514397324668538269e-01 +5.130000000000000000e+02 1.508990803386966173e-01 +5.140000000000000000e+02 1.503621837129602012e-01 +5.150000000000000000e+02 1.498289943336809926e-01 +5.160000000000000000e+02 1.492994648870618890e-01 +5.170000000000000000e+02 1.487735489778009845e-01 +5.180000000000000000e+02 1.482512011061621615e-01 +5.190000000000000000e+02 1.477323766457019349e-01 +5.200000000000000000e+02 1.472170318216717566e-01 +5.210000000000000000e+02 1.467051236415289894e-01 +5.220000000000000000e+02 1.461966100694034876e-01 +5.230000000000000000e+02 1.456914497601094205e-01 +5.240000000000000000e+02 1.451896020471993842e-01 +5.250000000000000000e+02 1.446910271597220132e-01 +5.260000000000000000e+02 1.441956860136566487e-01 +5.270000000000000000e+02 1.437035402421477648e-01 +5.280000000000000000e+02 1.432145521784317366e-01 +5.290000000000000000e+02 1.427286848392624319e-01 +5.300000000000000000e+02 1.422459019087904397e-01 +5.310000000000000000e+02 1.417661677229094530e-01 +5.320000000000000000e+02 1.412894472540359159e-01 +5.330000000000000000e+02 1.408157060963131368e-01 +5.340000000000000000e+02 1.403449104512287382e-01 +5.350000000000000000e+02 1.398770271136304533e-01 +5.360000000000000000e+02 1.394120234581230355e-01 +5.370000000000000000e+02 1.389498674258441147e-01 +5.380000000000000000e+02 1.384905275116004308e-01 +5.390000000000000000e+02 1.380339727513476555e-01 +5.400000000000000000e+02 1.375801727100182115e-01 +5.410000000000000000e+02 1.371290974696694198e-01 +5.420000000000000000e+02 1.366807176179598571e-01 +5.430000000000000000e+02 1.362350042369165071e-01 +5.440000000000000000e+02 1.357919288920213519e-01 +5.450000000000000000e+02 1.353514636215761568e-01 +5.460000000000000000e+02 1.349135809263443952e-01 +5.470000000000000000e+02 1.344782537594772232e-01 +5.480000000000000000e+02 1.340454555166927519e-01 +5.490000000000000000e+02 1.336151600267161399e-01 +5.500000000000000000e+02 1.331873415419657092e-01 +5.510000000000000000e+02 1.327619747294848385e-01 +5.520000000000000000e+02 1.323390346621011182e-01 +5.530000000000000000e+02 1.319184968098135180e-01 +5.540000000000000000e+02 1.315003370313998776e-01 +5.550000000000000000e+02 1.310845315662466370e-01 +5.560000000000000000e+02 1.306710570263680538e-01 +5.570000000000000000e+02 1.302598903886419413e-01 +5.580000000000000000e+02 1.298510089872303985e-01 +5.590000000000000000e+02 1.294443905062016287e-01 +5.600000000000000000e+02 1.290400129723235645e-01 +5.610000000000000000e+02 1.286378547480406531e-01 +5.620000000000000000e+02 1.282378945246333557e-01 +5.630000000000000000e+02 1.278401113154921109e-01 +5.640000000000000000e+02 1.274444844497578389e-01 +5.650000000000000000e+02 1.270509935657559153e-01 +5.660000000000000000e+02 1.266596186048500883e-01 +5.670000000000000000e+02 1.262703398055137760e-01 +5.680000000000000000e+02 1.258831376973126581e-01 +5.690000000000000000e+02 1.254979930951669320e-01 +5.700000000000000000e+02 1.251148870937316415e-01 +5.710000000000000000e+02 1.247338010619008508e-01 +5.720000000000000000e+02 1.243547166374542462e-01 +5.730000000000000000e+02 1.239776157218182850e-01 +5.740000000000000000e+02 1.236024804749573935e-01 +5.750000000000000000e+02 1.232292933103926735e-01 +5.760000000000000000e+02 1.228580368903178094e-01 +5.770000000000000000e+02 1.224886941208494368e-01 +5.780000000000000000e+02 1.221212481473756550e-01 +5.790000000000000000e+02 1.217556823500183238e-01 +5.800000000000000000e+02 1.213919803391943636e-01 +5.810000000000000000e+02 1.210301259512846506e-01 +5.820000000000000000e+02 1.206701032444012500e-01 +5.830000000000000000e+02 1.203118964942487962e-01 +5.840000000000000000e+02 1.199554901900795889e-01 +5.850000000000000000e+02 1.196008690307446137e-01 +5.860000000000000000e+02 1.192480179208306595e-01 +5.870000000000000000e+02 1.188969219668824795e-01 +5.880000000000000000e+02 1.185475664737183077e-01 +5.890000000000000000e+02 1.181999369408137240e-01 +5.900000000000000000e+02 1.178540190587768349e-01 +5.910000000000000000e+02 1.175097987059009891e-01 +5.920000000000000000e+02 1.171672619447881175e-01 +5.930000000000000000e+02 1.168263950190492340e-01 +5.940000000000000000e+02 1.164871843500789456e-01 +5.950000000000000000e+02 1.161496165338983394e-01 +5.960000000000000000e+02 1.158136783380677715e-01 +5.970000000000000000e+02 1.154793566986649367e-01 +5.980000000000000000e+02 1.151466387173311207e-01 +5.990000000000000000e+02 1.148155116583784441e-01 +6.000000000000000000e+02 1.144859629459602929e-01 +6.010000000000000000e+02 1.141579801613047396e-01 +6.020000000000000000e+02 1.138315510610745790e-01 +6.030000000000000000e+02 1.135066634902111432e-01 +6.040000000000000000e+02 1.131833054857417364e-01 +6.050000000000000000e+02 1.128614652721903477e-01 +6.060000000000000000e+02 1.125411311557544813e-01 +6.070000000000000000e+02 1.122222916051521246e-01 +6.080000000000000000e+02 1.119049352283636445e-01 +6.090000000000000000e+02 1.115890507702966272e-01 +6.100000000000000000e+02 1.112746271105028162e-01 +6.110000000000000000e+02 1.109616532609311729e-01 +6.120000000000000000e+02 1.106501183637413621e-01 +6.130000000000000000e+02 1.103400116891502525e-01 +6.140000000000000000e+02 1.100313226333304029e-01 +6.150000000000000000e+02 1.097240407163439790e-01 +6.160000000000000000e+02 1.094181555801294059e-01 +6.170000000000000000e+02 1.091136569865165939e-01 +6.180000000000000000e+02 1.088105348152902385e-01 +6.190000000000000000e+02 1.085087790622894233e-01 +6.200000000000000000e+02 1.082083798375482048e-01 +6.210000000000000000e+02 1.079093273634639805e-01 +6.220000000000000000e+02 1.076116119730188142e-01 +6.230000000000000000e+02 1.073152241080153890e-01 +6.240000000000000000e+02 1.070201543173670139e-01 +6.250000000000000000e+02 1.067263932554120415e-01 +6.260000000000000000e+02 1.064339316802580815e-01 +6.270000000000000000e+02 1.061427604521662099e-01 +6.280000000000000000e+02 1.058528705319620317e-01 +6.290000000000000000e+02 1.055642529794833112e-01 +6.300000000000000000e+02 1.052768989520453252e-01 +6.310000000000000000e+02 1.049907997029521783e-01 +6.320000000000000000e+02 1.047059465800220385e-01 +6.330000000000000000e+02 1.044223310241524094e-01 +6.340000000000000000e+02 1.041399445679029173e-01 +6.350000000000000000e+02 1.038587788341130691e-01 +6.360000000000000000e+02 1.035788255345441305e-01 +6.370000000000000000e+02 1.033000764685384071e-01 +6.380000000000000000e+02 1.030225235217194779e-01 +6.390000000000000000e+02 1.027461586647041569e-01 +6.400000000000000000e+02 1.024709739518415291e-01 +6.410000000000000000e+02 1.021969615199819770e-01 +6.420000000000000000e+02 1.019241135872587661e-01 +6.430000000000000000e+02 1.016524224518972896e-01 +6.440000000000000000e+02 1.013818804910511656e-01 +6.450000000000000000e+02 1.011124801596522821e-01 +6.460000000000000000e+02 1.008442139892827411e-01 +6.470000000000000000e+02 1.005770745870757932e-01 +6.480000000000000000e+02 1.003110546346218795e-01 +6.490000000000000000e+02 1.000461468869114218e-01 +6.500000000000000000e+02 9.978234417128330203e-02 +6.510000000000000000e+02 9.951963938640100149e-02 +6.520000000000000000e+02 9.925802550124120105e-02 +6.530000000000000000e+02 9.899749555410496116e-02 +6.540000000000000000e+02 9.873804265164554117e-02 +6.550000000000000000e+02 9.847965996791052667e-02 +6.560000000000000000e+02 9.822234074340530086e-02 +6.570000000000000000e+02 9.796607828417108754e-02 +6.580000000000000000e+02 9.771086596087912024e-02 +6.590000000000000000e+02 9.745669720793985469e-02 +6.600000000000000000e+02 9.720356552263154093e-02 +6.610000000000000000e+02 9.695146446423963393e-02 +6.620000000000000000e+02 9.670038765321312124e-02 +6.630000000000000000e+02 9.645032877033810070e-02 +6.640000000000000000e+02 9.620128155591793628e-02 +6.650000000000000000e+02 9.595323980897974003e-02 +6.660000000000000000e+02 9.570619738648178387e-02 +6.670000000000000000e+02 9.546014820254186684e-02 +6.680000000000000000e+02 9.521508622767922703e-02 +6.690000000000000000e+02 9.497100548806669540e-02 +6.700000000000000000e+02 9.472790006479210601e-02 +6.710000000000000000e+02 9.448576409314531077e-02 +6.720000000000000000e+02 9.424459176189903253e-02 +6.730000000000000000e+02 9.400437731261848673e-02 +6.740000000000000000e+02 9.376511503896947652e-02 +6.750000000000000000e+02 9.352679928604872017e-02 +6.760000000000000000e+02 9.328942444971767556e-02 +6.770000000000000000e+02 9.305298497595046459e-02 +6.780000000000000000e+02 9.281747536019520350e-02 +6.790000000000000000e+02 9.258289014673913575e-02 +6.800000000000000000e+02 9.234922392809159775e-02 +6.810000000000000000e+02 9.211647134437117579e-02 +6.820000000000000000e+02 9.188462708270714319e-02 +6.830000000000000000e+02 9.165368587664779465e-02 +6.840000000000000000e+02 9.142364250558188132e-02 +6.850000000000000000e+02 9.119449179416302953e-02 +6.860000000000000000e+02 9.096622861175272801e-02 +6.870000000000000000e+02 9.073884787186277390e-02 +6.880000000000000000e+02 9.051234453161291493e-02 +6.890000000000000000e+02 9.028671359119457007e-02 +6.900000000000000000e+02 9.006195009334588830e-02 +6.910000000000000000e+02 8.983804912283120669e-02 +6.920000000000000000e+02 8.961500580592933474e-02 +6.930000000000000000e+02 8.939281530993493929e-02 +6.940000000000000000e+02 8.917147284266045693e-02 +6.950000000000000000e+02 8.895097365195243910e-02 +6.960000000000000000e+02 8.873131302520982644e-02 +6.970000000000000000e+02 8.851248628891514314e-02 +6.980000000000000000e+02 8.829448880816814782e-02 +6.990000000000000000e+02 8.807731598622996205e-02 +7.000000000000000000e+02 8.786096326407055734e-02 +7.010000000000000000e+02 8.764542611993125787e-02 +7.020000000000000000e+02 8.743070006888306600e-02 +7.030000000000000000e+02 8.721678066239943461e-02 +7.040000000000000000e+02 8.700366348793345250e-02 +7.050000000000000000e+02 8.679134416850203815e-02 +7.060000000000000000e+02 8.657981836227203465e-02 +7.070000000000000000e+02 8.636908176216102906e-02 +7.080000000000000000e+02 8.615913009543682555e-02 +7.090000000000000000e+02 8.594995912332500931e-02 +7.100000000000000000e+02 8.574156464062566985e-02 +7.110000000000000000e+02 8.553394247532862538e-02 +7.120000000000000000e+02 8.532708848824398229e-02 +7.130000000000000000e+02 8.512099857262904468e-02 +7.140000000000000000e+02 8.491566865382750573e-02 +7.150000000000000000e+02 8.471109468890775096e-02 +7.160000000000000000e+02 8.450727266631387347e-02 +7.170000000000000000e+02 8.430419860551655042e-02 +7.180000000000000000e+02 8.410186855666709760e-02 +7.190000000000000000e+02 8.390027860026526285e-02 +7.200000000000000000e+02 8.369942484682130202e-02 +7.210000000000000000e+02 8.349930343653337583e-02 +7.220000000000000000e+02 8.329991053895692554e-02 +7.230000000000000000e+02 8.310124235269428228e-02 +7.240000000000000000e+02 8.290329510507447874e-02 +7.250000000000000000e+02 8.270606505184592561e-02 +7.260000000000000000e+02 8.250954847687301530e-02 +7.270000000000000000e+02 8.231374169183171274e-02 +7.280000000000000000e+02 8.211864103591502706e-02 +7.290000000000000000e+02 8.192424287554087026e-02 +7.300000000000000000e+02 8.173054360406327434e-02 +7.310000000000000000e+02 8.153753964148807709e-02 +7.320000000000000000e+02 8.134522743419352053e-02 +7.330000000000000000e+02 8.115360345465280623e-02 +7.340000000000000000e+02 8.096266420116210449e-02 +7.350000000000000000e+02 8.077240619757197759e-02 +7.360000000000000000e+02 8.058282599302331317e-02 +7.370000000000000000e+02 8.039392016168322996e-02 +7.380000000000000000e+02 8.020568530248957384e-02 +7.390000000000000000e+02 8.001811803889698205e-02 +7.400000000000000000e+02 7.983121501862579239e-02 +7.410000000000000000e+02 7.964497291341322838e-02 +7.420000000000000000e+02 7.945938841877041303e-02 +7.430000000000000000e+02 7.927445825374186683e-02 +7.440000000000000000e+02 7.909017916066828080e-02 +7.450000000000000000e+02 7.890654790495252313e-02 +7.460000000000000000e+02 7.872356127482506294e-02 +7.470000000000000000e+02 7.854121608112407671e-02 +7.480000000000000000e+02 7.835950915705916509e-02 +7.490000000000000000e+02 7.817843735799966109e-02 +7.500000000000000000e+02 7.799799756125053163e-02 +7.510000000000000000e+02 7.781818666583417698e-02 +7.520000000000000000e+02 7.763900159228455389e-02 +7.530000000000000000e+02 7.746043928242785093e-02 +7.540000000000000000e+02 7.728249669917981735e-02 +7.550000000000000000e+02 7.710517082634169017e-02 +7.560000000000000000e+02 7.692845866839373437e-02 +7.570000000000000000e+02 7.675235725029716516e-02 +7.580000000000000000e+02 7.657686361729941493e-02 +7.590000000000000000e+02 7.640197483473448736e-02 +7.600000000000000000e+02 7.622768798783630118e-02 +7.610000000000000000e+02 7.605400018154383213e-02 +7.620000000000000000e+02 7.588090854031788457e-02 +7.630000000000000000e+02 7.570841020795456011e-02 +7.640000000000000000e+02 7.553650234740082181e-02 +7.650000000000000000e+02 7.536518214057852383e-02 +7.660000000000000000e+02 7.519444678820114136e-02 +7.670000000000000000e+02 7.502429350960332366e-02 +7.680000000000000000e+02 7.485471954256316118e-02 +7.690000000000000000e+02 7.468572214313343172e-02 +7.700000000000000000e+02 7.451729858547094520e-02 +7.710000000000000000e+02 7.434944616167016296e-02 +7.720000000000000000e+02 7.418216218159577602e-02 +7.730000000000000000e+02 7.401544397272466491e-02 +7.740000000000000000e+02 7.384928887997892211e-02 +7.750000000000000000e+02 7.368369426557253021e-02 +7.760000000000000000e+02 7.351865750884771511e-02 +7.770000000000000000e+02 7.335417600612696709e-02 +7.780000000000000000e+02 7.319024717055415408e-02 +7.790000000000000000e+02 7.302686843194303168e-02 +7.800000000000000000e+02 7.286403723663467669e-02 +7.810000000000000000e+02 7.270175104734004357e-02 +7.820000000000000000e+02 7.254000734299849429e-02 +7.830000000000000000e+02 7.237880361863653633e-02 +7.840000000000000000e+02 7.221813738521926096e-02 +7.850000000000000000e+02 7.205800616951270332e-02 +7.860000000000000000e+02 7.189840751394413476e-02 +7.870000000000000000e+02 7.173933897646456170e-02 +7.880000000000000000e+02 7.158079813041265393e-02 +7.890000000000000000e+02 7.142278256437989414e-02 +7.900000000000000000e+02 7.126528988207803117e-02 +7.910000000000000000e+02 7.110831770220976678e-02 +7.920000000000000000e+02 7.095186365833487663e-02 +7.930000000000000000e+02 7.079592539874554613e-02 +7.940000000000000000e+02 7.064050058633830620e-02 +7.950000000000000000e+02 7.048558689848902215e-02 +7.960000000000000000e+02 7.033118202692904830e-02 +7.970000000000000000e+02 7.017728367762288144e-02 +7.980000000000000000e+02 7.002388957064674402e-02 +7.990000000000000000e+02 6.987099744006955437e-02 +8.000000000000000000e+02 6.971860503383361940e-02 +8.010000000000000000e+02 6.956671011364025381e-02 +8.020000000000000000e+02 6.941531045483030626e-02 +8.030000000000000000e+02 6.926440384627337299e-02 +8.040000000000000000e+02 6.911398809025275092e-02 +8.050000000000000000e+02 6.896406100235479009e-02 +8.060000000000000000e+02 6.881462041135676111e-02 +8.070000000000000000e+02 6.866566415912081500e-02 +8.080000000000000000e+02 6.851719010048246128e-02 +8.090000000000000000e+02 6.836919610314487472e-02 +8.100000000000000000e+02 6.822168004757425686e-02 +8.110000000000000000e+02 6.807463982689469784e-02 +8.120000000000000000e+02 6.792807334678388487e-02 +8.130000000000000000e+02 6.778197852537252988e-02 +8.140000000000000000e+02 6.763635329314113265e-02 +8.150000000000000000e+02 6.749119559282232284e-02 +8.160000000000000000e+02 6.734650337930052355e-02 +8.170000000000000000e+02 6.720227461951526482e-02 +8.180000000000000000e+02 6.705850729236101371e-02 +8.190000000000000000e+02 6.691519938859687155e-02 +8.200000000000000000e+02 6.677234891074584899e-02 +8.210000000000000000e+02 6.662995387300783834e-02 +8.220000000000000000e+02 6.648801230115966576e-02 +8.230000000000000000e+02 6.634652223246935432e-02 +8.240000000000000000e+02 6.620548171560201867e-02 +8.250000000000000000e+02 6.606488881053071416e-02 +8.260000000000000000e+02 6.592474158844759125e-02 +8.270000000000000000e+02 6.578503813167710379e-02 +8.280000000000000000e+02 6.564577653358878717e-02 +8.290000000000000000e+02 6.550695489850784370e-02 +8.300000000000000000e+02 6.536857134163538696e-02 +8.310000000000000000e+02 6.523062398895929093e-02 +8.320000000000000000e+02 6.509311097717457306e-02 +8.330000000000000000e+02 6.495603045359808758e-02 +8.340000000000000000e+02 6.481938057608727100e-02 +8.350000000000000000e+02 6.468315951296153832e-02 +8.360000000000000000e+02 6.454736544291815592e-02 +8.370000000000000000e+02 6.441199655495803700e-02 +8.380000000000000000e+02 6.427705104830210014e-02 +8.390000000000000000e+02 6.414252713231743952e-02 +8.400000000000000000e+02 6.400842302644024762e-02 +8.410000000000000000e+02 6.387473696009483837e-02 +8.420000000000000000e+02 6.374146717262732520e-02 +8.430000000000000000e+02 6.360861191322132735e-02 +8.440000000000000000e+02 6.347616944083175894e-02 +8.450000000000000000e+02 6.334413802410918115e-02 +8.460000000000000000e+02 6.321251594132408502e-02 +8.470000000000000000e+02 6.308130148030240136e-02 +8.480000000000000000e+02 6.295049293834584225e-02 +8.490000000000000000e+02 6.282008862216974243e-02 +8.500000000000000000e+02 6.269008684783013152e-02 +8.510000000000000000e+02 6.256048594065226343e-02 +8.520000000000000000e+02 6.243128423516935283e-02 +8.530000000000000000e+02 6.230248007504667063e-02 +8.540000000000000000e+02 6.217407181302170988e-02 +8.550000000000000000e+02 6.204605781083433191e-02 +8.560000000000000000e+02 6.191843643916138812e-02 +8.570000000000000000e+02 6.179120607755436700e-02 +8.580000000000000000e+02 6.166436511437235757e-02 +8.590000000000000000e+02 6.153791194671959230e-02 +8.600000000000000000e+02 6.141184498038079059e-02 +8.610000000000000000e+02 6.128616262976280260e-02 +8.620000000000000000e+02 6.116086331782810692e-02 +8.630000000000000000e+02 6.103594547603619774e-02 +8.640000000000000000e+02 6.091140754428196052e-02 +8.650000000000000000e+02 6.078724797083638609e-02 +8.660000000000000000e+02 6.066346521228518224e-02 +8.670000000000000000e+02 6.054005773347347769e-02 +8.680000000000000000e+02 6.041702400744229651e-02 +8.690000000000000000e+02 6.029436251537583641e-02 +8.700000000000000000e+02 6.017207174654047586e-02 +8.710000000000000000e+02 6.005015019822931843e-02 +8.720000000000000000e+02 5.992859637570507186e-02 +8.730000000000000000e+02 5.980740879214777039e-02 +8.740000000000000000e+02 5.968658596859374027e-02 +8.750000000000000000e+02 5.956612643388636830e-02 +8.760000000000000000e+02 5.944602872461682980e-02 +8.770000000000000000e+02 5.932629138507602290e-02 +8.780000000000000000e+02 5.920691296719701041e-02 +8.790000000000000000e+02 5.908789203050245076e-02 +8.800000000000000000e+02 5.896922714205522775e-02 +8.810000000000000000e+02 5.885091687640416069e-02 +8.820000000000000000e+02 5.873295981553382922e-02 +8.830000000000000000e+02 5.861535454881306589e-02 +8.840000000000000000e+02 5.849809967294432311e-02 +8.850000000000000000e+02 5.838119379191560043e-02 +8.860000000000000000e+02 5.826463551694777143e-02 +8.870000000000000000e+02 5.814842346644778087e-02 +8.880000000000000000e+02 5.803255626596106470e-02 +8.890000000000000000e+02 5.791703254812029245e-02 +8.900000000000000000e+02 5.780185095260030603e-02 +8.910000000000000000e+02 5.768701012606759770e-02 +8.920000000000000000e+02 5.757250872213757337e-02 +8.930000000000000000e+02 5.745834540132586238e-02 +8.940000000000000000e+02 5.734451883100093877e-02 +8.950000000000000000e+02 5.723102768533962909e-02 +8.960000000000000000e+02 5.711787064528337649e-02 +8.970000000000000000e+02 5.700504639849190286e-02 +8.980000000000000000e+02 5.689255363929695414e-02 +8.990000000000000000e+02 5.678039106866154123e-02 +9.000000000000000000e+02 5.666855739413403925e-02 +9.010000000000000000e+02 5.655705132980475697e-02 +9.020000000000000000e+02 5.644587159626474060e-02 +9.030000000000000000e+02 5.633501692056052529e-02 +9.040000000000000000e+02 5.622448603615591567e-02 +9.050000000000000000e+02 5.611427768288385770e-02 +9.060000000000000000e+02 5.600439060691189685e-02 +9.070000000000000000e+02 5.589482356069510466e-02 +9.080000000000000000e+02 5.578557530293885847e-02 +9.090000000000000000e+02 5.567664459855761749e-02 +9.100000000000000000e+02 5.556803021863365027e-02 +9.110000000000000000e+02 5.545973094037940504e-02 +9.120000000000000000e+02 5.535174554709338529e-02 +9.130000000000000000e+02 5.524407282812886927e-02 +9.140000000000000000e+02 5.513671157884629526e-02 +9.150000000000000000e+02 5.502966060058165493e-02 +9.160000000000000000e+02 5.492291870060433956e-02 +9.170000000000000000e+02 5.481648469208057900e-02 +9.180000000000000000e+02 5.471035739403662390e-02 +9.190000000000000000e+02 5.460453563132046384e-02 +9.200000000000000000e+02 5.449901823456317074e-02 +9.210000000000000000e+02 5.439380404014901305e-02 +9.220000000000000000e+02 5.428889189017009620e-02 +9.230000000000000000e+02 5.418428063239608822e-02 +9.240000000000000000e+02 5.407996912023766561e-02 +9.250000000000000000e+02 5.397595621270976501e-02 +9.260000000000000000e+02 5.387224077439715930e-02 +9.270000000000000000e+02 5.376882167542018642e-02 +9.280000000000000000e+02 5.366569779140005492e-02 +9.290000000000000000e+02 5.356286800342188043e-02 +9.300000000000000000e+02 5.346033119800532030e-02 +9.310000000000000000e+02 5.335808626706761704e-02 +9.320000000000000000e+02 5.325613210788914670e-02 +9.330000000000000000e+02 5.315446762308459472e-02 +9.340000000000000000e+02 5.305309172056539568e-02 +9.350000000000000000e+02 5.295200331351098549e-02 +9.360000000000000000e+02 5.285120132033131746e-02 +9.370000000000000000e+02 5.275068466464050143e-02 +9.380000000000000000e+02 5.265045227522070770e-02 +9.390000000000000000e+02 5.255050308599330117e-02 +9.400000000000000000e+02 5.245083603598438282e-02 +9.410000000000000000e+02 5.235145006929694395e-02 +9.420000000000000000e+02 5.225234413507608144e-02 +9.430000000000000000e+02 5.215351718748354598e-02 +9.440000000000000000e+02 5.205496818566268669e-02 +9.450000000000000000e+02 5.195669609370881514e-02 +9.460000000000000000e+02 5.185869988064253228e-02 +9.470000000000000000e+02 5.176097852037665065e-02 +9.480000000000000000e+02 5.166353099168728008e-02 +9.490000000000000000e+02 5.156635627818639822e-02 +9.500000000000000000e+02 5.146945336829008427e-02 +9.510000000000000000e+02 5.137282125519330306e-02 +9.520000000000000000e+02 5.127645893683676487e-02 +9.530000000000000000e+02 5.118036541588092542e-02 +9.540000000000000000e+02 5.108453969968018010e-02 +9.550000000000000000e+02 5.098898080025093121e-02 +9.560000000000000000e+02 5.089368773424415848e-02 +9.570000000000000000e+02 5.079865952292122316e-02 +9.580000000000000000e+02 5.070389519212406548e-02 +9.590000000000000000e+02 5.060939377224725477e-02 +9.600000000000000000e+02 5.051515429821440417e-02 +9.610000000000000000e+02 5.042117580944818767e-02 +9.620000000000000000e+02 5.032745734984433311e-02 +9.630000000000000000e+02 5.023399796774737081e-02 +9.640000000000000000e+02 5.014079671592251708e-02 +9.650000000000000000e+02 5.004785265153038898e-02 +9.660000000000000000e+02 4.995516483610217690e-02 +9.670000000000000000e+02 4.986273233551228451e-02 +9.680000000000000000e+02 4.977055421995346673e-02 +9.690000000000000000e+02 4.967862956391449342e-02 +9.700000000000000000e+02 4.958695744614960432e-02 +9.710000000000000000e+02 4.949553694966054435e-02 +9.720000000000000000e+02 4.940436716166575482e-02 +9.730000000000000000e+02 4.931344717357958457e-02 +9.740000000000000000e+02 4.922277608098767077e-02 +9.750000000000000000e+02 4.913235298362070291e-02 +9.760000000000000000e+02 4.904217698533338415e-02 +9.770000000000000000e+02 4.895224719407928471e-02 +9.780000000000000000e+02 4.886256272188840150e-02 +9.790000000000000000e+02 4.877312268483927071e-02 +9.800000000000000000e+02 4.868392620304506924e-02 +9.810000000000000000e+02 4.859497240061909362e-02 +9.820000000000000000e+02 4.850626040566254071e-02 +9.830000000000000000e+02 4.841778935023247771e-02 +9.840000000000000000e+02 4.832955837032919255e-02 +9.850000000000000000e+02 4.824156660586283174e-02 +9.860000000000000000e+02 4.815381320064161114e-02 +9.870000000000000000e+02 4.806629730233984849e-02 +9.880000000000000000e+02 4.797901806248633383e-02 +9.890000000000000000e+02 4.789197463643337510e-02 +9.900000000000000000e+02 4.780516618334321177e-02 +9.910000000000000000e+02 4.771859186615777515e-02 +9.920000000000000000e+02 4.763225085158701716e-02 +9.930000000000000000e+02 4.754614231007906616e-02 +9.940000000000000000e+02 4.746026541580609936e-02 +9.950000000000000000e+02 4.737461934663952240e-02 +9.960000000000000000e+02 4.728920328412990204e-02 +9.970000000000000000e+02 4.720401641348708627e-02 +9.980000000000000000e+02 4.711905792356008843e-02 +9.990000000000000000e+02 4.703432700681647177e-02 +1.000000000000000000e+03 4.694982285932213645e-02 +1.001000000000000000e+03 4.686554468072069018e-02 +1.002000000000000000e+03 4.678149167421420673e-02 +1.003000000000000000e+03 4.669766304654451861e-02 +1.004000000000000000e+03 4.661405800797140814e-02 +1.005000000000000000e+03 4.653067577225675905e-02 +1.006000000000000000e+03 4.644751555664054787e-02 +1.007000000000000000e+03 4.636457658182494695e-02 +1.008000000000000000e+03 4.628185807195582535e-02 +1.009000000000000000e+03 4.619935925460127296e-02 +1.010000000000000000e+03 4.611707936073305286e-02 +1.011000000000000000e+03 4.603501762471245290e-02 +1.012000000000000000e+03 4.595317328426416076e-02 +1.013000000000000000e+03 4.587154558046479397e-02 +1.014000000000000000e+03 4.579013375772208322e-02 +1.015000000000000000e+03 4.570893706375506876e-02 +1.016000000000000000e+03 4.562795474957732911e-02 +1.017000000000000000e+03 4.554718606948134074e-02 +1.018000000000000000e+03 4.546663028101787657e-02 +1.019000000000000000e+03 4.538628664497876969e-02 +1.020000000000000000e+03 4.530615442537974658e-02 +1.021000000000000000e+03 4.522623288944378761e-02 +1.022000000000000000e+03 4.514652130758237819e-02 +1.023000000000000000e+03 4.506701895338031255e-02 +1.024000000000000000e+03 4.498772510357602894e-02 +1.025000000000000000e+03 4.490863903804732243e-02 +1.026000000000000000e+03 4.482976003979229768e-02 +1.027000000000000000e+03 4.475108739491331922e-02 +1.028000000000000000e+03 4.467262039260247453e-02 +1.029000000000000000e+03 4.459435832512118059e-02 +1.030000000000000000e+03 4.451630048778755511e-02 +1.031000000000000000e+03 4.443844617895682109e-02 +1.032000000000000000e+03 4.436079470000889313e-02 +1.033000000000000000e+03 4.428334535532755384e-02 +1.034000000000000000e+03 4.420609745229023280e-02 +1.035000000000000000e+03 4.412905030124629480e-02 +1.036000000000000000e+03 4.405220321550581963e-02 +1.037000000000000000e+03 4.397555551132076995e-02 +1.038000000000000000e+03 4.389910650787198082e-02 +1.039000000000000000e+03 4.382285552725249944e-02 +1.040000000000000000e+03 4.374680189445174366e-02 +1.041000000000000000e+03 4.367094493734085398e-02 +1.042000000000000000e+03 4.359528398665875326e-02 +1.043000000000000000e+03 4.351981837599327302e-02 +1.044000000000000000e+03 4.344454744177256300e-02 +1.045000000000000000e+03 4.336947052324281043e-02 +1.046000000000000000e+03 4.329458696245927496e-02 +1.047000000000000000e+03 4.321989610426901773e-02 +1.048000000000000000e+03 4.314539729629629505e-02 +1.049000000000000000e+03 4.307108988892886792e-02 +1.050000000000000000e+03 4.299697323530446424e-02 +1.051000000000000000e+03 4.292304669129345940e-02 +1.052000000000000000e+03 4.284930961548822498e-02 +1.053000000000000000e+03 4.277576136918651711e-02 +1.054000000000000000e+03 4.270240131637885461e-02 +1.055000000000000000e+03 4.262922882373330891e-02 +1.056000000000000000e+03 4.255624326058293772e-02 +1.057000000000000000e+03 4.248344399891215012e-02 +1.058000000000000000e+03 4.241083041334093445e-02 +1.059000000000000000e+03 4.233840188111369363e-02 +1.060000000000000000e+03 4.226615778208513835e-02 +1.061000000000000000e+03 4.219409749870575016e-02 +1.062000000000000000e+03 4.212222041601004080e-02 +1.063000000000000000e+03 4.205052592160153646e-02 +1.064000000000000000e+03 4.197901340564186290e-02 +1.065000000000000000e+03 4.190768226083528558e-02 +1.066000000000000000e+03 4.183653188241730214e-02 +1.067000000000000000e+03 4.176556166814170828e-02 +1.068000000000000000e+03 4.169477101826717796e-02 +1.069000000000000000e+03 4.162415933554438480e-02 +1.070000000000000000e+03 4.155372602520363695e-02 +1.071000000000000000e+03 4.148347049494242877e-02 +1.072000000000000000e+03 4.141339215491256914e-02 +1.073000000000000000e+03 4.134349041770881555e-02 +1.074000000000000000e+03 4.127376469835493389e-02 +1.075000000000000000e+03 4.120421441429165943e-02 +1.076000000000000000e+03 4.113483898536566402e-02 +1.077000000000000000e+03 4.106563783381777383e-02 +1.078000000000000000e+03 4.099661038426729437e-02 +1.079000000000000000e+03 4.092775606370514102e-02 +1.080000000000000000e+03 4.085907430147769220e-02 +1.081000000000000000e+03 4.079056452927744270e-02 +1.082000000000000000e+03 4.072222618113039566e-02 +1.083000000000000000e+03 4.065405869338484246e-02 +1.084000000000000000e+03 4.058606150469744323e-02 +1.085000000000000000e+03 4.051823405602600348e-02 +1.086000000000000000e+03 4.045057579061465958e-02 +1.087000000000000000e+03 4.038308615398251977e-02 +1.088000000000000000e+03 4.031576459391483097e-02 +1.089000000000000000e+03 4.024861056044839319e-02 +1.090000000000000000e+03 4.018162350586326065e-02 +1.091000000000000000e+03 4.011480288466880151e-02 +1.092000000000000000e+03 4.004814815359631491e-02 +1.093000000000000000e+03 3.998165877158500747e-02 +1.094000000000000000e+03 3.991533419976994040e-02 +1.095000000000000000e+03 3.984917390147672128e-02 +1.096000000000000000e+03 3.978317734220530866e-02 +1.097000000000000000e+03 3.971734398962056128e-02 +1.098000000000000000e+03 3.965167331354341879e-02 +1.099000000000000000e+03 3.958616478593766919e-02 diff --git a/spectractor/extractor/extractor.py b/spectractor/extractor/extractor.py index bce64c9e6..ca3650876 100644 --- a/spectractor/extractor/extractor.py +++ b/spectractor/extractor/extractor.py @@ -63,19 +63,21 @@ def __init__(self, spectrum, amplitude_priors_method="noprior", verbose=False, p psf_poly_params_names = np.copy(spectrum.chromatic_psf.params.axis_names[length:]) psf_poly_params_bounds = spectrum.chromatic_psf.set_bounds() D2CCD = np.copy(spectrum.header['D2CCD']) - p = np.array([1, 1, 1, D2CCD, np.copy(spectrum.header['PIXSHIFT']), 0, - np.copy(spectrum.rotation_angle), 1, parameters.OBS_CAMERA_ROTATION, + p = np.array([1, 1, 0, D2CCD, np.copy(spectrum.header['PIXSHIFT']), 0, + np.copy(spectrum.rotation_angle), 1, 1, parameters.OBS_CAMERA_ROTATION, np.copy(spectrum.pressure), np.copy(spectrum.temperature), np.copy(spectrum.airmass)]) - self.psf_params_start_index = np.array([12 + len(self.psf_poly_params) * k for k in range(len(self.diffraction_orders))]) + self.psf_params_start_index = np.array([p.size + len(self.psf_poly_params) * k for k in range(len(self.diffraction_orders))]) self.saturation = spectrum.spectrogram_saturation p = np.concatenate([p] + [self.psf_poly_params] * len(self.diffraction_orders)) + # for order in self.diffraction_orders: + # p = np.concatenate([p] + [self.psf_poly_params * order]) input_labels = [f"A{order}" for order in self.diffraction_orders] - input_labels += [r"D_CCD [mm]", r"shift_x [pix]", r"shift_y [pix]", r"angle [deg]", "B", "R", "P [hPa]", "T [Celsius]", "z"] + input_labels += [r"D_CCD [mm]", r"shift_x [pix]", r"shift_y [pix]", r"angle [deg]", "B", "A_star", "R", "P [hPa]", "T [Celsius]", "z"] for order in self.diffraction_orders: input_labels += [label+f"_{order}" for label in psf_poly_params_labels] axis_names = [f"$A_{order}$" for order in self.diffraction_orders] axis_names += [r"$D_{CCD}$ [mm]", r"$\delta_{\mathrm{x}}^{(\mathrm{fit})}$ [pix]", - r"$\delta_{\mathrm{y}}^{(\mathrm{fit})}$ [pix]", r"$\alpha$ [deg]", "$B$", "R", + r"$\delta_{\mathrm{y}}^{(\mathrm{fit})}$ [pix]", r"$\alpha$ [deg]", "$B$", r"$A_{star}$", "R", r"$P_{\mathrm{atm}}$ [hPa]", r"$T_{\mathrm{atm}}$ [Celcius]", "$z$"] for order in self.diffraction_orders: axis_names += [label+rf"$\!_{order}$" for label in psf_poly_params_names] @@ -83,7 +85,7 @@ def __init__(self, spectrum, amplitude_priors_method="noprior", verbose=False, p [D2CCD - 3 * parameters.DISTANCE2CCD_ERR, D2CCD + 3 * parameters.DISTANCE2CCD_ERR], [-parameters.PIXSHIFT_PRIOR, parameters.PIXSHIFT_PRIOR], [-10 * parameters.PIXSHIFT_PRIOR, 10 * parameters.PIXSHIFT_PRIOR], - [-90, 90], [0.2, 5], [-360, 360], [300, 1100], [-100, 100], [1.001, 3]] + [-90, 90], [0.2, 5], [0.5, 2], [-360, 360], [300, 1100], [-100, 100], [1.001, 3]] bounds += list(psf_poly_params_bounds) * len(self.diffraction_orders) fixed = [False] * p.size for k, par in enumerate(input_labels): @@ -91,8 +93,15 @@ def __init__(self, spectrum, amplitude_priors_method="noprior", verbose=False, p fixed[k] = True for k, par in enumerate(input_labels): if "y_c" in par: + fixed[k] = True + p[k] = 0 + for k, par in enumerate(input_labels): + if "y_c" in par and (("y_c_0" not in par and "y_c_1" not in par) or (par[-2:] == "_2" or par[-2:] == "_3")): fixed[k] = False p[k] = 0 + elif k >= self.psf_params_start_index[0] and "y_c" not in par and "x_c" not in par and par[-2:] != f"_{spectrum.order}" and "_0_" not in par: + fixed[k] = True + p[k] = 0 params = FitParameters(p, labels=input_labels, axis_names=axis_names, fixed=fixed, bounds=bounds, truth=truth, filename=spectrum.filename) @@ -103,10 +112,12 @@ def __init__(self, spectrum, amplitude_priors_method="noprior", verbose=False, p params.fixed[params.get_index(f"A{order}")] = True if "A2" in params.labels: params.fixed[params.get_index("A2")] = (not spectrum.disperser.flat_ratio_order_2over1) and (not ("A2_T" in spectrum.header)) + if spectrum.spectrogram_starfield is None: + params.fixed[params.get_index("A_star")] = True # Astar params.fixed[params.get_index("D_CCD [mm]")] = True # D2CCD: spectrogram can not tell something on this parameter: rely on calibrate_spectrum params.fixed[params.get_index("shift_x [pix]")] = True # delta x: if False, extracted spectrum is biased compared with truth - params.fixed[params.get_index("shift_y [pix]")] = True # delta y - params.fixed[params.get_index("angle [deg]")] = True # angle + params.fixed[params.get_index("shift_y [pix]")] = False # delta y + params.fixed[params.get_index("angle [deg]")] = False # angle params.fixed[params.get_index("B")] = True # B: not needed in simulations, to check with data params.fixed[params.get_index("R")] = True # camera rot params.fixed[params.get_index("P [hPa]")] = True # pressure @@ -119,13 +130,31 @@ def __init__(self, spectrum, amplitude_priors_method="noprior", verbose=False, p # crop data to fit faster self.lambdas = self.spectrum.lambdas self.bgd_width = parameters.PIXWIDTH_BACKGROUND + parameters.PIXDIST_BACKGROUND - parameters.PIXWIDTH_SIGNAL - self.data = spectrum.spectrogram[self.bgd_width:-self.bgd_width, :] - self.err = spectrum.spectrogram_err[self.bgd_width:-self.bgd_width, :] - self.bgd = spectrum.spectrogram_bgd[self.bgd_width:-self.bgd_width, :] - self.bgd_flat = self.bgd.flatten() - self.Ny, self.Nx = self.data.shape + if spectrum.spectrogram_data.shape[0] < 2 * self.bgd_width: + # Data has been already cropped + self.bgd_width = 0 + rows = np.arange(self.bgd_width, spectrum.spectrogram_data.shape[0]-self.bgd_width) + self.Ny, self.Nx = spectrum.spectrogram_data[rows, :].shape yy, xx = np.mgrid[:self.Ny, :self.Nx] self.pixels = np.asarray([xx, yy], dtype=int) + self.data = spectrum.spectrogram_data[rows, :].flatten() + self.err = spectrum.spectrogram_err[rows, :].flatten() + self.bgd = spectrum.spectrogram_bgd[rows, :].flatten() + if spectrum.spectrogram_flat is not None: + self.flat = spectrum.spectrogram_flat[rows, :].flatten() + self.bgd *= self.flat + else: + self.flat = None + if spectrum.spectrogram_starfield is not None: + self.starfield = spectrum.spectrogram_starfield[rows, :].flatten() + if self.flat is not None: + self.starfield *= self.flat + else: + self.starfield = None + if spectrum.spectrogram_mask is not None: + self.mask = list(np.where(spectrum.spectrogram_mask[rows, :].astype(bool).ravel())[0]) + else: + self.mask = [] # adapt the ChromaticPSF table shape if self.Nx != self.spectrum.chromatic_psf.Nx: @@ -157,23 +186,13 @@ def __init__(self, spectrum, amplitude_priors_method="noprior", verbose=False, p self.psf_profile_params[order] = None self.fix_psf_cube = False - # prepare the background, data and errors - self.bgd_std = float(np.std(np.random.poisson(np.abs(self.bgd)))) - # error matrix # here image uncertainties are assumed to be uncorrelated # (which is not exactly true in rotated images) self.W = 1. / (self.err * self.err) - self.W = self.W.flatten() - - # flat data for fitworkspace - self.data = self.data.flatten() - self.bgd_flat - self.err = self.err.flatten() self.data_before_mask = np.copy(self.data) - self.W_before_mask = np.copy(self.W) - - # create mask - self.sqrtW = sparse.diags(np.sqrt(self.W), format="dia", dtype="float32") + self.W_before_mask = self.W.copy() + self.mask_before_mask = list(np.copy(self.mask)) # design matrix self.M = None @@ -199,7 +218,7 @@ def __init__(self, spectrum, amplitude_priors_method="noprior", verbose=False, p self.reg = float(spectrum.header['PSF_REG']) if self.reg < 0: self.reg = parameters.PSF_FIT_REG_PARAM - self.trace_r = self.Nx / np.min(self.fwhm_priors) # spectrophotometric uncertainty principle + self.trace_r = self.Nx / np.median(self.fwhm_priors) # spectrophotometric uncertainty principle self.my_logger.info(f"\n\tFull forward model fitting with regularisation parameter r={self.reg}.") self.Q = np.zeros((self.Nx, self.Nx), dtype="float32") self.Q_dot_A0 = np.zeros(self.Nx, dtype="float32") @@ -260,7 +279,7 @@ def set_mask(self, params=None, fwhmx_clip=3*parameters.PSF_FWHM_CLIP, fwhmy_cli self.my_logger.info("\n\tReset spectrogram mask with current parameters.") if params is None: params = self.params.values - A1, A2, A3, D2CCD, dx0, dy0, angle, B, rot, pressure, temperature, airmass, *psf_poly_params_all = params + A1, A2, A3, D2CCD, dx0, dy0, angle, B, Astar, rot, pressure, temperature, airmass, *psf_poly_params_all = params poly_params = np.array(psf_poly_params_all).reshape((len(self.diffraction_orders), -1)) lambdas = self.spectrum.compute_lambdas_in_spectrogram(D2CCD, dx0, dy0, angle, niter=5, with_adr=True, @@ -285,30 +304,48 @@ def set_mask(self, params=None, fwhmx_clip=3*parameters.PSF_FWHM_CLIP, fwhmy_cli self.psf_cubes_masked[order] = self.spectrum.chromatic_psf.convolve_psf_cube_masked(psf_cube_masked) # make rectangular mask per wavelength - self.boundaries[order], self.psf_cubes_masked[order] = self.spectrum.chromatic_psf.get_boundaries(self.psf_cubes_masked[order]) - self.psf_cube_sparse_indices[order], self.M_sparse_indices[order] = self.spectrum.chromatic_psf.get_sparse_indices(self.psf_cubes_masked[order]) + self.boundaries[order], self.psf_cubes_masked[order] = self.spectrum.chromatic_psf.set_rectangular_boundaries(self.psf_cubes_masked[order]) + if k > 0: + # spectrogram model must be accurate inside the k=0 order footprint: enlarge the next order footprints + self.boundaries[order]["ymin"] = np.zeros_like(self.boundaries[order]["ymin"]) + self.boundaries[order]["ymax"] = self.Ny * np.ones_like(self.boundaries[order]["ymax"]) + self.psf_cube_sparse_indices[order], self.M_sparse_indices[order] = self.spectrum.chromatic_psf.get_sparse_indices(self.boundaries[order]) mask = np.sum(self.psf_cubes_masked[self.diffraction_orders[0]].reshape(psf_cube_masked.shape[0], psf_cube_masked[0].size), axis=0) == 0 - self.W = np.copy(self.W_before_mask) - self.W[mask] = 0 - self.sqrtW = sparse.diags(np.sqrt(self.W), format="dia", dtype="float32") - self.mask = list(np.where(mask)[0]) + # cumulate the boolean values as int + weight_mask = np.sum(self.psf_cubes_masked[self.diffraction_orders[0]], axis=0) + # look for indices with maximum weight per column (all sheets of the psf cube have contributed) + res = np.max(weight_mask, axis=0)[np.newaxis,:] * np.ones((weight_mask.shape[0],1)) + # keep only the pixels where all psf_cube sheets have contributed per column + mask = (weight_mask != res).ravel() + self.W = self.W_before_mask.copy() + self.mask = list(np.copy(self.mask_before_mask)) + self.mask += list(np.where(mask)[0]) + self.mask = list(set(self.mask)) + self.W[self.mask] = 0 def simulate(self, *params): r""" Compute a ChromaticPSF2D model given PSF shape parameters and minimizing amplitude parameters using a spectrogram data array. - The ChromaticPSF2D model :math:`\vec{m}(\vec{x},\vec{p})` can be written as + The full forward model of the spectrogram image :math:`\vec{I}(\vec{x},\vec{p})` can be written as .. math :: - :label: chromaticpsf2d + :label: ffm - \vec{m}(\vec{x},\vec{p}) = \sum_{i=0}^{N_x} A_i \phi\left(\vec{x},\vec{p}_i\right) + \vec{I}(\vec{x},\vec{p}) = \sum_{i=0}^{N_x} A_i F_i \phi\left(\vec{x},\vec{p}_i\right) + + \bar F B b\left(\vec{x}\right) + \bar F S s\left(\vec{x}\right) - with :math:`\vec{x}` the 2D array of the pixel coordinates, :math:`\vec{A}` the amplitude parameter array - along the x axis of the spectrogram, :math:`\phi\left(\vec{x},\vec{p}_i\right)` the 2D PSF kernel whose integral - is normalised to one parametrized with the :math:`\vec{p}_i` non-linear parameter array. If the :math:`\vec{x}` - 2D array is flatten in 1D, equation :eq:`chromaticpsf2d` is + with + - :math:`\vec{x}` the 2D array of the pixel coordinates, + - :math:`\vec{A}` the amplitude parameter array along the x axis of the spectrogram, + - :math:`\phi\left(\vec{x},\vec{p}_i\right)` the 2D PSF kernel whose integral is normalised to one parametrized + with the :math:`\vec{p}_i` non-linear parameter array, + - math:`B b\left(\vec{x}\right)` the background function weighted by a scalar math:`B`, + - math:`S s\left(\vec{x}\right)` the star field function weighted by a scalar math:`S`, + - :math:`F_i` a flat cube (wavelengths indexed by :math:`i`) and \bar F the mean flat. + + If the :math:`\vec{x}` 2D array is flatten in 1D, equation :eq:`ffm` is .. math :: :label: chromaticpsf2d_matrix @@ -318,11 +355,11 @@ def simulate(self, *params): \vec{m}(\vec{x},\vec{p}) & = \mathbf{M}\left(\vec{x},\vec{p}\right) \mathbf{A} \\ \mathbf{M}\left(\vec{x},\vec{p}\right) & = \left(\begin{array}{cccc} - \phi\left(\vec{x}_1,\vec{p}_1\right) & \phi\left(\vec{x}_2,\vec{p}_1\right) & ... - & \phi\left(\vec{x}_{N_x},\vec{p}_1\right) \\ + F_1\phi\left(\vec{x}_1,\vec{p}_1\right) & F_2\phi\left(\vec{x}_2,\vec{p}_1\right) & ... + & F_{N_x}\phi\left(\vec{x}_{N_x},\vec{p}_1\right) \\ ... & ... & ... & ...\\ - \phi\left(\vec{x}_1,\vec{p}_{N_x}\right) & \phi\left(\vec{x}_2,\vec{p}_{N_x}\right) & ... - & \phi\left(\vec{x}_{N_x},\vec{p}_{N_x}\right) \\ + F_1\phi\left(\vec{x}_1,\vec{p}_{N_x}\right) & F_2\phi\left(\vec{x}_2,\vec{p}_{N_x}\right) & ... + & F_{N_x}\phi\left(\vec{x}_{N_x},\vec{p}_{N_x}\right) \\ \end{array}\right) \end{align} @@ -330,26 +367,26 @@ def simulate(self, *params): with :math:`\mathbf{M}` the design matrix. The goal of this function is to perform a minimisation of the amplitude vector :math:`\mathbf{A}` given - a set of non-linear parameters :math:`\mathbf{p}` and a spectrogram data array :math:`mathbf{y}` modelise as + a set of non-linear parameters :math:`\mathbf{p}` and a spectrogram data array :math:`\mathbf{D}` modelised as - .. math:: \mathbf{y} = \mathbf{m}(\vec{x},\vec{p}) + \vec{\epsilon} + .. math:: \mathbf{D} = \mathbf{m}(\vec{x},\vec{p}) + \bar F B b\left(\vec{x}\right) + \bar F S s\left(\vec{x}\right) + \vec{\epsilon} with :math:`\vec{\epsilon}` a random noise vector. The :math:`\chi^2` function to minimise is .. math:: - :label: chromaticspsf2d_chi2 + :label: ffm_chi2 - \chi^2(\mathbf{A})= \left(\mathbf{y} - \mathbf{M}\left(\vec{x},\vec{p}\right) \mathbf{A}\right)^T \mathbf{W} - \left(\mathbf{y} - \mathbf{M}\left(\vec{x},\vec{p}\right) \mathbf{A} \right) + \chi^2(\mathbf{A})= \left(\mathbf{D} - \bar F B b\left(\vec{x}\right) - \bar F S s\left(\vec{x}\right) - \mathbf{M}\left(\vec{x},\vec{p}\right) \mathbf{A}\right)^T \mathbf{W} + \left(\mathbf{D} - \bar F B b\left(\vec{x}\right) - \bar F S s\left(\vec{x}\right) -\mathbf{M}\left(\vec{x},\vec{p}\right) \mathbf{A} \right) with :math:`\mathbf{W}` the weight matrix, inverse of the covariance matrix. In our case this matrix is diagonal - as the pixels are considered all independent. The minimum of equation :eq:`chromaticspsf2d_chi2` is reached for + as the pixels are considered all independent. The minimum of equation :eq:`ffm_chi2` is reached for a set of amplitude parameters :math:`\hat{\mathbf{A}}` given by .. math:: - \hat{\mathbf{A}} = (\mathbf{M}^T \mathbf{W} \mathbf{M})^{-1} \mathbf{M}^T \mathbf{W} \mathbf{y} + \hat{\mathbf{A}} = (\mathbf{M}^T \mathbf{W} \mathbf{M})^{-1} \mathbf{M}^T \mathbf{W}\left( \mathbf{D} - \bar F B b\left(\vec{x}\right) - \bar F S s\left(\vec{x}\right) \right) The error matrix on the :math:`\hat{\mathbf{A}}` coefficient is simply :math:`(\mathbf{M}^T \mathbf{W} \mathbf{M})^{-1}`. @@ -369,6 +406,7 @@ def simulate(self, *params): Load data: >>> spec = Spectrum("./tests/data/sim_20170530_134_spectrum.fits") + >>> spec.plot_spectrogram() Simulate the data with fixed amplitude priors: @@ -396,19 +434,23 @@ def simulate(self, *params): # linear regression for the amplitude parameters # prepare the vectors self.params.values = np.asarray(params) - A1, A2, A3, D2CCD, dx0, dy0, angle, B, rot, pressure, temperature, airmass, *poly_params_all = params + A1, A2, A3, D2CCD, dx0, dy0, angle, B, Astar, rot, pressure, temperature, airmass, *poly_params_all = params poly_params = np.array(poly_params_all).reshape((len(self.diffraction_orders), -1)) self.spectrum.adr_params[2] = temperature self.spectrum.adr_params[3] = pressure self.spectrum.adr_params[-1] = airmass parameters.OBS_CAMERA_ROTATION = rot - W_dot_data = (self.W * (self.data + (1 - B) * self.bgd_flat)).astype("float32") + R = self.data - B * self.bgd + if self.starfield is not None: + R -= self.starfield + W_dot_data = (self.W * R).astype("float32") # Evaluate ADR and compute wavelength arrays self.lambdas = self.spectrum.compute_lambdas_in_spectrogram(D2CCD, dx0, dy0, angle, niter=5, with_adr=True, order=self.diffraction_orders[0]) M = None + # distance = None for k, order in enumerate(self.diffraction_orders): if self.tr[k] is None or self.params[f"A{order}"] == 0: # diffraction order undefined self.psf_profile_params[order] = None @@ -429,34 +471,40 @@ def simulate(self, *params): self.psf_profile_params[order][:, 1] = dispersion_law.real + self.spectrum.spectrogram_x0 self.psf_profile_params[order][:, 2] += dispersion_law.imag - self.bgd_width - # Matrix filling - # Older piece of code, using full matrices (non sparse). Keep here for temporary archive. - # psf_cube_order = self.spectrum.chromatic_psf.build_psf_cube(self.pixels, profile_params[-1], fwhmx_clip=3 * parameters.PSF_FWHM_CLIP, fwhmy_clip=parameters.PSF_FWHM_CLIP, dtype="float32", mask=self.psf_cubes_masked[order], boundaries=self.boundaries[order]) - # if self.sparse_indices is None: - # self.sparse_indices = np.concatenate([np.where(self.psf_cube_masked[k].ravel() > 0)[0] for k in range(len(profile_params))]) - # if psf_cube is None: - # psf_cube = psf_cube_order + # if k == 0: + # distance = np.abs(dispersion_law) # else: - # psf_cube += psf_cube_order + # distance_order = np.abs(dispersion_law) + # for p in range(3, self.psf_profile_params[order].shape[1]): + # self.psf_profile_params[order][:, p] = np.copy(self.psf_profile_params[self.spectrum.order][:, p]) + # self.psf_profile_params[order][:, p] = interpolate.interp1d(distance, self.psf_profile_params[order][:, p], + # kind="cubic", fill_value="extrapolate")(distance_order) + + # Matrix filling M_order = self.spectrum.chromatic_psf.build_sparse_M(self.pixels, self.psf_profile_params[order], - dtype="float32", M_sparse_indices=self.M_sparse_indices[order], boundaries=self.boundaries[order]) + dtype="float32", M_sparse_indices=self.M_sparse_indices[order], + boundaries=self.boundaries[order]) if M is None: M = M_order else: M += M_order - # M = psf_cube.reshape(len(profile_params[0]), self.pixels[0].size).T # flattening - # if self.sparse_indices is None: - # self.sparse_indices = np.where(M > 0) - # M = sparse.csc_matrix((M[self.sparse_indices].ravel(), self.sparse_indices), shape=M.shape, dtype="float32") + if self.flat is not None: + # multiply each M matrix columns by the flat array (see the docstring) + # TODO: if flat array is a cube flat, needs to multiply directly in build_sparse_M + dia = sparse.dia_matrix(([self.flat], [0]), shape=(self.flat.size, self.flat.size)) + M = (dia @ M).tocsc() + + # Algebra to compute amplitude parameters if self.amplitude_priors_method != "fixed": - M_dot_W = M.T @ self.sqrtW + M_dot_W = M.T @ sparse.diags(np.sqrt(self.W), format="dia", dtype="float32") if sparse_dot_mkl is None: M_dot_W_dot_M = M_dot_W @ M_dot_W.T else: tri = sparse_dot_mkl.gram_matrix_mkl(M_dot_W, transpose=True) - dia = sparse.csr_matrix((tri.diagonal(), (np.arange(tri.shape[0]), np.arange(tri.shape[0]))), shape=tri.shape, dtype="float32") + dia = sparse.csr_matrix((tri.diagonal(), (np.arange(tri.shape[0]), np.arange(tri.shape[0]))), + shape=tri.shape, dtype="float32") M_dot_W_dot_M = (tri + tri.T - dia).toarray() if self.amplitude_priors_method != "spectrum": if self.amplitude_priors_method == "keep": @@ -512,6 +560,9 @@ def simulate(self, *params): # Compute the model self.model = M @ amplitude_params + self.model += B * self.bgd + if self.starfield is not None: + self.model += Astar * self.starfield self.model_err = np.zeros_like(self.model) return self.pixels, self.model, self.model_err @@ -521,7 +572,6 @@ def jacobian(self, params, epsilon, model_input=None): lambdas, model, model_err = model_input else: lambdas, model, model_err = self.simulate(*params) - model = model.flatten() J = np.zeros((params.size, model.size)) method = copy.copy(self.amplitude_priors_method) self.amplitude_priors_method = "keep" @@ -535,7 +585,7 @@ def jacobian(self, params, epsilon, model_input=None): epsilon[ip] = - epsilon[ip] tmp_p[ip] += epsilon[ip] tmp_lambdas, tmp_model, tmp_model_err = self.simulate(*tmp_p) - J[ip] = (tmp_model.flatten() - model) / epsilon[ip] + J[ip] = (tmp_model - model) / epsilon[ip] self.amplitude_priors_method = method for k, order in enumerate(self.diffraction_orders): if self.psf_profile_params[order] is None: @@ -591,7 +641,7 @@ def amplitude_derivatives(self): """ # compute matrices without derivatives WM = sparse.dia_matrix((self.W, 0), shape=(self.W.size, self.W.size), dtype="float32") @ self.M - WD = (self.W * (self.data + (1 - self.params.values[self.params.get_index("B")]) * self.bgd_flat)).astype("float32") + WD = (self.W * (self.data + (1 - self.params.values[self.params.get_index("B")]) * self.bgd)).astype("float32") MWD = self.M.T @ WD if self.amplitude_priors_method == "spectrum": MWD += np.float32(self.reg) * self.Q_dot_A0 @@ -642,10 +692,10 @@ def plot_spectrogram_comparison_simple(self, ax, title='', extent=None, dispersi lambdas = self.spectrum.lambdas sub = np.where((lambdas > parameters.LAMBDA_MIN) & (lambdas < parameters.LAMBDA_MAX))[0] - sub = np.where(sub < self.spectrum.spectrogram.shape[1])[0] - data = (data + self.bgd_flat).reshape((self.Ny, self.Nx)) + sub = np.where(sub < self.spectrum.spectrogram_data.shape[1])[0] + data = data.reshape((self.Ny, self.Nx)) err = self.err.reshape((self.Ny, self.Nx)) - model = (self.model + self.params["B"] * self.bgd_flat).reshape((self.Ny, self.Nx)) + model = self.model.reshape((self.Ny, self.Nx)) if extent is not None: sub = np.where((lambdas > extent[0]) & (lambdas < extent[1]))[0] if len(sub) > 0: @@ -768,11 +818,18 @@ def adjust_spectrogram_position_parameters(self): epsilon[epsilon == 0] = 1e-4 fixed_default = np.copy(self.params.fixed) self.params.fixed = [True] * len(self.params.values) + strategy = copy.copy(self.amplitude_priors_method) + self.amplitude_priors_method = "fixed" + # let A1 free to help finding the spectrogram trace, with amplitude fixed to prior + self.params.fixed[self.params.get_index(r"A1")] = False # A1 self.params.fixed[self.params.get_index(r"shift_y [pix]")] = False # shift y self.params.fixed[self.params.get_index(r"angle [deg]")] = False # angle run_minimisation(self, "newton", epsilon, xtol=1e-2, ftol=0.01, with_line_search=False) # 1000 / self.data.size) self.params.fixed = fixed_default self.set_mask(params=self.params.values, fwhmx_clip=3 * parameters.PSF_FWHM_CLIP, fwhmy_clip=parameters.PSF_FWHM_CLIP) + # refix A1=1 and let amplitude parameters free + self.amplitude_priors_method = strategy + self.params.values[self.params.get_index(r"A1")] = 1 def run_ffm_minimisation(w, method="newton", niter=2): @@ -797,7 +854,7 @@ def run_ffm_minimisation(w, method="newton", niter=2): >>> spec = Spectrum("./tests/data/sim_20170530_134_spectrum.fits") >>> parameters.VERBOSE = True - >>> w = FullForwardModelFitWorkspace(spec, verbose=True, plot=True, live_fit=True, amplitude_priors_method="spectrum") + >>> w = FullForwardModelFitWorkspace(spec, verbose=True, plot=True, live_fit=False, amplitude_priors_method="spectrum") >>> spec = run_ffm_minimisation(w, method="newton") # doctest: +ELLIPSIS >>> if 'LBDAS_T' in spec.header: plot_comparison_truth(spec, w) @@ -883,23 +940,6 @@ def run_ffm_minimisation(w, method="newton", niter=2): if parameters.DEBUG and parameters.DISPLAY: w.plot_fit() - # recompute angle and dy0 if fixed while y_c parameters are free - # if w.fixed[3] and w.fixed[4] and not np.any([w.fixed[k] for k, par in enumerate(w.input_labels) if "y_c" in par]): - # pval_leg = [w.p[k] for k, par in enumerate(w.input_labels) if "y_c" in par][ - # :w.spectrum.chromatic_psf.degrees["y_c"] + 1] - # pval_poly = np.polynomial.legendre.leg2poly(pval_leg) - # new_dy0, new_angle = w.p[2], w.p[4] - # from numpy.polynomial import Polynomial as P - # p = P(pval_poly) - # pX = P([0, 0.5 * (w.spectrum.spectrogram_Nx)]) - # pfinal = p(pX) - # pval_poly = pfinal.coef - # for k in range(pval_poly.size): - # if k == 0: - # new_dy0 += pval_poly[k] - # if k == 1: - # new_angle += np.arctan(pval_poly[k]) * 180 / np.pi - w.spectrum.lambdas = np.copy(w.lambdas) w.spectrum.chromatic_psf.table['lambdas'] = np.copy(w.lambdas) w.spectrum.data = np.copy(w.amplitude_params) @@ -939,14 +979,13 @@ def run_ffm_minimisation(w, method="newton", niter=2): parameters.SAVE = False # Propagate parameters - A1, A2, A3, D2CCD, dx0, dy0, angle, B, rot, pressure, temperature, airmass, *poly_params_all = w.params.values - w.spectrum.rotation_angle = angle - w.spectrum.spectrogram_bgd *= B - w.spectrum.spectrogram_bgd_rms *= B - w.spectrum.spectrogram_x0 += dx0 - w.spectrum.spectrogram_y0 += dy0 - w.spectrum.x0[0] += dx0 - w.spectrum.x0[1] += dy0 + w.spectrum.rotation_angle = w.params.values[w.params.get_index("angle [deg]")] + w.spectrum.spectrogram_bgd *= w.params.values[w.params.get_index("B")] + w.spectrum.spectrogram_bgd_rms *= w.params.values[w.params.get_index("B")] + w.spectrum.spectrogram_x0 += w.params.values[w.params.get_index("shift_x [pix]")] + w.spectrum.spectrogram_y0 += w.params.values[w.params.get_index("shift_y [pix]")] + w.spectrum.x0[0] += w.params.values[w.params.get_index("shift_x [pix]")] + w.spectrum.x0[1] += w.params.values[w.params.get_index("shift_y [pix]")] w.spectrum.header["TARGETX"] = w.spectrum.x0[0] w.spectrum.header["TARGETY"] = w.spectrum.x0[1] w.spectrum.header['MEANFWHM'] = np.mean(np.array(w.spectrum.chromatic_psf.table['fwhm'])) @@ -1037,7 +1076,7 @@ def SpectractorRun(image, output_directory, guess=None): spectrum: Spectrum The extracted spectrum object. w: FullForwardModelFitWorkspace - The FFM wrokspace. + The FFM workspace. Examples -------- @@ -1080,11 +1119,11 @@ def SpectractorRun(image, output_directory, guess=None): my_logger.info(f"\n\tNo guess position of order 0 has been given. Assuming the spectrum to extract comes " f"from the brightest object, guess position is set as {image.target_guess}.") if parameters.DEBUG: - image.plot_image(scale='symlog', title="before rebinning", target_pixcoords=image.target_guess, cmap='gray', vmax=1e3) + image.plot_image(scale='symlog', title="before rebinning", target_pixcoords=image.target_guess, vmax=1e3) # Use fast mode if parameters.CCD_REBIN > 1: - my_logger.info('\n\t ======================= REBIN =============================') + my_logger.info('\n\t ======================= REBIN =============================') image.rebin() if parameters.DEBUG: image.plot_image(scale='symlog', title="after rebinning ", target_pixcoords=image.target_guess) @@ -1095,26 +1134,29 @@ def SpectractorRun(image, output_directory, guess=None): output_filename = output_filename.replace('.fits', '_spectrum.fits') output_filename = output_filename.replace('.fz', '_spectrum.fits') output_filename = os.path.join(output_directory, output_filename) + # Find the exact target position in the raw cut image: several methods my_logger.info(f'\n\tSearch for the target in the image with guess={image.target_guess}...') find_target(image, image.target_guess, widths=(parameters.XWINDOW, parameters.YWINDOW)) + # Simulate star field + if parameters.SPECTRACTOR_SIMULATE_STARFIELD: + image.starfield = image.simulate_starfield_with_gaia() # Rotate the image turn_image(image) + # Find the exact target position in the rotated image: several methods my_logger.info('\n\tSearch for the target in the rotated image...') - find_target(image, image.target_guess, rotated=True, widths=(parameters.XWINDOW_ROT, parameters.YWINDOW_ROT)) # Create Spectrum object spectrum = Spectrum(image=image, order=parameters.SPEC_ORDER) - # First 1D spectrum extraction and background extraction + # First 1D spectrum extraction and background extraction my_logger.info('\n\t ======================== PSF1D Extraction ====================================') w_psf1d, bgd_model_func = extract_spectrum_from_image(image, spectrum, signal_width=parameters.PIXWIDTH_SIGNAL, ws=(parameters.PIXDIST_BACKGROUND, parameters.PIXDIST_BACKGROUND - + parameters.PIXWIDTH_BACKGROUND), - right_edge=image.data.shape[1]) + + parameters.PIXWIDTH_BACKGROUND)) # PSF2D deconvolution if parameters.SPECTRACTOR_DECONVOLUTION_PSF2D: @@ -1131,14 +1173,15 @@ def SpectractorRun(image, output_directory, guess=None): spectrum.err_next_order = np.zeros_like(spectrum.lambdas) # Full forward model extraction: add transverse ADR and order 2 subtraction + w = None if parameters.SPECTRACTOR_DECONVOLUTION_FFM: - my_logger.info('\n\t ======================= FFM DECONVOLUTION =============================') + my_logger.info('\n\t ======================= FFM DECONVOLUTION =============================') w = FullForwardModelFitWorkspace(spectrum, verbose=parameters.VERBOSE, plot=True, live_fit=False, amplitude_priors_method="spectrum") spectrum = run_ffm_minimisation(w, method="newton", niter=2) # Save the spectrum - my_logger.info('\n\t ======================= SAVE SPECTRUM =============================') + my_logger.info('\n\t ======================= SAVE SPECTRUM =============================') spectrum.save_spectrum(output_filename, overwrite=True) spectrum.lines.table = spectrum.lines.build_detected_line_table(amplitude_units=spectrum.units) @@ -1205,7 +1248,7 @@ def Spectractor(file_name, output_directory, target_label='', guess=None, disper return spectrum -def extract_spectrum_from_image(image, spectrum, signal_width=10, ws=(20, 30), right_edge=parameters.CCD_IMSIZE): +def extract_spectrum_from_image(image, spectrum, signal_width=10, ws=(20, 30)): """Extract the 1D spectrum from the image. Method : remove a uniform background estimated from the rectangular lateral bands @@ -1231,8 +1274,6 @@ def extract_spectrum_from_image(image, spectrum, signal_width=10, ws=(20, 30), r Half width of central region where the spectrum is extracted and summed (default: 10) ws: list up/down region extension where the sky background is estimated with format [int, int] (default: [20,30]) - right_edge: int - Right-hand pixel position above which no pixel should be used (default: parameters.CCD_IMSIZE) """ my_logger = set_logger(__name__) @@ -1240,17 +1281,17 @@ def extract_spectrum_from_image(image, spectrum, signal_width=10, ws=(20, 30), r ws = [signal_width + 20, signal_width + 30] my_logger.info('\n\t ======================= extract_spectrum_from_image =============================') - my_logger.info( - f'\n\tExtracting spectrum from image: spectrum with width 2*{signal_width:.0f} pixels ' - f'and background from {ws[0]:.0f} to {ws[1]:.0f} pixels') + my_logger.info(f'\n\tExtracting spectrum from image: spectrum with width 2*{signal_width:.0f} pixels ' + f'and background from {ws[0]:.0f} to {ws[1]:.0f} pixels') # Make a data copy - data = np.copy(image.data_rotated)#[:, 0:right_edge] - err = np.copy(image.stat_errors_rotated)#[:, 0:right_edge] + data = np.copy(image.data_rotated) + err = np.copy(image.err_rotated) # Lateral bands to remove sky background Ny, Nx = data.shape y0 = int(image.target_pixcoords_rotated[1]) + right_edge = image.data_rotated.shape[1] ymax = min(Ny, y0 + ws[1]) ymin = max(0, y0 - ws[1]) @@ -1273,6 +1314,16 @@ def extract_spectrum_from_image(image, spectrum, signal_width=10, ws=(20, 30), r # Create spectrogram data = data[ymin:ymax, xmin:xmax] err = err[ymin:ymax, xmin:xmax] + + # clean the data: this is truly a backward spectrum extraction to feed correctly the forward model + # if available, apply flats + if image.flat_rotated is not None: + data /= image.flat_rotated[ymin:ymax, xmin:xmax] + if image.mask_rotated is not None: + mask = image.mask_rotated[ymin:ymax, xmin:xmax] + else: + mask = None + Ny, Nx = data.shape my_logger.info(f'\n\tExtract spectrogram: crop rotated image [{xmin}:{xmax},{ymin}:{ymax}] (size ({Nx}, {Ny}))') @@ -1285,7 +1336,6 @@ def bgd_model_func(x, y): return np.zeros((y.size, x.size)) if parameters.SPECTRACTOR_BACKGROUND_SUBTRACTION: bgd_model_func, bgd_res, bgd_rms = extract_spectrogram_background_sextractor(data, err, ws=ws, mask_signal_region=True) - # while np.nanmean(bgd_res)/np.nanstd(bgd_res) < -0.2 and parameters.PIXWIDTH_BOXSIZE >= 5: while (np.abs(np.nanmean(bgd_res)) > 0.5 or np.nanstd(bgd_res) > 1.3) and parameters.PIXWIDTH_BOXSIZE > 5: parameters.PIXWIDTH_BOXSIZE = max(5, parameters.PIXWIDTH_BOXSIZE // 2) my_logger.debug(f"\n\tPull distribution of background residuals differs too much from mean=0 and std=1. " @@ -1300,7 +1350,6 @@ def bgd_model_func(x, y): # Fit the transverse profile my_logger.info('\n\t ======================= Fit the transverse profile =============================') - my_logger.info(f'\n\tStart PSF1D transverse fit...') psf = load_PSF(psf_type=parameters.PSF_TYPE, target=image.target, clip=False) s = ChromaticPSF(psf, Nx=Nx, Ny=Ny, x0=target_pixcoords_spectrogram[0], y0=target_pixcoords_spectrogram[1], @@ -1309,6 +1358,13 @@ def bgd_model_func(x, y): debug = copy.copy(parameters.DEBUG) parameters.VERBOSE = False parameters.DEBUG = False + + # clean the data: this is truly a backward spectrum extraction to feed correctly the forward model + # if available, subtract starfield before 1D spectrum estimate + # it is important to have a clean 1D spectrum as it is used as a prior for regularisation + if image.starfield_rotated is not None: + data -= image.starfield_rotated[ymin:ymax, xmin:xmax] + s.fit_transverse_PSF1D_profile(data, err, signal_width, ws, pixel_step=parameters.PSF_PIXEL_STEP_TRANSVERSE_FIT, sigma_clip=5, bgd_model_func=bgd_model_func, saturation=image.saturation, live_fit=False) @@ -1330,7 +1386,7 @@ def bgd_model_func(x, y): my_logger.info('\n\t ======================= ChromaticPSF1D polynomial fit =============================') my_logger.info(f'\n\tStart ChromaticPSF polynomial fit with ' f'mode={mode} and amplitude_priors_method={method}...') - w = s.fit_chromatic_psf(data, bgd_model_func=bgd_model_func, data_errors=err, + w = s.fit_chromatic_psf(data, bgd_model_func=bgd_model_func, data_errors=err, mask=mask, amplitude_priors_method=method, mode=mode, verbose=parameters.VERBOSE, analytical=True) Dx_rot = spectrum.pixels.astype(float) - image.target_pixcoords_rotated[0] @@ -1356,9 +1412,7 @@ def bgd_model_func(x, y): spectrum.chromatic_psf = s # Extract the spectrogram edges - data = np.copy(image.data)[:, 0:right_edge] - err = np.copy(image.stat_errors)[:, 0:right_edge] - Ny, Nx = data.shape + Ny, Nx = image.data.shape x0 = int(image.target_pixcoords[0]) y0 = int(image.target_pixcoords[1]) ymax = min(Ny, y0 + int(s.table['Dy_disp_axis'].max()) + ws[1] + 1) # +1 to include edges @@ -1368,7 +1422,7 @@ def bgd_model_func(x, y): lambda_min_index = int(np.argmin(np.abs(lambdas[::np.sign(spectrum.order)] - parameters.LAMBDA_MIN))) lambda_max_index = int(np.argmin(np.abs(lambdas[::np.sign(spectrum.order)] - parameters.LAMBDA_MAX))) xmin = max(0, int(s.table['Dx'][lambda_min_index] + x0)) - xmax = min(right_edge, int(s.table['Dx'][lambda_max_index] + x0) + 1) # +1 to include edges + xmax = min(Nx, int(s.table['Dx'][lambda_max_index] + x0) + 1) # +1 to include edges # Position of the order 0 in the spectrogram coordinates target_pixcoords_spectrogram = [image.target_pixcoords[0] - xmin, image.target_pixcoords[1] - ymin] s.y0 = target_pixcoords_spectrogram[1] @@ -1381,28 +1435,43 @@ def bgd_model_func(x, y): f"\n{s.table[['amplitude', 'x_c', 'y_c', 'Dx', 'Dy', 'Dy_disp_axis']]}") # Create spectrogram - data = data[ymin:ymax, xmin:xmax] - err = err[ymin:ymax, xmin:xmax] - Ny, Nx = data.shape + spectrum.spectrogram_data = np.copy(image.data[ymin:ymax, xmin:xmax]) + spectrum.spectrogram_err = np.copy(image.err[ymin:ymax, xmin:xmax]) + if image.starfield is not None: + spectrum.spectrogram_starfield = np.copy(image.starfield[ymin:ymax, xmin:xmax]) + else: + spectrum.spectrogram_starfield = None # np.zeros_like(spectrum.spectrogram_data) + if image.flat is not None: + spectrum.spectrogram_flat = np.copy(image.flat[ymin:ymax, xmin:xmax]) + else: + spectrum.spectrogram_flat = None # np.ones_like(spectrum.spectrogram_data) + if image.mask is not None: + spectrum.spectrogram_mask = np.copy(image.mask[ymin:ymax, xmin:xmax]) + else: + spectrum.spectrogram_mask = None # np.ones_like(spectrum.spectrogram_data) + + Ny, Nx = spectrum.spectrogram_data.shape my_logger.info(f'\n\tExtract spectrogram: crop raw image [{xmin}:{xmax},{ymin}:{ymax}] (size ({Nx}, {Ny}))') - # Extract the non rotated background + # Extract the non-rotated background my_logger.info('\n\t ======================= Extract the non rotated background =============================') if parameters.SPECTRACTOR_BACKGROUND_SUBTRACTION: - bgd_model_func, bgd_res, bgd_rms = extract_spectrogram_background_sextractor(data, err, ws=ws, Dy_disp_axis=s.table['y_c']) + data = np.copy(spectrum.spectrogram_data) + if spectrum.spectrogram_flat is not None: + data /= spectrum.spectrogram_flat + bgd_model_func, bgd_res, bgd_rms = extract_spectrogram_background_sextractor(data, spectrum.spectrogram_err, + ws=ws, Dy_disp_axis=s.table['y_c']) bgd = bgd_model_func(np.arange(Nx), np.arange(Ny)) my_logger.info(f"\n\tBackground statistics: mean={np.nanmean(bgd):.3f} {image.units}, " f"RMS={np.nanmean(bgd_rms):.3f} {image.units}.") # Propagate background uncertainties - err = np.sqrt(err * err + bgd_rms * bgd_rms) + spectrum.spectrogram_err = np.sqrt(spectrum.spectrogram_err * spectrum.spectrogram_err + bgd_rms * bgd_rms) spectrum.spectrogram_bgd = bgd spectrum.spectrogram_bgd_rms = bgd_rms # First guess for lambdas - my_logger.info('\n\t ======================= first guess for lambdas =============================') - first_guess_lambdas = image.disperser.grating_pixel_to_lambda(s.get_algebraic_distance_along_dispersion_axis(), x0=image.target_pixcoords, order=spectrum.order) s.table['lambdas'] = first_guess_lambdas @@ -1413,8 +1482,6 @@ def bgd_model_func(x, y): f'\n\tNew target position in spectrogram frame: {target_pixcoords_spectrogram}') # Save results - spectrum.spectrogram = data - spectrum.spectrogram_err = err spectrum.spectrogram_x0 = target_pixcoords_spectrogram[0] spectrum.spectrogram_y0 = target_pixcoords_spectrogram[1] spectrum.spectrogram_xmin = xmin @@ -1449,7 +1516,8 @@ def bgd_model_func(x, y): gs_kw = dict(width_ratios=[3, 0.08], height_ratios=[1, 1]) fig, ax = plt.subplots(2, 2, sharex='none', figsize=(16, 6), gridspec_kw=gs_kw) xx = np.arange(s.table['Dx'].size) - plot_image_simple(ax[1, 0], data=data, scale="symlog", title='', units=image.units, aspect='auto', cax=ax[1, 1]) + plot_image_simple(ax[1, 0], data=spectrum.spectrogram_data, scale="symlog", title='', mask=spectrum.spectrogram_mask, + units=image.units, aspect='auto', cax=ax[1, 1]) ax[1, 0].plot(xx, target_pixcoords_spectrogram[1] + s.table['Dy_disp_axis'], label='Dispersion axis', color="r") ax[1, 0].scatter(xx, target_pixcoords_spectrogram[1] + s.table['Dy'], c=s.table['lambdas'], edgecolors='None', cmap=from_lambda_to_colormap(s.table['lambdas']), @@ -1474,6 +1542,8 @@ def bgd_model_func(x, y): plt.show() if parameters.LSST_SAVEFIGPATH: fig.savefig(os.path.join(parameters.LSST_SAVEFIGPATH, 'intermediate_spectrum.pdf')) + if parameters.DEBUG: + spectrum.plot_spectrum() return w, bgd_model_func @@ -1493,7 +1563,7 @@ def run_spectrogram_deconvolution_psf2d(spectrum, bgd_model_func): """ my_logger = set_logger(__name__) s = spectrum.chromatic_psf - Ny, Nx = spectrum.spectrogram.shape + Ny, Nx = spectrum.spectrogram_data.shape # build 1D priors Dx_rot = np.copy(s.table['Dx']) @@ -1527,11 +1597,20 @@ def run_spectrogram_deconvolution_psf2d(spectrum, bgd_model_func): f"\n{s.table[['amplitude', 'x_c', 'y_c', 'Dx', 'Dy', 'Dy_disp_axis']]}") my_logger.info(f'\n\tStart ChromaticPSF polynomial fit with ' f'mode={mode} and amplitude_priors_method={method}...') - data = spectrum.spectrogram - err = spectrum.spectrogram_err + data = np.copy(spectrum.spectrogram_data) + err = np.copy(spectrum.spectrogram_err) + + # clean the data: this is truly a backward spectrum extraction to feed correctly the forward model + # if available, apply flats + if spectrum.spectrogram_flat is not None: + data /= spectrum.spectrogram_flat + # if available, subtract starfield before 1D spectrum estimate + # (important as it is used as a prior for regularisation) + if spectrum.spectrogram_starfield is not None: + data -= spectrum.spectrogram_starfield my_logger.info('\n\t ======================= ChromaticPSF2D polynomial fit =============================') - w = s.fit_chromatic_psf(data, bgd_model_func=bgd_model_func, data_errors=err, live_fit=False, + w = s.fit_chromatic_psf(data, bgd_model_func=bgd_model_func, data_errors=err, live_fit=False, mask=spectrum.spectrogram_mask, amplitude_priors_method=method, mode=mode, verbose=parameters.VERBOSE, analytical=True) # save results @@ -1576,11 +1655,11 @@ def run_spectrogram_deconvolution_psf2d(spectrum, bgd_model_func): def plot_comparison_truth(spectrum, w): # pragma: no cover s = spectrum.chromatic_psf - lambdas_truth = np.fromstring(spectrum.header['LBDAS_T'][1:-1], sep=' ') - psf_poly_truth = np.fromstring(spectrum.header['PSF_P_T'][1:-1], sep=' ', dtype=float) + lambdas_truth = np.fromstring(spectrum.header['LBDAS_T'][1:-1], sep=',') + psf_poly_truth = np.fromstring(spectrum.header['PSF_P_T'][1:-1], sep=',', dtype=float) deg_truth = int(spectrum.header["PSF_DEG"]) psf_poly_truth[-1] = spectrum.spectrogram_saturation - amplitude_truth = np.fromstring(spectrum.header['AMPLIS_T'][1:-1], sep=' ', dtype=float) + amplitude_truth = np.fromstring(spectrum.header['AMPLIS_T'][1:-1], sep=',', dtype=float) amplitude_truth *= parameters.FLAM_TO_ADURATE * lambdas_truth * np.gradient(lambdas_truth) * parameters.CCD_REBIN s0 = ChromaticPSF(s.psf, lambdas_truth.size, s.Ny, deg=deg_truth, saturation=spectrum.spectrogram_saturation) diff --git a/spectractor/extractor/images.py b/spectractor/extractor/images.py index 896482107..e2c7ee966 100644 --- a/spectractor/extractor/images.py +++ b/spectractor/extractor/images.py @@ -34,14 +34,26 @@ class Image(object): Units of the image. data: array Image 2D array in self.units units. - stat_errors: array + err: array Image 2D uncertainty array in self.units units. target_pixcoords: array Target position [x,y] in the image in pixels. data_rotated: array Rotated image 2D array in self.units units. - stat_errors_rotated: array + err_rotated: array Rotated image 2D uncertainty array in self.units units. + flat: array + Flat 2D array without units and median of 1. + starfield: array + Star field simulation, no units needed but better in ADU/s. + mask: array + Boolean array to mask defects. + flat_rotated: array + Rotated flat 2D array without units and median of 1. + starfield_rotated: array + Rotated star field simulation, no units needed but better in ADU/s. + mask_rotated: array + Rotated boolean array to mask defects. target_pixcoords_rotated: array Target position [x,y] in the rotated image in pixels. date_obs: str @@ -116,7 +128,7 @@ def __init__(self, file_name, *, target_label="", disperser_label="", :hide: >>> assert im.data is not None and np.mean(im.data) > 0 - >>> assert im.stat_errors is not None and np.mean(im.stat_errors) > 0 + >>> assert im.err is not None and np.mean(im.err) > 0 >>> assert im.header is not None >>> assert im.gain is not None and np.mean(im.gain) > 0 @@ -140,8 +152,8 @@ def __init__(self, file_name, *, target_label="", disperser_label="", self.data_rotated = None self.gain = None # in e-/ADU self.read_out_noise = None - self.stat_errors = None - self.stat_errors_rotated = None + self.err = None + self.err_rotated = None self.rotation_angle = 0 self.parallactic_angle = None self.saturation = None @@ -154,6 +166,13 @@ def __init__(self, file_name, *, target_label="", disperser_label="", self.pressure = 0 self.humidity = 0 + self.flat = None + self.flat_rotated = None + self.starfield = None + self.starfield_rotated = None + self.mask = None + self.mask_rotated = None + if parameters.CALLING_CODE != 'LSST_DM' and file_name != "": self.load_image(file_name) else: @@ -193,20 +212,28 @@ def rebin(self): -------- >>> parameters.CCD_REBIN = 2 >>> im = Image('tests/data/reduc_20170605_028.fits') + >>> im.mask = np.zeros_like(im.data).astype(bool) + >>> im.mask[700:750, 800:850] = True >>> im.target_guess = [810, 590] >>> im.data.shape (2048, 2048) >>> im.rebin() >>> im.data.shape (1024, 1024) - >>> im.stat_errors.shape + >>> im.err.shape (1024, 1024) >>> im.target_guess array([405., 295.]) """ new_shape = np.asarray(self.data.shape) // parameters.CCD_REBIN self.data = rebin(self.data, new_shape) - self.stat_errors = np.sqrt(rebin(self.stat_errors ** 2, new_shape)) + self.err = np.sqrt(rebin(self.err ** 2, new_shape)) + if self.mask is not None: + self.mask = rebin(self.mask, new_shape, FLAG_MAKESUM=True).astype(bool) + if self.flat is not None: + self.flat = rebin(self.flat, new_shape, FLAG_MAKESUM=False) + if self.starfield is not None: + self.starfield = rebin(self.starfield, new_shape) if self.target_guess is not None: self.target_guess = np.asarray(self.target_guess) / parameters.CCD_REBIN @@ -284,9 +311,9 @@ def convert_to_ADU_rate_units(self): >>> assert np.all(np.isclose(data_before, im.data * im.expo)) """ self.data = self.data.astype(np.float64) / self.expo - self.stat_errors /= self.expo - if self.stat_errors_rotated is not None: - self.stat_errors_rotated /= self.expo + self.err /= self.expo + if self.err_rotated is not None: + self.err_rotated /= self.expo self.units = 'ADU/s' def convert_to_ADU_units(self): @@ -308,9 +335,9 @@ def convert_to_ADU_units(self): >>> assert np.all(np.isclose(data_before, im.data)) """ self.data *= self.expo - self.stat_errors *= self.expo - if self.stat_errors_rotated is not None: - self.stat_errors_rotated *= self.expo + self.err *= self.expo + if self.err_rotated is not None: + self.err_rotated *= self.expo self.units = 'ADU' def compute_statistical_error(self): @@ -350,9 +377,9 @@ def compute_statistical_error(self): # remove negative values (due to dead columns for instance min_noz = np.min(err2[err2 > 0]) err2[err2 <= 0] = min_noz - self.stat_errors = np.sqrt(err2) + self.err = np.sqrt(err2) # convert in ADU - self.stat_errors /= self.gain + self.err /= self.gain # check uncertainty model self.check_statistical_error() @@ -398,7 +425,7 @@ def check_statistical_error(self): data = np.copy(self.data) min_noz = np.min(data[data > 0]) data[data <= 0] = min_noz - y = self.stat_errors.flatten() ** 2 + y = self.err.flatten() ** 2 x = data.flatten() fit, cov, model = fit_poly1d(x, y, order=1) gain = 1 / fit[0] @@ -446,7 +473,7 @@ def plot_statistical_error(self): ax[0].grid() ax[0].set_ylabel(r"$\sigma_{\mathrm{ADU}}^2$ [ADU$^2$]") ax[0].set_xlabel(r"Data pixel values [ADU]") - plot_image_simple(ax[1], data=self.stat_errors, scale="log10", title="Statistical uncertainty map", + plot_image_simple(ax[1], data=self.err, scale="log10", title="Statistical uncertainty map", units=self.units, target_pixcoords=None, aspect="auto", cmap=None) fig.tight_layout() if parameters.LSST_SAVEFIGPATH: # pragma: no cover @@ -471,7 +498,7 @@ def compute_parallactic_angle(self): def plot_image(self, ax=None, scale="lin", title="", units="", plot_stats=False, target_pixcoords=None, figsize=(7.3, 6), aspect=None, vmin=None, vmax=None, - cmap=None, cax=None): + cmap=None, cax=None, use_flat=True): """Plot image. Parameters @@ -500,10 +527,14 @@ def plot_image(self, ax=None, scale="lin", title="", units="", plot_stats=False, Figure size (default: [9.3, 8]). plot_stats: bool If True, plot the uncertainty map instead of the image (default: False). + use_flat: bool + If True and self.flat exists, divide the image by the flat (default: True). Examples -------- >>> im = Image('tests/data/reduc_20170605_028.fits', config="./config/ctio.ini") + >>> im.mask = np.zeros_like(im.data).astype(bool) + >>> im.mask[700:705, 1250:1260] = True # test masking of some pixels like cosmic rays >>> im.plot_image(target_pixcoords=[820, 580], scale="symlog") >>> if parameters.DISPLAY: plt.show() """ @@ -512,10 +543,12 @@ def plot_image(self, ax=None, scale="lin", title="", units="", plot_stats=False, ax = plt.gca() data = np.copy(self.data) if plot_stats: - data = np.copy(self.stat_errors) + data = np.copy(self.err) if units == "": units = self.units - plot_image_simple(ax, data=data, scale=scale, title=title, units=units, cax=cax, + if self.flat is not None and use_flat: + data /= self.flat + plot_image_simple(ax, data=data, scale=scale, title=title, units=units, cax=cax, mask=self.mask, target_pixcoords=target_pixcoords, aspect=aspect, vmin=vmin, vmax=vmax, cmap=cmap) if parameters.OBS_OBJECT_TYPE == "STAR": plot_compass_simple(ax, self.parallactic_angle, arrow_size=0.1, origin=[0.15, 0.15]) @@ -528,6 +561,16 @@ def plot_image(self, ax=None, scale="lin", title="", units="", plot_stats=False, if parameters.PdfPages: parameters.PdfPages.savefig() + def simulate_starfield_with_gaia(self): + from spectractor.simulation.image_simulation import StarFieldModel + starfield = StarFieldModel(self, flux_factor=1) + yy, xx = np.mgrid[0:self.data.shape[1]:1, 0:self.data.shape[0]:1] + starfield.model(xx, yy) + if parameters.DEBUG: + self.plot_image(scale='symlog', target_pixcoords=starfield.pixcoords) + starfield.plot_model() + return starfield.field + def load_CTIO_image(image): """Specific routine to load CTIO fits files and load their data and properties for Spectractor. @@ -566,6 +609,8 @@ def load_CTIO_image(image): # compute CCD gain map build_CTIO_gain_map(image) build_CTIO_read_out_noise_map(image) + image.flat = image.gain / np.mean(image.gain) + # parallactic angle image.compute_parallactic_angle() # WCS wcs_file_name = set_wcs_file_name(image.file_name) @@ -679,7 +724,10 @@ def load_AUXTEL_image(image): # pragma: no cover image.my_logger.info(f'\n\tLoading AUXTEL image {image.file_name}...') with fits.open(image.file_name) as hdu_list: image.header = hdu_list[0].header - image.data = hdu_list[1].data.astype(np.float64) + if hdu_list[0].data is not None: + image.data = hdu_list[0].data.astype(np.float64) + else: + image.data = hdu_list[1].data.astype(np.float64) image.date_obs = image.header['DATE'] image.expo = float(image.header['EXPTIME']) if "empty" not in image.header['FILTER'].lower(): @@ -722,7 +770,7 @@ def load_AUXTEL_image(image): # pragma: no cover if parameters.OBS_CAMERA_ROTATION < -360: parameters.OBS_CAMERA_ROTATION += 360 image.header["CAM_ROT"] = parameters.OBS_CAMERA_ROTATION - if "CD2_1" in hdu_list[1].header: + if len(hdu_list) > 1 and "CD2_1" in hdu_list[1].header: rotation_wcs = 180 / np.pi * np.arctan2(hdu_list[1].header["CD2_1"], hdu_list[1].header["CD1_1"]) + 90 if not np.isclose(rotation_wcs % 360, parameters.OBS_CAMERA_ROTATION % 360, atol=2): image.my_logger.warning(f"\n\tWCS rotation angle is {rotation_wcs} degree while " @@ -759,20 +807,33 @@ def load_STARDICE_image(image): # pragma: no cover if "BSCALE" in image.header: del image.header["BSCALE"] - #Set the flip signs depending on the side of the pillar + ILLUREGION = slice(None, 1032), slice(1, 1057) + OVERSCANA = slice(1032, None), slice(None) + OVERSCANB = slice(None, 1032), slice(1059, None) + + def detrend(im): + res = im - np.mean(im[OVERSCANA], axis=0) # [:-100] + return np.subtract(res[ILLUREGION].T, np.mean(res[OVERSCANB], axis=1)).T + + if image.data.shape[0] > 1032 and image.data.shape[1] > 1057: + image.data = detrend(image.data) + # transformations so that stars are like in Stellarium up to a rotation + # with spectrogram nearly horizontal and on the right of central star + # no transformation if data are simulated + image.data = image.data[::-1, ::-1] + + #Set the flip signs depending on the side of the pillar if image.header['MOUNTTAU'] < 90: parameters.OBS_CAMERA_ROTATION = 180 elif image.header['MOUNTTAU'] >= 90: parameters.OBS_CAMERA_ROTATION = 0 + image.units = 'ADU' image.target_label = image.header['mountTARGET'] image.date_obs = image.header['DATE-OBS'] image.expo = float(image.header['cameraexptime']) image.filter_label = 'EMPTY' - # transformations so that stars are like in Stellarium up to a rotation - # with spectrogram nearly horizontal and on the right of central star - image.data = image.data[::-1, ::-1] image.airmass = 1/np.cos(np.radians(90-image.header['MOUNTALT'])) image.my_logger.info('\n\tImage loaded') @@ -786,10 +847,26 @@ def load_STARDICE_image(image): # pragma: no cover if image.header['MOUNTTAU'] >= 90: image.hour_angle = image.hour_angle - 180*units.deg image.dec = 180*units.deg - image.dec - image.temperature = 10 - image.pressure = 1000 - image.humidity = 87 - image.units = 'ADU' + + if "weatherAir temperature [C]" in image.header: + image.temperature = float(image.header["weatherAir temperature [C]"]) + else: + image.temperature = 10. + if "weatherAir pressure [hPa]" in image.header: + image.pressure = float(image.header["weatherAir pressure [hPa]"]) + else: + image.pressure = 950. + if "weatherRelative humidity [%]" in image.header: + image.humidity = float(image.header["weatherRelative humidity [%]"]) + else: + image.humidity = 50. + + # WCS + wcs_file_name = set_wcs_file_name(image.file_name) + if os.path.isfile(wcs_file_name): + image.my_logger.info(f"\n\tUse WCS {wcs_file_name}.") + image.wcs = load_wcs_from_file(wcs_file_name) + if "PC2_1" in image.header: rotation_wcs = 180 / np.pi * np.arctan2(-hdu_list[0].header["PC2_1"]/hdu_list[0].header["CDELT2"], hdu_list[0].header["PC1_1"]/hdu_list[0].header["CDELT1"]) atol = 0.02 @@ -934,6 +1011,8 @@ def find_target(image, guess=None, rotated=False, widths=[parameters.XWINDOW, pa image.target.image_x0 = sub_image_x0 image.target.image_y0 = sub_image_y0 image.target_pixcoords = [theX, theY] + if image.starfield is not None: + image.target.starfield = np.copy(image.starfield[int(theY) - Dy:int(theY) + Dy, int(theX) - Dx:int(theX) + Dx]) image.header['TARGETX'] = theX image.header.comments['TARGETX'] = 'target position on X axis' image.header['TARGETY'] = theY @@ -984,10 +1063,10 @@ def find_target_init(image, guess, rotated=False, widths=[parameters.XWINDOW, pa Dx, Dy = widths if rotated: sub_image = np.copy(image.data_rotated[y0 - Dy:y0 + Dy, x0 - Dx:x0 + Dx]) - sub_errors = np.copy(image.stat_errors[y0 - Dy:y0 + Dy, x0 - Dx:x0 + Dx]) + sub_errors = np.copy(image.err[y0 - Dy:y0 + Dy, x0 - Dx:x0 + Dx]) else: sub_image = np.copy(image.data[y0 - Dy:y0 + Dy, x0 - Dx:x0 + Dx]) - sub_errors = np.copy(image.stat_errors[y0 - Dy:y0 + Dy, x0 - Dx:x0 + Dx]) + sub_errors = np.copy(image.err[y0 - Dy:y0 + Dy, x0 - Dx:x0 + Dx]) # usually one rebin by adding pixel contents image.saturation = parameters.CCD_MAXADU / image.expo *parameters.CCD_REBIN**2 @@ -1411,11 +1490,21 @@ def turn_image(image): if not np.isnan(image.rotation_angle): image.data_rotated = ndimage.rotate(image.data, image.rotation_angle, prefilter=parameters.ROT_PREFILTER, order=parameters.ROT_ORDER) - image.stat_errors_rotated = np.sqrt( - np.abs(ndimage.rotate(image.stat_errors ** 2, image.rotation_angle, + image.err_rotated = np.sqrt( + np.abs(ndimage.rotate(image.err ** 2, image.rotation_angle, prefilter=parameters.ROT_PREFILTER, order=parameters.ROT_ORDER))) - min_noz = np.min(image.stat_errors_rotated[image.stat_errors_rotated > 0]) - image.stat_errors_rotated[image.stat_errors_rotated <= 0] = min_noz + min_noz = np.min(image.err_rotated[image.err_rotated > 0]) + image.err_rotated[image.err_rotated <= 0] = min_noz + if image.flat is not None: + image.flat_rotated = ndimage.rotate(image.flat, image.rotation_angle, + prefilter=parameters.ROT_PREFILTER, order=parameters.ROT_ORDER) + if image.starfield is not None: + image.starfield_rotated = ndimage.rotate(image.starfield, image.rotation_angle, + prefilter=parameters.ROT_PREFILTER, order=parameters.ROT_ORDER) + if image.mask is not None: + image.mask_rotated = ndimage.rotate(image.mask, image.rotation_angle, + prefilter=parameters.ROT_PREFILTER, order=parameters.ROT_ORDER) + if parameters.DEBUG: margin = 100 // parameters.CCD_REBIN y0 = int(image.target_pixcoords[1]) diff --git a/spectractor/extractor/psf.py b/spectractor/extractor/psf.py index 63acf2bc4..cf397f648 100644 --- a/spectractor/extractor/psf.py +++ b/spectractor/extractor/psf.py @@ -1187,15 +1187,15 @@ def __init__(self, values=None, clip=False): values = np.copy(self.values_default) labels = ["amplitude", "x_c", "y_c", "gamma", "alpha", "saturation"] axis_names = ["$A$", r"$x_c$", r"$y_c$", r"$\gamma$", r"$\alpha$", "saturation"] - bounds = [(0, np.inf), (-np.inf, np.inf), (-np.inf, np.inf), (0.1, np.inf), - (1.1, 100), (0, np.inf)] + bounds = [(0, np.inf), (-np.inf, np.inf), (-np.inf, np.inf), (1, np.inf), + (1.1, 10), (0, np.inf)] self.params = FitParameters(values=values, labels=labels, axis_names=axis_names, bounds=bounds) def apply_max_width_to_bounds(self, max_half_width=None): if max_half_width is not None: self.max_half_width = max_half_width - self.params.bounds[2] = (0, 2 * self.max_half_width) - self.params.bounds[3] = (0.1, self.max_half_width) + self.params.bounds[2] = (-2 * self.max_half_width, 2 * self.max_half_width) + self.params.bounds[3] = (1, self.max_half_width) def evaluate(self, pixels, values=None): r"""Evaluate the Moffat function. @@ -1390,7 +1390,7 @@ def __init__(self, values=None, clip=False): def apply_max_width_to_bounds(self, max_half_width=None): if max_half_width is not None: self.max_half_width = max_half_width - self.params.bounds[2] = (0, 2 * self.max_half_width) + self.params.bounds[2] = (-2 * self.max_half_width, 2 * self.max_half_width) self.params.bounds[3] = (1, self.max_half_width) def evaluate(self, pixels, values=None): @@ -1556,16 +1556,16 @@ def __init__(self, values=None, clip=False): values = np.copy(self.values_default) labels = ["amplitude", "x_c", "y_c", "gamma", "alpha", "eta_gauss", "stddev", "saturation"] axis_names = ["$A$", r"$x_c$", r"$y_c$", r"$\gamma$", r"$\alpha$", r"$\eta$", r"$\sigma$", "saturation"] - bounds = [(0, np.inf), (-np.inf, np.inf), (-np.inf, np.inf), (0.1, np.inf), (1.1, 100), - (-1, -5e-3), (0.5, np.inf), (0, np.inf)] + bounds = [(0, np.inf), (-np.inf, np.inf), (-np.inf, np.inf), (1, np.inf), (1.1, 10), + (-1, -5e-3), (1, np.inf), (0, np.inf)] self.params = FitParameters(values=values, labels=labels, axis_names=axis_names, bounds=bounds) def apply_max_width_to_bounds(self, max_half_width=None): if max_half_width is not None: self.max_half_width = max_half_width - self.params.bounds[2] = (0, 2 * self.max_half_width) - self.params.bounds[3] = (0.1, self.max_half_width) - self.params.bounds[6] = (0.5, self.max_half_width) + self.params.bounds[2] = (-2 * self.max_half_width, 2 * self.max_half_width) + self.params.bounds[3] = (1, self.max_half_width) + self.params.bounds[6] = (1, self.max_half_width) def evaluate(self, pixels, values=None): r"""Evaluate the MoffatGauss function. @@ -1769,7 +1769,7 @@ def func(x, y, amplitude, x_c, y_c, gamma): def apply_max_width_to_bounds(self, max_half_width=None): if max_half_width is not None: self.max_half_width = max_half_width - self.params.bounds[2] = (0, 2 * self.max_half_width) + self.params.bounds[2] = (-2 * self.max_half_width, 2 * self.max_half_width) def evaluate(self, pixels, values=None): r"""Evaluate the Order 0 interpolated function. @@ -2093,8 +2093,9 @@ def plot_fit(self): if self.bgd_model_func is not None: data = data + self.bgd_model_func(self.pixels) ax[0].errorbar(self.pixels, data, yerr=self.err, fmt='ro', label="Data") - if len(self.outliers) > 0: - ax[0].errorbar(self.outliers, data[self.outliers], yerr=self.err[self.outliers], fmt='go', + if len(self.outliers) > 0 or len(self.mask) > 0: + bads = list(np.unique(np.concatenate([self.mask, self.outliers])).astype(int)) + ax[0].errorbar(bads, data[bads], yerr=self.err[bads], fmt='go', label=rf"Outliers ({self.sigma_clip}$\sigma$)") if self.bgd_model_func is not None: ax[0].plot(self.pixels, self.bgd_model_func(self.pixels), 'b--', label="fitted bgd") @@ -2124,10 +2125,11 @@ def plot_fit(self): residuals = (data - model) / self.err residuals_err = np.ones_like(self.err) ax[1].errorbar(self.pixels, residuals, yerr=residuals_err, fmt='ro') - if len(self.outliers) > 0: - residuals_outliers = (data[self.outliers] - model[self.outliers]) / self.err[self.outliers] + if len(self.outliers) > 0 or len(self.mask) > 0: + bads = list(np.unique(np.concatenate([self.mask, self.outliers])).astype(int)) + residuals_outliers = (data[bads] - model[bads]) / self.err[bads] residuals_outliers_err = np.ones_like(residuals_outliers) - ax[1].errorbar(self.outliers, residuals_outliers, yerr=residuals_outliers_err, fmt='go') + ax[1].errorbar(bads, residuals_outliers, yerr=residuals_outliers_err, fmt='go') ax[1].axhline(0, color='b') ax[1].grid(True) std = np.std(residuals) diff --git a/spectractor/extractor/spectrum.py b/spectractor/extractor/spectrum.py index c3641e06f..fb09fa5f2 100644 --- a/spectractor/extractor/spectrum.py +++ b/spectractor/extractor/spectrum.py @@ -133,7 +133,7 @@ class Spectrum: Outside relative humidity in fraction of one. throughput: callable Instrumental throughput of the telescope. - spectrogram: array + spectrogram_data: array Spectrogram 2D image in image units. spectrogram_bgd: array Estimated 2D background fitted below the spectrogram in image units. @@ -145,6 +145,12 @@ class Spectrum: Best fitting model of the spectrogram in image units. spectrogram_residuals: array Residuals between the spectrogram data and the best fitting model of the spectrogram in image units. + spectrogram_flat: array + Flat array for the spectrogram with average=1. + spectrogram_starfield: array + Star field simulation array for the spectrogram in ADU/s. + spectrogram_mask: array + Boolean mask array to flag the defects. spectrogram_x0: float Relative position of the target in the spectrogram array along the x axis. spectrogram_y0: float @@ -237,12 +243,15 @@ def __init__(self, file_name="", image=None, order=1, target=None, config="", fa self.rotation_angle = 0 self.parallactic_angle = None self.camera_angle = 0 - self.spectrogram = None + self.spectrogram_data = None self.spectrogram_bgd = None self.spectrogram_bgd_rms = None self.spectrogram_err = None self.spectrogram_residuals = None self.spectrogram_fit = None + self.spectrogram_flat = None + self.spectrogram_starfield = None + self.spectrogram_mask = None self.spectrogram_x0 = None self.spectrogram_y0 = None self.spectrogram_xmin = None @@ -504,7 +513,7 @@ def plot_spectrogram(self, ax=None, scale="lin", title="", units="Image units", if ax is None: plt.figure(figsize=figsize) ax = plt.gca() - data = np.copy(self.spectrogram) + data = np.copy(self.spectrogram_data) if plot_stats: data = np.copy(self.spectrogram_err) plot_image_simple(ax, data=data, scale=scale, title=title, units=units, cax=cax, @@ -587,7 +596,7 @@ def generate_axes(fig): widthPlot.set_xlabel(r'$\lambda$ [nm]') widthPlot.grid() - spectrogram = np.copy(self.spectrogram) + spectrogram = np.copy(self.spectrogram_data) res = self.spectrogram_residuals.reshape((-1, self.spectrogram_Nx)) std = np.std(res) if spectrogram.shape[0] != res.shape[0]: @@ -647,8 +656,8 @@ def save_spectrum(self, output_file_name, overwrite=False): """ from spectractor._version import __version__ self.header["VERSION"] = str(__version__) - self.header["REBIN"] = parameters.CCD_REBIN - self.header.comments['REBIN'] = 'original image rebinning factor to get spectrum.' + self.header["CCD_REBIN"] = parameters.CCD_REBIN + self.header.comments['CCD_REBIN'] = 'original image rebinning factor to get spectrum.' self.header['UNIT1'] = "nanometer" self.header['UNIT2'] = self.units self.header['COMMENTS'] = 'First column gives the wavelength in unit UNIT1, ' \ @@ -669,7 +678,7 @@ def save_spectrum(self, output_file_name, overwrite=False): # print(f"Set header key {header_key} to {value} from attr {attribute}") extnames = ["SPECTRUM", "SPEC_COV", "ORDER2", "ORDER0"] # spectrum data - extnames += ["S_DATA", "S_ERR", "S_BGD", "S_BGD_ER", "S_FIT", "S_RES"] # spectrogram data + extnames += ["S_DATA", "S_ERR", "S_BGD", "S_BGD_ER", "S_FIT", "S_RES", "S_FLAT", "S_STAR", "S_MASK"] extnames += ["PSF_TAB"] # PSF parameter table extnames += ["LINES"] # spectroscopic line table extnames += ["CONFIG"] # config parameters @@ -682,13 +691,16 @@ def save_spectrum(self, output_file_name, overwrite=False): if extname == "SPEC_COV": hdus[extname].data = self.cov_matrix elif extname == "ORDER2": - hdus[extname].data = [self.lambdas, self.data_next_order, self.err_next_order] + if self.data_next_order is not None: + hdus[extname].data = [self.lambdas, self.data_next_order, self.err_next_order] + else: + hdus[extname].data = [self.lambdas, np.zeros_like(self.lambdas), np.zeros_like(self.lambdas)] elif extname == "ORDER0": hdus[extname].data = self.target.image hdus[extname].header["IM_X0"] = self.target.image_x0 hdus[extname].header["IM_Y0"] = self.target.image_y0 elif extname == "S_DATA": - hdus[extname].data = self.spectrogram + hdus[extname].data = self.spectrogram_data hdus[extname].header['UNIT1'] = self.units elif extname == "S_ERR": hdus[extname].data = self.spectrogram_err @@ -700,6 +712,15 @@ def save_spectrum(self, output_file_name, overwrite=False): hdus[extname].data = self.spectrogram_fit elif extname == "S_RES": hdus[extname].data = self.spectrogram_residuals + elif extname == "S_FLAT": + hdus[extname].data = self.spectrogram_flat + elif extname == "S_STAR": + hdus[extname].data = self.spectrogram_starfield + elif extname == "S_MASK": + if self.spectrogram_mask is not None: + hdus[extname].data = self.spectrogram_mask.astype(int) + else: + hdus[extname].data = self.spectrogram_mask elif extname == "PSF_TAB": hdus[extname] = fits.table_to_hdu(self.chromatic_psf.table) elif extname == "LINES": @@ -784,7 +805,7 @@ def save_spectrogram(self, output_file_name, overwrite=False): # pragma: no cov hdu6 = fits.ImageHDU() hdu6.header["EXTNAME"] = "S_RES" hdu1.header = self.header - hdu1.data = self.spectrogram + hdu1.data = self.spectrogram_data hdu2.data = self.spectrogram_err hdu3.data = self.spectrogram_bgd hdu4.data = self.spectrogram_bgd_rms @@ -967,7 +988,7 @@ def load_spectrum_older_24(self, input_file_name, spectrogram_file_name_override self.target.image_y0 = float(hdu_list["ORDER0"].header["IM_Y0"]) # load spectrogram info if len(hdu_list) > 4: - self.spectrogram = hdu_list["S_DATA"].data + self.spectrogram_data = hdu_list["S_DATA"].data self.spectrogram_err = hdu_list["S_ERR"].data self.spectrogram_bgd = hdu_list["S_BGD"].data if len(hdu_list) > 7: @@ -1072,7 +1093,7 @@ def load_spectrum_latest(self, input_file_name): self.chromatic_psf.opt_reg = float(self.header["PSF_REG"]) if not self.fast_load: - with fits.open(input_file_name) as hdu_list: + with (fits.open(input_file_name) as hdu_list): # load other spectrum info self.cov_matrix = hdu_list["SPEC_COV"].data _, self.data_next_order, self.err_next_order = hdu_list["ORDER2"].data @@ -1080,12 +1101,20 @@ def load_spectrum_latest(self, input_file_name): self.target.image_x0 = float(hdu_list["ORDER0"].header["IM_X0"]) self.target.image_y0 = float(hdu_list["ORDER0"].header["IM_Y0"]) # load spectrogram info - self.spectrogram = hdu_list["S_DATA"].data + self.spectrogram_data = hdu_list["S_DATA"].data self.spectrogram_err = hdu_list["S_ERR"].data self.spectrogram_bgd = hdu_list["S_BGD"].data self.spectrogram_bgd_rms = hdu_list["S_BGD_ER"].data self.spectrogram_fit = hdu_list["S_FIT"].data self.spectrogram_residuals = hdu_list["S_RES"].data + if "S_FLAT" in [hdu.name for hdu in hdu_list]: + self.spectrogram_flat = hdu_list["S_FLAT"].data + if "S_STAR" in [hdu.name for hdu in hdu_list]: + self.spectrogram_starfield = hdu_list["S_STAR"].data + if "S_MASK" in [hdu.name for hdu in hdu_list]: + self.spectrogram_mask = hdu_list["S_MASK"].data + if self.spectrogram_mask is not None: + self.spectrogram_mask = self.spectrogram_mask.astype(bool) self.chromatic_psf.init_from_table(Table.read(hdu_list["PSF_TAB"]), saturation=self.spectrogram_saturation) self.lines.table = Table.read(hdu_list["LINES"], unit_parse_strict="silent") @@ -1106,7 +1135,7 @@ def load_spectrogram(self, input_file_name): # pragma: no cover if os.path.isfile(input_file_name): with fits.open(input_file_name) as hdu_list: header = hdu_list[0].header - self.spectrogram = hdu_list[0].data + self.spectrogram_data = hdu_list[0].data self.spectrogram_err = hdu_list[1].data self.spectrogram_bgd = hdu_list[2].data if len(hdu_list) > 3: @@ -1787,8 +1816,8 @@ def detect_lines(lines, lambdas, spec, spec_err=None, cov_matrix=None, fwhm_func Y = -Gauss / Continuum Ydata = 1 - spectr_data / Continuum - line.fit_eqwidth_mod = integrate.simps(Y, x_int) # sol1 - line.fit_eqwidth_data = integrate.simps(Ydata, x_int) # sol2 + line.fit_eqwidth_mod = integrate.simpson(Y, x=x_int) # sol1 + line.fit_eqwidth_data = integrate.simpson(Ydata, x=x_int) # sol2 line.fit_popt = popt line.fit_pcov = pcov diff --git a/spectractor/extractor/targets.py b/spectractor/extractor/targets.py index 25c830633..6a29e8cd0 100644 --- a/spectractor/extractor/targets.py +++ b/spectractor/extractor/targets.py @@ -86,6 +86,7 @@ def __init__(self, label, verbose=False): self.image = None self.image_x0 = None self.image_y0 = None + self.starfield = None class ArcLamp(Target): @@ -230,6 +231,9 @@ def __init__(self, label, verbose=False): """ Target.__init__(self, label, verbose=verbose) self.my_logger = set_logger(self.__class__.__name__) + self.lines = Lines(HYDROGEN_LINES + ATMOSPHERIC_LINES + STELLAR_LINES, + redshift=self.redshift, emission_spectrum=self.emission_spectrum, + hydrogen_only=self.hydrogen_only) self.simbad_table = None self.load() diff --git a/spectractor/fit/fit_multispectra.py b/spectractor/fit/fit_multispectra.py index 521f1adf2..c8db045d7 100644 --- a/spectractor/fit/fit_multispectra.py +++ b/spectractor/fit/fit_multispectra.py @@ -51,7 +51,7 @@ def _build_sim_sample(spectra, aerosols=0.05, ozone=300, pwv=5, angstrom_exponen # fast_sim must be True to avoid biases (the rebinning is done after in _prepare_data()) s = SpectrumSimulation(spec, atmosphere=atm, fast_sim=True, with_adr=True) s.simulate(A1=1, A2=0, aerosols=aerosols, angstrom_exponent=angstrom_exponent, ozone=ozone, pwv=pwv, - reso=-1, D=parameters.DISTANCE2CCD, shift_x=0, B=0) + reso=-1, D=parameters.DISTANCE2CCD, shift_x=0) sim_spectra.append(s) return sim_spectra @@ -99,7 +99,7 @@ def _build_test_sample(targets=["HD111980"]*3, zs=np.linspace(1, 2, 3), aerosols s.temperature = temperature s.adr_params = [s.dec, s.hour_angle, temperature, pressure, s.humidity, airmass] s.simulate(A1=1, A2=0, aerosols=aerosols, angstrom_exponent=angstrom_exponent, ozone=ozone, pwv=pwv, - reso=-1, D=parameters.DISTANCE2CCD, shift_x=0, B=0) + reso=-1, D=parameters.DISTANCE2CCD, shift_x=0) spectra.append(s) return spectra diff --git a/spectractor/fit/fit_spectrogram.py b/spectractor/fit/fit_spectrogram.py index 80fdf8b97..ddaf3f715 100644 --- a/spectractor/fit/fit_spectrogram.py +++ b/spectractor/fit/fit_spectrogram.py @@ -67,26 +67,29 @@ def __init__(self, spectrum, atmgrid_file_name="", fit_angstrom_exponent=False, self.psf_poly_params = self.spectrum.chromatic_psf.from_table_to_poly_params()[length:] self.saturation = self.spectrum.spectrogram_saturation D2CCD = np.copy(spectrum.header['D2CCD']) - p = np.array([1, 1, 1, 0.05, 1.2, 400, 5, D2CCD, self.spectrum.header['PIXSHIFT'], - 0, self.spectrum.rotation_angle, 1]) - self.psf_params_start_index = np.array([12 + len(self.psf_poly_params) * k for k in range(len(self.diffraction_orders))]) + p = np.array([1, 1, 0, 0.05, 1.2, 400, 5, 1, 1, D2CCD, self.spectrum.header['PIXSHIFT'], + 0, self.spectrum.rotation_angle]) + # parameter indices for which we don't need to recompute the PSF cube for model evaluation + # warning: they must be contiguous to preserve psf_cube in jacobian function loop + self.fixed_psf_params = np.arange(0, 9, dtype=int) + self.psf_params_start_index = np.array([p.size + len(self.psf_poly_params) * k for k in range(len(self.diffraction_orders))]) psf_poly_params_labels = np.copy(self.spectrum.chromatic_psf.params.labels[length:]) psf_poly_params_names = np.copy(self.spectrum.chromatic_psf.params.axis_names[length:]) psf_poly_params_bounds = self.spectrum.chromatic_psf.set_bounds() p = np.concatenate([p] + [self.psf_poly_params] * len(self.diffraction_orders)) input_labels = [f"A{order}" for order in self.diffraction_orders] - input_labels += ["VAOD", "angstrom_exp", "ozone [db]", "PWV [mm]", r"D_CCD [mm]", - r"shift_x [pix]", r"shift_y [pix]", r"angle [deg]", "B"] + input_labels += ["VAOD", "angstrom_exp", "ozone [db]", "PWV [mm]", "B", "A_star", + r"D_CCD [mm]", r"shift_x [pix]", r"shift_y [pix]", r"angle [deg]"] for order in self.diffraction_orders: input_labels += [label + f"_{order}" for label in psf_poly_params_labels] axis_names = [f"$A_{order}$" for order in self.diffraction_orders] - axis_names += ["VAOD", r'$\"a$', "ozone [db]", "PWV [mm]", r"$D_{CCD}$ [mm]", - r"$\Delta_{\mathrm{x}}$ [pix]", r"$\Delta_{\mathrm{y}}$ [pix]", r"$\theta$ [deg]", "$B$"] + axis_names += ["VAOD", r'$\"a$', "ozone [db]", "PWV [mm]", "$B$", r"$A_{star}$", r"$D_{CCD}$ [mm]", + r"$\Delta_{\mathrm{x}}$ [pix]", r"$\Delta_{\mathrm{y}}$ [pix]", r"$\theta$ [deg]"] for order in self.diffraction_orders: axis_names += [label+rf"$\!_{order}$" for label in psf_poly_params_names] - bounds = [[0, 2], [0, 2], [0, 2], [0, 0.1], [0, 3], [100, 700], [0, 20], + bounds = [[0, 2], [0, 2], [0, 2], [0, 0.1], [0, 3], [100, 700], [0, 20], [0.8, 1.2], [0, np.inf], [D2CCD - 5 * parameters.DISTANCE2CCD_ERR, D2CCD + 5 * parameters.DISTANCE2CCD_ERR], [-2, 2], - [-10, 10], [-90, 90], [0.8, 1.2]] + [-10, 10], [-90, 90]] bounds += list(psf_poly_params_bounds) * len(self.diffraction_orders) fixed = [False] * p.size for k, par in enumerate(input_labels): @@ -96,17 +99,20 @@ def __init__(self, spectrum, atmgrid_file_name="", fit_angstrom_exponent=False, if "y_c" in par: fixed[k] = False p[k] = 0 + for k, par in enumerate(input_labels): + if k >= self.psf_params_start_index[0] and "y_c" not in par and "x_c" not in par and par[-2:] != f"_{spectrum.order}" and "_0_" not in par: + fixed[k] = True + p[k] = 0 params = FitParameters(p, labels=input_labels, axis_names=axis_names, bounds=bounds, fixed=fixed, truth=truth, filename=self.filename) - self.fixed_psf_params = np.array([0, 1, 2, 3, 4, 5, 6, 9]) self.atm_params_indices = np.array([params.get_index(label) for label in ["VAOD", "angstrom_exp", "ozone [db]", "PWV [mm]"]]) # A2 is free only if spectrogram is a simulation or if the order 2/1 ratio is not known and flat if "A2" in params.labels: params.fixed[params.get_index(f"A{self.diffraction_orders[1]}")] = "A2_T" not in self.spectrum.header if "A3" in params.labels: params.fixed[params.get_index(f"A{self.diffraction_orders[2]}")] = "A3_T" not in self.spectrum.header - params.fixed[params.get_index(r"shift_x [pix]")] = True # Delta x + params.fixed[params.get_index(r"shift_x [pix]")] = False # Delta x params.fixed[params.get_index(r"shift_y [pix]")] = True # Delta y params.fixed[params.get_index(r"angle [deg]")] = True # angle params.fixed[params.get_index("B")] = True # B @@ -129,16 +135,29 @@ def __init__(self, spectrum, atmgrid_file_name="", fit_angstrom_exponent=False, if self.spectrum.spectrogram_Ny > 2 * parameters.PIXDIST_BACKGROUND: self.crop_spectrogram() self.lambdas = self.spectrum.lambdas - self.Ny, self.Nx = self.spectrum.spectrogram.shape - self.data = self.spectrum.spectrogram.flatten() + self.Ny, self.Nx = self.spectrum.spectrogram_data.shape + self.data = self.spectrum.spectrogram_data.flatten() self.err = self.spectrum.spectrogram_err.flatten() + self.bgd = self.spectrum.spectrogram_bgd.flatten() + if self.spectrum.spectrogram_flat is not None: + self.flat = self.spectrum.spectrogram_flat.flatten() + else: + self.flat = None + if self.spectrum.spectrogram_starfield is not None: + self.starfield = self.spectrum.spectrogram_starfield.flatten() + else: + self.starfield = None + if self.spectrum.spectrogram_mask is not None: + self.mask = list(np.where(spectrum.spectrogram_mask.astype(bool).ravel())[0]) + else: + self.mask = [] self.fit_angstrom_exponent = fit_angstrom_exponent if not fit_angstrom_exponent: self.params.fixed[self.params.get_index("angstrom_exp")] = True # angstrom exponent self.params.values[self.params.get_index("angstrom_exp")] = self.atmosphere.angstrom_exponent_default - self.simulation = SpectrogramModel(self.spectrum, atmosphere=self.atmosphere, + self.spectrogram_simulation = SpectrogramModel(self.spectrum, atmosphere=self.atmosphere, diffraction_orders=self.diffraction_orders, - with_background=True, fast_sim=False, with_adr=True) + fast_sim=False, with_adr=True) self.lambdas_truth = None self.amplitude_truth = None self.get_spectrogram_truth() @@ -164,11 +183,17 @@ def crop_spectrogram(self): self.spectrum.spectrogram_ymax = self.spectrum.spectrogram_ymax - bgd_width self.spectrum.spectrogram_ymin += bgd_width self.spectrum.spectrogram_bgd = self.spectrum.spectrogram_bgd[bgd_width:-bgd_width, :] - self.spectrum.spectrogram = self.spectrum.spectrogram[bgd_width:-bgd_width, :] + self.spectrum.spectrogram_data = self.spectrum.spectrogram_data[bgd_width:-bgd_width, :] self.spectrum.spectrogram_err = self.spectrum.spectrogram_err[bgd_width:-bgd_width, :] + if self.spectrum.spectrogram_flat is not None: + self.spectrum.spectrogram_flat = self.spectrum.spectrogram_flat[bgd_width:-bgd_width, :] + if self.spectrum.spectrogram_starfield is not None: + self.spectrum.spectrogram_starfield = self.spectrum.spectrogram_starfield[bgd_width:-bgd_width, :] + if self.spectrum.spectrogram_mask is not None: + self.spectrum.spectrogram_mask = self.spectrum.spectrogram_mask[bgd_width:-bgd_width, :] self.spectrum.spectrogram_y0 -= bgd_width self.spectrum.chromatic_psf.y0 -= bgd_width - self.spectrum.spectrogram_Ny, self.spectrum.spectrogram_Nx = self.spectrum.spectrogram.shape + self.spectrum.spectrogram_Ny, self.spectrum.spectrogram_Nx = self.spectrum.spectrogram_data.shape self.spectrum.chromatic_psf.table["y_c"] -= bgd_width self.my_logger.debug(f'\n\tSize of the spectrogram region after cropping: ' f'({self.spectrum.spectrogram_Nx},{self.spectrum.spectrogram_Ny})') @@ -194,11 +219,11 @@ def set_mask(self, params=None): self.my_logger.info("\n\tReset spectrogram mask with current parameters.") if params is None: params = self.params.values - A1, A2, A3, aerosols, angstrom_exponent, ozone, pwv, D, shift_x, shift_y, angle, B, *psf_poly_params_all = params + A1, A2, A3, aerosols, angstrom_exponent, ozone, pwv, B, Astar, D, shift_x, shift_y, angle, *psf_poly_params_all = params poly_params = np.array(psf_poly_params_all).reshape((len(self.diffraction_orders), -1)) - self.simulation.psf_cubes_masked = {} - self.simulation.M_sparse_indices = {} - self.simulation.psf_cube_sparse_indices = {} + self.spectrogram_simulation.psf_cubes_masked = {} + self.spectrogram_simulation.M_sparse_indices = {} + self.spectrogram_simulation.psf_cube_sparse_indices = {} for k, order in enumerate(self.diffraction_orders): profile_params = self.spectrum.chromatic_psf.from_poly_params_to_profile_params(poly_params[k], apply_bounds=True) @@ -208,19 +233,30 @@ def set_mask(self, params=None): niter=5, with_adr=True, order=order) profile_params[:, 0] = 1 - profile_params[:, 1] = dispersion_law.real + self.simulation.r0.real - profile_params[:, 2] += dispersion_law.imag - psf_cube_masked = self.spectrum.chromatic_psf.build_psf_cube_masked(self.simulation.pixels, profile_params, + profile_params[:, 1] = dispersion_law.real + self.spectrogram_simulation.r0.real + profile_params[:, 2] += dispersion_law.imag # - self.bgd_width + psf_cube_masked = self.spectrum.chromatic_psf.build_psf_cube_masked(self.spectrogram_simulation.pixels, profile_params, fwhmx_clip=3 * parameters.PSF_FWHM_CLIP, fwhmy_clip=parameters.PSF_FWHM_CLIP) psf_cube_masked = self.spectrum.chromatic_psf.convolve_psf_cube_masked(psf_cube_masked) # make rectangular mask per wavelength - self.simulation.boundaries[order], self.simulation.psf_cubes_masked[order] = self.spectrum.chromatic_psf.get_boundaries(psf_cube_masked) - self.simulation.psf_cube_sparse_indices[order], self.simulation.M_sparse_indices[order] = self.spectrum.chromatic_psf.get_sparse_indices(psf_cube_masked) - mask = np.sum(self.simulation.psf_cubes_masked[self.diffraction_orders[0]].reshape(psf_cube_masked.shape[0], self.simulation.pixels[0].size), axis=0) == 0 + self.spectrogram_simulation.boundaries[order], self.spectrogram_simulation.psf_cubes_masked[order] = self.spectrum.chromatic_psf.set_rectangular_boundaries(psf_cube_masked) + if k > 0: + # spectrogram model must be accurate inside the k=0 order footprint: enlarge the next order footprints + self.spectrogram_simulation.boundaries[order]["ymin"] = np.zeros_like(self.spectrogram_simulation.boundaries[order]["ymin"]) + self.spectrogram_simulation.boundaries[order]["ymax"] = self.Ny * np.ones_like(self.spectrogram_simulation.boundaries[order]["ymax"]) + self.spectrogram_simulation.psf_cube_sparse_indices[order], self.spectrogram_simulation.M_sparse_indices[order] = self.spectrum.chromatic_psf.get_sparse_indices(self.spectrogram_simulation.boundaries[order]) + mask = np.sum(self.spectrogram_simulation.psf_cubes_masked[self.diffraction_orders[0]].reshape(psf_cube_masked.shape[0], self.spectrogram_simulation.pixels[0].size), axis=0) == 0 + # cumulate the boolean values as int + weight_mask = np.sum(self.spectrogram_simulation.psf_cubes_masked[self.diffraction_orders[0]], axis=0) + # look for indices with maximum weight per column (all sheets of the psf cube have contributed) + res = np.max(weight_mask, axis=0)[np.newaxis,:] * np.ones((weight_mask.shape[0],1)) + # keep only the pixels where all psf_cube sheets have contributed per column + mask = (weight_mask != res).ravel() self.W = np.copy(self.W_before_mask) self.W[mask] = 0 - self.mask = list(np.where(mask)[0]) + self.mask += list(np.where(mask)[0]) + self.mask = list(set(self.mask)) def get_spectrogram_truth(self): """Load the truth parameters (if provided) from the file header. @@ -241,11 +277,12 @@ def get_spectrogram_truth(self): shifty_truth = 0 rotation_angle = self.spectrum.header['ROT_T'] B = 1 - poly_truth = np.fromstring(self.spectrum.header['PSF_P_T'][1:-1], sep=' ', dtype=float) + Astar = 1 + poly_truth = np.fromstring(self.spectrum.header['PSF_P_T'][1:-1], sep=',', dtype=float) self.truth = (A1_truth, A2_truth, A3_truth, aerosols_truth, ozone_truth, pwv_truth, - D_truth, shiftx_truth, shifty_truth, rotation_angle, B, *poly_truth) - self.lambdas_truth = np.fromstring(self.spectrum.header['LBDAS_T'][1:-1], sep=' ', dtype=float) - self.amplitude_truth = np.fromstring(self.spectrum.header['AMPLIS_T'][1:-1], sep=' ', dtype=float) + D_truth, shiftx_truth, shifty_truth, rotation_angle, B, Astar, *poly_truth) + self.lambdas_truth = np.fromstring(self.spectrum.header['LBDAS_T'][1:-1], sep=',', dtype=float) + self.amplitude_truth = np.fromstring(self.spectrum.header['AMPLIS_T'][1:-1], sep=',', dtype=float) else: self.truth = None @@ -349,14 +386,20 @@ def simulate(self, *params): >>> w.plot_fit() """ - A1, A2, A3, aerosols, angstrom_exponent, ozone, pwv, D, shift_x, shift_y, angle, B, *psf_poly_params = params + A1, A2, A3, aerosols, angstrom_exponent, ozone, pwv, B, Astar, D, shift_x, shift_y, angle, *psf_poly_params = params self.params.values = np.asarray(params) if not self.fit_angstrom_exponent: angstrom_exponent = None - lambdas, model, model_err = self.simulation.simulate(A1, A2, A3, aerosols, angstrom_exponent, ozone, pwv, D, shift_x, shift_y, angle, B, psf_poly_params) + lambdas, model, model_err = self.spectrogram_simulation.simulate(A1, A2, A3, aerosols, angstrom_exponent, ozone, pwv, D, shift_x, shift_y, angle, psf_poly_params) self.lambdas = lambdas self.model = model.flatten() self.model_err = model_err.flatten() + self.model += B * self.bgd + if self.starfield is not None: + self.model += Astar * self.starfield + if self.flat is not None: + # TODO: if flat array is a cube flat, needs to multiply directly in build_psf_cube + self.model *= self.flat return self.lambdas, self.model, self.model_err def jacobian(self, params, epsilon, model_input=None): @@ -367,19 +410,19 @@ def jacobian(self, params, epsilon, model_input=None): lambdas, model, model_err = self.simulate(*params) model = model.flatten() J = np.zeros((params.size, model.size)) - strategy = copy.copy(self.simulation.fix_psf_cube) - atmosphere = copy.copy(self.simulation.atmosphere_sim) + strategy = copy.copy(self.spectrogram_simulation.fix_psf_cube) + atmosphere = copy.copy(self.spectrogram_simulation.atmosphere_sim) for ip, p in enumerate(params): if self.params.fixed[ip]: continue if ip in self.fixed_psf_params: - self.simulation.fix_psf_cube = True + self.spectrogram_simulation.fix_psf_cube = True else: - self.simulation.fix_psf_cube = False + self.spectrogram_simulation.fix_psf_cube = False if ip in self.atm_params_indices: - self.simulation.fix_atm_sim = False + self.spectrogram_simulation.fix_atm_sim = False else: - self.simulation.fix_atm_sim = True + self.spectrogram_simulation.fix_atm_sim = True if ip >= self.psf_params_start_index[0]: continue tmp_p = np.copy(params) @@ -387,21 +430,21 @@ def jacobian(self, params, epsilon, model_input=None): epsilon[ip] = - epsilon[ip] tmp_p[ip] += epsilon[ip] tmp_lambdas, tmp_model, tmp_model_err = self.simulate(*tmp_p) - if self.simulation.fix_atm_sim is False: - self.simulation.atmosphere_sim = atmosphere + if self.spectrogram_simulation.fix_atm_sim is False: + self.spectrogram_simulation.atmosphere_sim = atmosphere J[ip] = (tmp_model.flatten() - model) / epsilon[ip] - self.simulation.fix_atm_sim = True - self.simulation.fix_psf_cube = False + self.spectrogram_simulation.fix_atm_sim = True + self.spectrogram_simulation.fix_psf_cube = False for k, order in enumerate(self.diffraction_orders): - if self.simulation.profile_params[order] is None: + if self.spectrogram_simulation.profile_params[order] is None: continue start = self.psf_params_start_index[k] - profile_params = np.copy(self.simulation.profile_params[order]) - J[start:start+len(self.psf_poly_params)] = self.simulation.chromatic_psf.build_psf_jacobian(self.simulation.pixels, profile_params=profile_params, - psf_cube_sparse_indices=self.simulation.psf_cube_sparse_indices[order], - boundaries=self.simulation.boundaries[order], dtype="float32") - self.simulation.fix_psf_cube = strategy - self.simulation.fix_atm_sim = False + profile_params = np.copy(self.spectrogram_simulation.profile_params[order]) + J[start:start+len(self.psf_poly_params)] = self.spectrogram_simulation.chromatic_psf.build_psf_jacobian(self.spectrogram_simulation.pixels, profile_params=profile_params, + psf_cube_sparse_indices=self.spectrogram_simulation.psf_cube_sparse_indices[order], + boundaries=self.spectrogram_simulation.boundaries[order], dtype="float32") + self.spectrogram_simulation.fix_psf_cube = strategy + self.spectrogram_simulation.fix_atm_sim = False self.my_logger.debug(f"\n\tJacobian time computation = {time.time() - start:.1f}s") return J @@ -520,7 +563,7 @@ def run_spectrogram_minimisation(fit_workspace, method="newton", verbose=False): my_logger.info(f"\n\tStart guess: {guess}\n\twith {fit_workspace.params.labels}") epsilon = 1e-4 * guess epsilon[epsilon == 0] = 1e-4 - fixed = np.copy(fit_workspace.params.fixed) + fixed_default = np.copy(fit_workspace.params.fixed) # fit_workspace.simulation.fast_sim = True # fit_workspace.simulation.fix_psf_cube = False @@ -540,9 +583,18 @@ def run_spectrogram_minimisation(fit_workspace, method="newton", verbose=False): # run_minimisation(fit_workspace, method="newton", epsilon=epsilon, fix=fit_workspace.fixed, # xtol=1e-2, ftol=10 / fit_workspace.data.size, verbose=False) - fit_workspace.simulation.fast_sim = False - fit_workspace.simulation.fix_psf_cube = False - fit_workspace.params.fixed = np.copy(fixed) + fit_workspace.spectrogram_simulation.fast_sim = False + fit_workspace.spectrogram_simulation.fix_psf_cube = False + fit_workspace.params.fixed = [True] * len(fit_workspace.params.values) + fit_workspace.params.fixed[fit_workspace.params.get_index(r"A1")] = False # shift y + fit_workspace.params.fixed[fit_workspace.params.get_index(r"shift_y [pix]")] = False # shift y + fit_workspace.params.fixed[fit_workspace.params.get_index(r"angle [deg]")] = False # angle + run_minimisation(fit_workspace, "newton", epsilon, xtol=1e-2, ftol=0.01, with_line_search=False) + fit_workspace.params.fixed = fixed_default + + fit_workspace.spectrogram_simulation.fast_sim = False + fit_workspace.spectrogram_simulation.fix_psf_cube = False + fit_workspace.params.fixed = np.copy(fixed_default) # guess = fit_workspace.p # params_table, costs = run_gradient_descent(fit_workspace, guess, epsilon, params_table, costs, # fix=fit_workspace.fixed, xtol=1e-6, ftol=1 / fit_workspace.data.size, diff --git a/spectractor/fit/fit_spectrum.py b/spectractor/fit/fit_spectrum.py index 75981ba12..595fdd8af 100644 --- a/spectractor/fit/fit_spectrum.py +++ b/spectractor/fit/fit_spectrum.py @@ -63,6 +63,7 @@ def __init__(self, spectrum, atmgrid_file_name="", fit_angstrom_exponent=False, p = np.array([1, 0, 0.05, 1.2, 400, 5, 1, self.spectrum.header['D2CCD'], self.spectrum.header['PIXSHIFT'], 0]) fixed = [False] * p.size # fixed[0] = True + # TODO: StarDICE data for HD93521 clearly needs to fit A2 and shift_x => find a better way to decontaminate from order 2 fixed[1] = "A2_T" not in self.spectrum.header # fit A2 only on sims to evaluate extraction biases fixed[5] = False # fixed[6:8] = [True, True] @@ -75,9 +76,9 @@ def __init__(self, spectrum, atmgrid_file_name="", fit_angstrom_exponent=False, (0.1, 10),(p[7] - 5 * parameters.DISTANCE2CCD_ERR, p[7] + 5 * parameters.DISTANCE2CCD_ERR), (-2, 2), (-np.inf, np.inf)] params = FitParameters(p, labels=["A1", "A2", "VAOD", "angstrom_exp", "ozone [db]", "PWV [mm]", - "reso [pix]", r"D_CCD [mm]", r"alpha_pix [pix]", "B"], + "reso [nm]", r"D_CCD [mm]", r"alpha_pix [pix]", "B"], axis_names=["$A_1$", "$A_2$", "VAOD", r'$\"a$', "ozone [db]", "PWV [mm]", - "reso [pix]", r"$D_{CCD}$ [mm]", r"$\alpha_{\mathrm{pix}}$ [pix]", "$B$"], + "reso [nm]", r"$D_{CCD}$ [mm]", r"$\alpha_{\mathrm{pix}}$ [pix]", "$B$"], bounds=bounds, fixed=fixed, truth=truth, filename=spectrum.filename) FitWorkspace.__init__(self, params, verbose=verbose, plot=plot, live_fit=live_fit, file_name=spectrum.filename) if atmgrid_file_name == "": @@ -229,7 +230,9 @@ def simulate(self, A1, A2, aerosols, angstrom_exponent, ozone, pwv, reso, D, shi """ if not self.fit_angstrom_exponent: angstrom_exponent = None - lambdas, model, model_err = self.simulation.simulate(A1, A2, aerosols, angstrom_exponent, ozone, pwv, reso, D, shift_x, B) + lambdas, model, model_err = self.simulation.simulate(A1, A2, aerosols, angstrom_exponent, ozone, pwv, reso, D, shift_x) + if B != 0: + model += B / (lambdas * np.gradient(lambdas)) self.model = model self.model_err = model_err return lambdas, model, model_err diff --git a/spectractor/fit/fitter.py b/spectractor/fit/fitter.py index c09ee81ad..ed83a14dc 100644 --- a/spectractor/fit/fitter.py +++ b/spectractor/fit/fitter.py @@ -219,6 +219,24 @@ def __eq__(self, other): out *= getattr(self, key) == getattr(other, key) return out + def __repr__(self): + """Print the best fitting parameters on screen. + Labels are from self.labels. + + Examples + -------- + >>> parameters.VERBOSE = True + >>> params = FitParameters(values=[1, 2, 3, 4], labels=["x", "y", "z", "t"], fixed=[True, False, True, False]) + >>> params.cov = np.array([[1, -0.5], [-0.5, 4]]) + >>> params + x: 1.0 (fixed) + y: 2 +1 -1 bounds=[-inf, inf] + z: 3.0 (fixed) + t: 4 +2 -2 bounds=[-inf, inf] + + """ + return self.print_parameters_summary() + def get_index(self, label): """Get parameter index given its label. @@ -401,7 +419,7 @@ def get_fixed_parameters(self): return np.array(np.where(np.array(self.fixed).astype(int) == 1)[0]) def print_parameters_summary(self): - """Print the best fitting parameters on screen. + """Build a string with the best fitting parameters to display on screen. Labels are from self.labels. Returns @@ -424,12 +442,15 @@ def print_parameters_summary(self): txt += "%s: %s +%s -%s" % formatting_numbers(self.values[ip], np.sqrt(np.abs(self.cov[icov, icov])), np.sqrt(np.abs(self.cov[icov, icov])), label=self.labels[ip]) - txt += f" bounds={self.bounds[ip]}\n\t" + txt += f" bounds={self.bounds[ip]}" icov += 1 else: - txt += f"{self.labels[ip]}: {self.values[ip]} (fixed)\n\t" + txt += f"{self.labels[ip]}: {self.values[ip]} (fixed)" + if ip != self.ndim-1: + txt += "\n" return txt + def get_parameter(self, key): """Return a FitParameter instance. key argument can be the parameter label or its index value. @@ -666,6 +687,7 @@ def __init__(self, params=None, file_name="", verbose=False, plot=False, live_fi self.err = None self.data_cov = None self.W = None + self.W_before_mask = None self.x = None self.outliers = [] self.mask = [] @@ -686,22 +708,29 @@ def get_bad_indices(self): Examples -------- >>> w = FitWorkspace() + >>> w.data = np.array([1,2,3,4,5,6]) + >>> w.mask = [2, 4] + >>> w.outliers = [2, 6] + >>> w.get_bad_indices() + array([2, 4, 6]) >>> w.data = np.array([np.array([1,2,3]), np.array([1,2,3,4])], dtype=object) + >>> w.mask = [2, 4] >>> w.outliers = [2, 6] >>> w.get_bad_indices() - [array([2]), array([3])] + [array([2]), array([1, 3])] """ - bad_indices = np.asarray(self.outliers, dtype=int) + bad_indices = np.unique(np.concatenate([self.outliers, self.mask])).astype(int) if self.data.dtype == object: - if len(self.outliers) > 0: + if len(self.outliers) > 0 or len(self.mask) > 0: bad_indices = [] + bads = np.unique(np.concatenate([self.outliers, self.mask])).astype(int) start_index = 0 for k in range(self.data.shape[0]): mask = np.zeros(self.data[k].size, dtype=bool) - outliers = np.asarray(self.outliers)[np.logical_and(np.asarray(self.outliers) > start_index, - np.asarray(self.outliers) < start_index + + bad = np.asarray(bads)[np.logical_and(np.asarray(bads) > start_index, + np.asarray(bads) < start_index + self.data[k].size)] - mask[outliers - start_index] = True + mask[bad - start_index] = True bad_indices.append(np.arange(self.data[k].size)[mask]) start_index += self.data[k].size else: @@ -831,7 +860,8 @@ def weighted_residuals(self, p): # pragma: nocover def prepare_weight_matrices(self): r"""Compute weight matrix :math:`\mathbf{W}` `self.W` as the inverse of data covariance matrix `self.data_cov`. - Cancel weights of data outliers given by `self.outliers`. + Cancel weights of data outliers given by `self.outliers` or masked data given by `self.mask`. + It uses `self.W_before_mask` to reset the null weights at each computation. Examples -------- @@ -865,8 +895,8 @@ def prepare_weight_matrices(self): Use sparse matrix: - >>> w.W = scipy.sparse.diags(np.ones(3)) - >>> w.W.toarray() + >>> w.W_before_mask = scipy.sparse.diags(np.ones(3)) + >>> w.W_before_mask.toarray() array([[1., 0., 0.], [0., 1., 0.], [0., 0., 1.]]) @@ -878,29 +908,39 @@ def prepare_weight_matrices(self): [0., 1., 0.], [0., 0., 0.]]) + Add mask but no outliers on same matrix: + + >>> w.outliers = [] + >>> w.mask = np.array([1]) + >>> w.prepare_weight_matrices() + >>> w.W.toarray() + array([[1., 0., 0.], + [0., 0., 0.], + [0., 0., 1.]]) """ # Prepare covariance matrix for data if self.data_cov is None: self.data_cov = np.asarray(self.err.flatten() ** 2) # Prepare inverse covariance matrix for data - if self.W is None: + if self.W_before_mask is None: if self.data_cov.ndim == 1 and self.data_cov.dtype != object: - self.W = 1 / self.data_cov + self.W_before_mask = 1 / self.data_cov elif self.data_cov.ndim == 2 and self.data_cov.dtype != object: - self.W = np.linalg.inv(self.data_cov) + self.W_before_mask = np.linalg.inv(self.data_cov) elif self.data_cov.dtype is object: if self.data_cov[0].ndim == 1: - self.W = np.array([1 / self.data_cov[k] for k in range(self.data_cov.shape[0])]) + self.W_before_mask = np.array([1 / self.data_cov[k] for k in range(self.data_cov.shape[0])]) else: - self.W = [] + self.W_before_mask = [] for k in range(len(self.data_cov)): L = np.linalg.inv(np.linalg.cholesky(self.data_cov[k])) - self.W[k] = L.T @ L - self.W = np.asarray(self.W) - if len(self.outliers) > 0: + self.W_before_mask[k] = L.T @ L + self.W_before_mask = np.asarray(self.W_before_mask) + self.W = self.W_before_mask.copy() + if len(self.outliers) > 0 or len(self.mask) > 0: bad_indices = self.get_bad_indices() - if not scipy.sparse.issparse(self.W): + if not scipy.sparse.issparse(self.W_before_mask): if self.W.ndim == 1 and self.W.dtype != object: self.W[bad_indices] = 0 elif self.W.ndim == 2 and self.W.dtype != object: @@ -921,11 +961,15 @@ def prepare_weight_matrices(self): f"\nHere W type is {type(self.W)}, shape is {self.W.shape} and W is {self.W}.") else: format = self.W.getformat() - W = self.W.tocsr() - W[:, bad_indices] = 0 - W[bad_indices, :] = 0 - W.eliminate_zeros() - self.W = W.asformat(format=format) + if format == 'dia': + self.W.data[0, bad_indices] = 0 + else: + W = self.W.tolil() + W[:, bad_indices] = 0 + W[bad_indices, :] = 0 + W = self.W.asformat(format='csr') + W.eliminate_zeros() + self.W = W.asformat(format=format) def compute_W_with_model_error(self, model_err): """Propagate model uncertainties to weight matrix W. @@ -1006,13 +1050,13 @@ def compute_W_with_model_error(self, model_err): elif self.W.ndim == 2 and self.W.dtype != object: cov = self.data_cov + np.diag(model_err * model_err) self.W = np.linalg.inv(cov) - # needs to reapply the mask of outliers + # needs to reapply the mask of outliers and masked data self.W[zeros] = 0 else: cov = self.data_cov + np.diag(model_err * model_err) L = np.linalg.inv(np.linalg.cholesky(cov)) W = L.T @ L - # needs to reapply the mask of outliers + # needs to reapply the mask of outliers and masked data rows, cols = self.W.nonzero() self.W = scipy.sparse.csr_matrix((W[rows, cols], (rows, cols)), dtype=self.W.dtype, shape=self.W.shape) return self.W @@ -1287,7 +1331,7 @@ def gradient_descent(fit_workspace, epsilon, niter=10, xtol=1e-3, ftol=1e-3, wit ipar = np.delete(ipar, list(ipar).index(jp)) fit_workspace.params.fixed[jp] = True my_logger.warning( - f"\n\tStep {i}: {fit_workspace.params.labels[ip]} is degenerated with {fit_workspace.params.labels[jp]}; " + f"\n\tStep {i}: {fit_workspace.params.labels[jp]} is degenerated with {fit_workspace.params.labels[ip]}; " f"parameter {fit_workspace.params.labels[jp]} is fixed at its last known current value ({tmp_params[jp]}).") continue # remove fixed and degenerated parameters; then transpose @@ -1519,7 +1563,7 @@ def run_gradient_descent(fit_workspace, epsilon, xtol, ftol, niter, verbose=Fals fit_workspace.params_table = np.concatenate([fit_workspace.params_table, tmp_params_table]) fit_workspace.costs = np.concatenate([fit_workspace.costs, tmp_costs]) if verbose or fit_workspace.verbose: - fit_workspace.my_logger.info(f"\n\t{fit_workspace.params.print_parameters_summary()}") + fit_workspace.my_logger.info(f"\n{fit_workspace.params.print_parameters_summary()}") if parameters.DEBUG and (verbose or fit_workspace.verbose): fit_workspace.plot_gradient_descent() if len(fit_workspace.params.get_free_parameters()) > 1: @@ -1531,7 +1575,7 @@ def run_simple_newton_minimisation(fit_workspace, epsilon, xtol=1e-8, ftol=1e-8, epsilon, niter=niter, xtol=xtol, ftol=ftol) if verbose or fit_workspace.verbose: - fit_workspace.my_logger.info(f"\n\t{fit_workspace.params.print_parameters_summary()}") + fit_workspace.my_logger.info(f"\n{fit_workspace.params.print_parameters_summary()}") if parameters.DEBUG and (verbose or fit_workspace.verbose): fit_workspace.plot_gradient_descent() if len(fit_workspace.params.get_free_parameters()) > 1: diff --git a/spectractor/parameters.py b/spectractor/parameters.py index 6469ea505..3b7603a77 100644 --- a/spectractor/parameters.py +++ b/spectractor/parameters.py @@ -40,6 +40,7 @@ def __getattr__(name): SPECTRACTOR_FIT_TIMEOUT_PER_ITER = 600 # maximum time per gradient descent iteration before TimeoutError in seconds SPECTRACTOR_FIT_TIMEOUT = 3600 # maximum time per gradient descent before TimeoutError in seconds SPECTRACTOR_ATMOSPHERE_SIM = "none" # library to compute atmospheric transmission: none, libradtran, getobsatmo +SPECTRACTOR_SIMULATE_STARFIELD = False # simulate star field with Gaia catalog: False, True # Paths DISPERSER_DIR = "./extractor/dispersers/" @@ -113,6 +114,7 @@ def __getattr__(name): PSF_FIT_REG_PARAM = 0.01 # regularisation parameter for the chisq minimisation to extract the spectrum PSF_PIXEL_STEP_TRANSVERSE_FIT = 10 # step size in pixels for the first transverse PSF1D fit PSF_FWHM_CLIP = 2 # PSF is not evaluated outside a region larger than max(PIXWIDTH_SIGNAL, PSF_FWHM_CLIP*fwhm) pixels +PSF_POLY_TYPE = "polynomial" # polynomial type: must be polynomial or legendre # Detection line algorithm CALIB_BGD_ORDER = 3 # order of the background polynome to fit diff --git a/spectractor/simulation/AuxTelThroughput/SDSSg.txt b/spectractor/simulation/AuxTelThroughput/SDSSg.txt new file mode 100644 index 000000000..995cf6ead --- /dev/null +++ b/spectractor/simulation/AuxTelThroughput/SDSSg.txt @@ -0,0 +1,221 @@ +380 0.0000 +381 0.0000 +382 0.0000 +383 0.0000 +384 0.0000 +385 0.0000 +386 0.0000 +387 0.0000 +388 0.0000 +389 0.0000 +390 0.00005 +391 0.000149999999999999 +392 0.000599999999999999 +393 0.0027 +394 0.0249 +395 0.1686 +396 0.4554 +397 0.6898 +398 0.7937 +399 0.8518 +400 0.8893 +401 0.90645 +402 0.91595 +403 0.9241 +404 0.93125 +405 0.93795 +406 0.93915 +407 0.94105 +408 0.9456 +409 0.95105 +410 0.9532 +411 0.95715 +412 0.9597 +413 0.96175 +414 0.9605 +415 0.9611 +416 0.96505 +417 0.9713 +418 0.97295 +419 0.9717 +420 0.9714 +421 0.9745 +422 0.9758 +423 0.9711 +424 0.96195 +425 0.96105 +426 0.9665 +427 0.97565 +428 0.9812 +429 0.97955 +430 0.97655 +431 0.97665 +432 0.97865 +433 0.97795 +434 0.9756 +435 0.9718 +436 0.97215 +437 0.97775 +438 0.9837 +439 0.9861 +440 0.9858 +441 0.9833 +442 0.9828 +443 0.98345 +444 0.9853 +445 0.98515 +446 0.9839 +447 0.98385 +448 0.98445 +449 0.987 +450 0.9867 +451 0.9842 +452 0.97975 +453 0.9758 +454 0.97525 +455 0.9779 +456 0.98265 +457 0.98525 +458 0.9852 +459 0.98545 +460 0.9853 +461 0.9863 +462 0.9877 +463 0.988649999999999 +464 0.98705 +465 0.9837 +466 0.9818 +467 0.98225 +468 0.9848 +469 0.9873 +470 0.98885 +471 0.98775 +472 0.9839 +473 0.9806 +474 0.9792 +475 0.98035 +476 0.98205 +477 0.98335 +478 0.9833 +479 0.98355 +480 0.9826 +481 0.98295 +482 0.9856 +483 0.98925 +484 0.99005 +485 0.98845 +486 0.9826 +487 0.9784 +488 0.97425 +489 0.974599999999999 +490 0.9795 +491 0.98585 +492 0.99045 +493 0.9903 +494 0.98655 +495 0.9795 +496 0.9734 +497 0.97195 +498 0.97395 +499 0.97935 +500 0.9859 +501 0.9896 +502 0.9906 +503 0.9876 +504 0.9833 +505 0.9809 +506 0.98035 +507 0.98235 +508 0.98455 +509 0.98515 +510 0.98305 +511 0.97925 +512 0.97535 +513 0.97265 +514 0.9731 +515 0.97495 +516 0.9793 +517 0.98115 +518 0.9797 +519 0.9753 +520 0.96845 +521 0.9624 +522 0.95935 +523 0.9598 +524 0.96425 +525 0.9694 +526 0.9734 +527 0.97435 +528 0.9703 +529 0.9638 +530 0.95705 +531 0.95155 +532 0.9501 +533 0.95115 +534 0.95485 +535 0.9596 +536 0.9648 +537 0.9694 +538 0.97425 +539 0.97815 +540 0.98 +541 0.97815 +542 0.97005 +543 0.9588 +544 0.94475 +545 0.93505 +546 0.9309 +547 0.9338 +548 0.9316 +549 0.9093 +550 0.84955 +551 0.74365 +552 0.6038 +553 0.46095 +554 0.33455 +555 0.2317 +556 0.1552 +557 0.1012 +558 0.06525 +559 0.0419 +560 0.02715 +561 0.01795 +562 0.01205 +563 0.0084 +564 0.0061 +565 0.0046 +566 0.00354999999999999 +567 0.0028 +568 0.00225 +569 0.0018 +570 0.0015 +571 0.00119999999999999 +572 0.001 +573 0.0008 +574 0.000599999999999999 +575 0.00045 +576 0.00035 +577 0.000299999999999999 +578 0.0002 +579 0.0002 +580 0.000149999999999999 +581 0.0001 +582 0.0001 +583 0.00005 +584 0.00005 +585 0.00005 +586 0.00005 +587 0.00005 +588 0.0000 +589 0.00005 +590 0.0000 +591 0.00005 +592 0.0000 +593 0.0000 +594 0.0000 +595 0.0000 +596 0.0000 +597 0.0000 +598 0.0000 +599 0.0000 +600 0.0000 \ No newline at end of file diff --git a/spectractor/simulation/AuxTelThroughput/multispectra_holo4_003_HD142331_20230802_AuxTel_doGainsPTC_v3.0.3_throughput.txt b/spectractor/simulation/AuxTelThroughput/multispectra_holo4_003_HD142331_20230802_AuxTel_doGainsPTC_v3.0.3_throughput.txt index 01480e375..92f8f6131 100644 --- a/spectractor/simulation/AuxTelThroughput/multispectra_holo4_003_HD142331_20230802_AuxTel_doGainsPTC_v3.0.3_throughput.txt +++ b/spectractor/simulation/AuxTelThroughput/multispectra_holo4_003_HD142331_20230802_AuxTel_doGainsPTC_v3.0.3_throughput.txt @@ -1,83 +1,83 @@ -3.000000000000000000e+02 0.000000000000000000e+00 1.000000000000000021e-02 -3.010000000000000000e+02 0.000000000000000000e+00 1.000000000000000021e-02 -3.020000000000000000e+02 0.000000000000000000e+00 1.000000000000000021e-02 -3.030000000000000000e+02 0.000000000000000000e+00 1.000000000000000021e-02 -3.040000000000000000e+02 0.000000000000000000e+00 1.000000000000000021e-02 -3.050000000000000000e+02 0.000000000000000000e+00 1.000000000000000021e-02 -3.060000000000000000e+02 0.000000000000000000e+00 1.000000000000000021e-02 -3.070000000000000000e+02 0.000000000000000000e+00 1.000000000000000021e-02 -3.080000000000000000e+02 0.000000000000000000e+00 1.000000000000000021e-02 -3.090000000000000000e+02 0.000000000000000000e+00 1.000000000000000021e-02 -3.100000000000000000e+02 0.000000000000000000e+00 1.000000000000000021e-02 -3.110000000000000000e+02 0.000000000000000000e+00 1.000000000000000021e-02 -3.120000000000000000e+02 0.000000000000000000e+00 1.000000000000000021e-02 -3.130000000000000000e+02 0.000000000000000000e+00 1.000000000000000021e-02 -3.140000000000000000e+02 0.000000000000000000e+00 1.000000000000000021e-02 -3.150000000000000000e+02 0.000000000000000000e+00 1.000000000000000021e-02 -3.160000000000000000e+02 0.000000000000000000e+00 1.000000000000000021e-02 -3.170000000000000000e+02 0.000000000000000000e+00 1.000000000000000021e-02 -3.180000000000000000e+02 0.000000000000000000e+00 1.000000000000000021e-02 -3.190000000000000000e+02 0.000000000000000000e+00 1.000000000000000021e-02 -3.200000000000000000e+02 0.000000000000000000e+00 1.000000000000000021e-02 -3.210000000000000000e+02 0.000000000000000000e+00 1.000000000000000021e-02 -3.220000000000000000e+02 0.000000000000000000e+00 1.000000000000000021e-02 -3.230000000000000000e+02 0.000000000000000000e+00 1.000000000000000021e-02 -3.240000000000000000e+02 0.000000000000000000e+00 1.000000000000000021e-02 -3.250000000000000000e+02 0.000000000000000000e+00 1.000000000000000021e-02 -3.260000000000000000e+02 0.000000000000000000e+00 1.000000000000000021e-02 -3.270000000000000000e+02 0.000000000000000000e+00 1.000000000000000021e-02 -3.280000000000000000e+02 0.000000000000000000e+00 1.000000000000000021e-02 -3.290000000000000000e+02 0.000000000000000000e+00 1.000000000000000021e-02 -3.300000000000000000e+02 0.000000000000000000e+00 1.000000000000000021e-02 -3.310000000000000000e+02 0.000000000000000000e+00 1.000000000000000021e-02 -3.320000000000000000e+02 0.000000000000000000e+00 1.000000000000000021e-02 -3.330000000000000000e+02 0.000000000000000000e+00 1.000000000000000021e-02 -3.340000000000000000e+02 0.000000000000000000e+00 1.000000000000000021e-02 -3.350000000000000000e+02 0.000000000000000000e+00 1.000000000000000021e-02 -3.360000000000000000e+02 0.000000000000000000e+00 1.000000000000000021e-02 -3.370000000000000000e+02 0.000000000000000000e+00 1.000000000000000021e-02 -3.380000000000000000e+02 0.000000000000000000e+00 1.000000000000000021e-02 -3.390000000000000000e+02 0.000000000000000000e+00 1.000000000000000021e-02 -3.400000000000000000e+02 0.000000000000000000e+00 1.000000000000000021e-02 -3.410000000000000000e+02 0.000000000000000000e+00 1.000000000000000021e-02 -3.420000000000000000e+02 0.000000000000000000e+00 1.000000000000000021e-02 -3.430000000000000000e+02 0.000000000000000000e+00 1.000000000000000021e-02 -3.440000000000000000e+02 0.000000000000000000e+00 1.000000000000000021e-02 -3.450000000000000000e+02 0.000000000000000000e+00 1.000000000000000021e-02 -3.460000000000000000e+02 0.000000000000000000e+00 1.000000000000000021e-02 -3.470000000000000000e+02 0.000000000000000000e+00 1.000000000000000021e-02 -3.480000000000000000e+02 0.000000000000000000e+00 1.000000000000000021e-02 -3.490000000000000000e+02 0.000000000000000000e+00 1.000000000000000021e-02 -3.500000000000000000e+02 4.460543080675311023e-04 1.000000000000000021e-02 -3.510000000000000000e+02 5.127732532376337755e-03 1.000000000000000021e-02 -3.520000000000000000e+02 9.809410756685144409e-03 1.000000000000000021e-02 -3.530000000000000000e+02 1.449108898099395193e-02 1.000000000000000021e-02 -3.540000000000000000e+02 2.151360631745716928e-02 1.000000000000000021e-02 -3.550000000000000000e+02 2.853612365392038663e-02 1.000000000000000021e-02 -3.560000000000000000e+02 4.258115832684682134e-02 1.076978108162215649e-03 -3.570000000000000000e+02 5.662619299977324216e-02 1.000000000000000021e-02 -3.580000000000000000e+02 7.067122767269960748e-02 9.179710898409596063e-04 -3.590000000000000000e+02 8.458727746713645690e-02 1.000000000000000021e-02 -3.600000000000000000e+02 9.981309525069298472e-02 1.000000000000000021e-02 -3.610000000000000000e+02 1.159818086563590006e-01 1.000000000000000021e-02 -3.620000000000000000e+02 1.320523482528832560e-01 1.663011488662912915e-03 -3.630000000000000000e+02 1.476744926766204169e-01 1.000000000000000021e-02 -3.640000000000000000e+02 1.507394599221379972e-01 8.333343236250701294e-03 -3.650000000000000000e+02 1.538044271676555774e-01 6.666686472501400645e-03 -3.660000000000000000e+02 1.568693944131731577e-01 5.000029708752101731e-03 -3.670000000000000000e+02 1.599343616586907380e-01 3.333372945002801950e-03 -3.680000000000000000e+02 1.629993289042083182e-01 1.666716181253502602e-03 -3.690000000000000000e+02 1.783612927446105167e-01 1.870126998706461013e-03 -3.700000000000000000e+02 1.936064772326762939e-01 1.970150181592436340e-03 -3.710000000000000000e+02 2.081650200601536937e-01 2.119537801644612567e-03 -3.720000000000000000e+02 2.259372492357716034e-01 2.291670345302004863e-03 -3.730000000000000000e+02 2.425423740773889891e-01 2.455992604441717755e-03 -3.740000000000000000e+02 2.620251063350992338e-01 2.646727927819524529e-03 -3.750000000000000000e+02 2.815262246846203520e-01 2.844843184435932783e-03 -3.760000000000000000e+02 3.016515719597132605e-01 3.040447514683536183e-03 -3.770000000000000000e+02 3.179438795109302274e-01 3.206015471118409035e-03 -3.780000000000000000e+02 3.388975841081813822e-01 3.412701411070339849e-03 -3.790000000000000000e+02 3.466918843041088549e-01 3.487155017944860904e-03 +3.000000000000000000e+02 0.000000000000000000e+00 1.000000000000000000e+00 +3.010000000000000000e+02 0.000000000000000000e+00 1.000000000000000000e+00 +3.020000000000000000e+02 0.000000000000000000e+00 1.000000000000000000e+00 +3.030000000000000000e+02 0.000000000000000000e+00 1.000000000000000000e+00 +3.040000000000000000e+02 0.000000000000000000e+00 1.000000000000000000e+00 +3.050000000000000000e+02 0.000000000000000000e+00 1.000000000000000000e+00 +3.060000000000000000e+02 0.000000000000000000e+00 1.000000000000000000e+00 +3.070000000000000000e+02 0.000000000000000000e+00 1.000000000000000000e+00 +3.080000000000000000e+02 0.000000000000000000e+00 1.000000000000000000e+00 +3.090000000000000000e+02 0.000000000000000000e+00 1.000000000000000000e+00 +3.100000000000000000e+02 0.000000000000000000e+00 1.000000000000000000e+00 +3.110000000000000000e+02 0.000000000000000000e+00 1.000000000000000000e+00 +3.120000000000000000e+02 0.000000000000000000e+00 1.000000000000000000e+00 +3.130000000000000000e+02 0.000000000000000000e+00 1.000000000000000000e+00 +3.140000000000000000e+02 0.000000000000000000e+00 1.000000000000000000e+00 +3.150000000000000000e+02 0.000000000000000000e+00 1.000000000000000000e+00 +3.160000000000000000e+02 0.000000000000000000e+00 1.000000000000000000e+00 +3.170000000000000000e+02 0.000000000000000000e+00 1.000000000000000000e+00 +3.180000000000000000e+02 0.000000000000000000e+00 1.000000000000000000e+00 +3.190000000000000000e+02 0.000000000000000000e+00 1.000000000000000000e+00 +3.200000000000000000e+02 0.000000000000000000e+00 1.000000000000000000e+00 +3.210000000000000000e+02 0.000000000000000000e+00 1.000000000000000000e+00 +3.220000000000000000e+02 0.000000000000000000e+00 1.000000000000000000e+00 +3.230000000000000000e+02 0.000000000000000000e+00 1.000000000000000000e+00 +3.240000000000000000e+02 0.000000000000000000e+00 1.000000000000000000e+00 +3.250000000000000000e+02 0.000000000000000000e+00 1.000000000000000000e+00 +3.260000000000000000e+02 0.000000000000000000e+00 1.000000000000000000e+00 +3.270000000000000000e+02 0.000000000000000000e+00 1.000000000000000000e+00 +3.280000000000000000e+02 0.000000000000000000e+00 1.000000000000000000e+00 +3.290000000000000000e+02 0.000000000000000000e+00 1.000000000000000000e+00 +3.300000000000000000e+02 0.000000000000000000e+00 1.000000000000000000e+00 +3.310000000000000000e+02 0.000000000000000000e+00 1.000000000000000000e+00 +3.320000000000000000e+02 0.000000000000000000e+00 1.000000000000000000e+00 +3.330000000000000000e+02 0.000000000000000000e+00 1.000000000000000000e+00 +3.340000000000000000e+02 0.000000000000000000e+00 1.000000000000000000e+00 +3.350000000000000000e+02 0.000000000000000000e+00 1.000000000000000000e+00 +3.360000000000000000e+02 0.000000000000000000e+00 1.000000000000000000e+00 +3.370000000000000000e+02 0.000000000000000000e+00 1.000000000000000000e+00 +3.380000000000000000e+02 0.000000000000000000e+00 1.000000000000000000e+00 +3.390000000000000000e+02 0.000000000000000000e+00 1.000000000000000000e+00 +3.400000000000000000e+02 0.000000000000000000e+00 1.000000000000000000e+00 +3.410000000000000000e+02 0.000000000000000000e+00 1.000000000000000000e+00 +3.420000000000000000e+02 0.000000000000000000e+00 1.000000000000000000e+00 +3.430000000000000000e+02 0.000000000000000000e+00 1.000000000000000000e+00 +3.440000000000000000e+02 0.000000000000000000e+00 1.000000000000000000e+00 +3.450000000000000000e+02 0.000000000000000000e+00 1.000000000000000000e+00 +3.460000000000000000e+02 0.000000000000000000e+00 1.000000000000000000e+00 +3.470000000000000000e+02 0.000000000000000000e+00 1.000000000000000000e+00 +3.480000000000000000e+02 0.000000000000000000e+00 1.000000000000000000e+00 +3.490000000000000000e+02 0.000000000000000000e+00 1.000000000000000000e+00 +3.500000000000000000e+02 4.460543080675311023e-04 1.000000000000000000e+00 +3.510000000000000000e+02 5.127732532376337755e-03 1.000000000000000000e+00 +3.520000000000000000e+02 9.809410756685144409e-03 1.000000000000000000e+00 +3.530000000000000000e+02 1.449108898099395193e-02 1.000000000000000000e+00 +3.540000000000000000e+02 2.151360631745716928e-02 1.000000000000000000e+00 +3.550000000000000000e+02 2.853612365392038663e-02 1.000000000000000000e+00 +3.560000000000000000e+02 4.258115832684682134e-02 1.000000000000000000e+00 +3.570000000000000000e+02 5.662619299977324216e-02 1.000000000000000000e+00 +3.580000000000000000e+02 7.067122767269960748e-02 1.000000000000000000e+00 +3.590000000000000000e+02 8.458727746713645690e-02 1.000000000000000000e+00 +3.600000000000000000e+02 9.981309525069298472e-02 1.000000000000000000e+00 +3.610000000000000000e+02 1.159818086563590006e-01 1.000000000000000000e+00 +3.620000000000000000e+02 1.320523482528832560e-01 1.000000000000000000e+00 +3.630000000000000000e+02 1.476744926766204169e-01 1.000000000000000000e+00 +3.640000000000000000e+02 1.507394599221379972e-01 1.000000000000000000e+00 +3.650000000000000000e+02 1.538044271676555774e-01 1.000000000000000000e+00 +3.660000000000000000e+02 1.568693944131731577e-01 1.000000000000000000e+00 +3.670000000000000000e+02 1.599343616586907380e-01 1.000000000000000000e+00 +3.680000000000000000e+02 1.629993289042083182e-01 1.000000000000000000e+00 +3.690000000000000000e+02 1.783612927446105167e-01 1.000000000000000000e+00 +3.700000000000000000e+02 1.936064772326762939e-01 1.000000000000000000e+00 +3.710000000000000000e+02 2.081650200601536937e-01 1.000000000000000000e+00 +3.720000000000000000e+02 2.259372492357716034e-01 1.000000000000000000e+00 +3.730000000000000000e+02 2.425423740773889891e-01 1.000000000000000000e+00 +3.740000000000000000e+02 2.620251063350992338e-01 1.000000000000000000e+00 +3.750000000000000000e+02 2.815262246846203520e-01 1.000000000000000000e+00 +3.760000000000000000e+02 3.016515719597132605e-01 1.000000000000000000e+00 +3.770000000000000000e+02 3.179438795109302274e-01 1.000000000000000000e+00 +3.780000000000000000e+02 3.388975841081813822e-01 1.000000000000000000e+00 +3.790000000000000000e+02 3.466918843041088549e-01 1.000000000000000000e+00 3.800000000000000000e+02 3.537462102758726079e-01 3.575908857438699941e-03 3.810000000000000000e+02 3.604314183201944299e-01 3.651607519698463374e-03 3.820000000000000000e+02 3.681364447930130512e-01 3.714686331139742826e-03 @@ -699,102 +699,102 @@ 9.980000000000000000e+02 2.812373383558955386e-01 2.827643069676258596e-03 9.990000000000000000e+02 2.749788897718989933e-01 2.764330318055280636e-03 1.000000000000000000e+03 2.688198661347008800e-01 2.703798765187609768e-03 -1.001000000000000000e+03 2.626858331583472594e-01 2.642294925490960671e-03 -1.002000000000000000e+03 2.566380882610728720e-01 2.582674352689992743e-03 -1.003000000000000000e+03 2.506406642678879471e-01 2.523052630478435972e-03 -1.004000000000000000e+03 2.445805906376559147e-01 2.462670342248521327e-03 -1.005000000000000000e+03 2.384449151187563454e-01 2.402066659047045246e-03 -1.006000000000000000e+03 2.324181618625841272e-01 2.338632723353782032e-03 -1.007000000000000000e+03 2.263790747128379688e-01 2.278862670804639688e-03 -1.008000000000000000e+03 2.203749307534488555e-01 2.218035745811968319e-03 -1.009000000000000000e+03 2.144023626539646177e-01 2.159174455415866726e-03 -1.010000000000000000e+03 2.085083162517175626e-01 2.099530574967484707e-03 -1.011000000000000000e+03 2.027598266556651652e-01 2.042647505464125282e-03 -1.012000000000000000e+03 1.971316607775393526e-01 1.989290471299883997e-03 -1.013000000000000000e+03 1.915961281823060358e-01 1.934952990022929071e-03 -1.014000000000000000e+03 1.860896486576171516e-01 1.880464770718611204e-03 -1.015000000000000000e+03 1.806084251255839213e-01 1.826057556671594525e-03 -1.016000000000000000e+03 1.751840996217163549e-01 1.772766608616137794e-03 -1.017000000000000000e+03 1.699292533656071025e-01 1.720024025067603494e-03 -1.018000000000000000e+03 1.648253291334529913e-01 1.670169106422806542e-03 -1.019000000000000000e+03 1.599413311535699544e-01 1.620524357714481873e-03 -1.020000000000000000e+03 1.550995389730692731e-01 1.573670485639895155e-03 -1.021000000000000000e+03 1.501884077670336826e-01 1.524170542004606166e-03 -1.022000000000000000e+03 1.451769617188636563e-01 1.475043594854790309e-03 -1.023000000000000000e+03 1.400422500111145885e-01 1.424081586205500159e-03 -1.024000000000000000e+03 1.349361203646674001e-01 1.373436919252747287e-03 -1.025000000000000000e+03 1.299316336185109000e-01 1.324560078061857776e-03 -1.026000000000000000e+03 1.250822021568329667e-01 1.276046108168024098e-03 -1.027000000000000000e+03 1.203902626949029386e-01 1.230764779016065708e-03 -1.028000000000000000e+03 1.158435635843868411e-01 1.184273647097548298e-03 -1.029000000000000000e+03 1.113628634525782590e-01 1.148079837018516113e-03 -1.030000000000000000e+03 1.071331508999577159e-01 1.104077842662819914e-03 -1.031000000000000000e+03 1.030328734580701622e-01 1.069558316461686033e-03 -1.032000000000000000e+03 9.897703059925638813e-02 1.030711554635111186e-03 -1.033000000000000000e+03 9.502098388115687300e-02 9.967592639921547988e-04 -1.034000000000000000e+03 9.121032303002588049e-02 9.569960465470421507e-04 -1.035000000000000000e+03 8.758718231083717498e-02 9.236251748465754445e-04 -1.036000000000000000e+03 8.422038789529767699e-02 8.919992371290537880e-04 -1.037000000000000000e+03 8.114766280502058726e-02 8.613009439363004992e-04 -1.038000000000000000e+03 7.831952673163725120e-02 8.358958316476878007e-04 -1.039000000000000000e+03 7.564386588068071349e-02 7.968575400530856839e-04 -1.040000000000000000e+03 7.292613926279578607e-02 7.731060425568140508e-04 -1.041000000000000000e+03 7.016850977876504247e-02 7.446963329554155036e-04 -1.042000000000000000e+03 6.745740654215512389e-02 7.122153971857195188e-04 -1.043000000000000000e+03 6.495798992699892971e-02 6.947504519314385077e-04 -1.044000000000000000e+03 6.270525431671919447e-02 6.753775118836584076e-04 -1.045000000000000000e+03 6.066431717329990453e-02 6.559615538185594157e-04 -1.046000000000000000e+03 5.894564991770784995e-02 6.315141427348644129e-04 -1.047000000000000000e+03 5.746473567181502318e-02 6.297817567149599461e-04 -1.048000000000000000e+03 5.613709189995956528e-02 6.143078174291037065e-04 -1.049000000000000000e+03 5.498369486041716769e-02 6.021371346904693745e-04 -1.050000000000000000e+03 5.397177732146830192e-02 5.926933529180221025e-04 -1.051000000000000000e+03 5.280612241128356671e-02 6.143816255422037548e-04 -1.052000000000000000e+03 5.169321034488788547e-02 6.089535753514795351e-04 -1.053000000000000000e+03 5.064899427349616595e-02 5.897112727267215561e-04 -1.054000000000000000e+03 4.963468792895304321e-02 5.796219646114333717e-04 -1.055000000000000000e+03 4.874155299496014948e-02 5.475960922906729540e-04 -1.056000000000000000e+03 4.792922545752861807e-02 5.381912556774555911e-04 -1.057000000000000000e+03 4.715536370557339013e-02 5.287326911311681027e-04 -1.058000000000000000e+03 4.636232041424764166e-02 5.186969275864616565e-04 -1.059000000000000000e+03 4.555588605030019833e-02 5.361508561385514319e-04 -1.060000000000000000e+03 4.477065780367314729e-02 5.309154762718984065e-04 -1.061000000000000000e+03 4.402301902457297217e-02 4.989388995924729821e-04 -1.062000000000000000e+03 4.333220388136843626e-02 4.955957656644576588e-04 -1.063000000000000000e+03 4.280785989472904451e-02 4.925201621502814636e-04 -1.064000000000000000e+03 4.236036332700753720e-02 4.993465219291960558e-04 -1.065000000000000000e+03 4.198928768615071971e-02 5.131605353879616386e-04 -1.066000000000000000e+03 4.168687308875029113e-02 5.151988970972071983e-04 -1.067000000000000000e+03 4.128830020406685369e-02 4.947015081778467598e-04 -1.068000000000000000e+03 4.077523432980383750e-02 4.900586617293405155e-04 -1.069000000000000000e+03 4.017064276046052734e-02 4.800469433877069605e-04 -1.070000000000000000e+03 3.938520105824146189e-02 4.678362836705530960e-04 -1.071000000000000000e+03 3.860265371760809860e-02 4.721488869384776114e-04 -1.072000000000000000e+03 3.794444885152389174e-02 4.506952258253157299e-04 -1.073000000000000000e+03 3.745606571401392804e-02 4.514017268251912705e-04 -1.074000000000000000e+03 3.718445982832373209e-02 4.495596483287294439e-04 -1.075000000000000000e+03 3.690507733666610612e-02 4.490612658475153364e-04 -1.076000000000000000e+03 3.648760106433639877e-02 4.389242208124782612e-04 -1.077000000000000000e+03 3.612551329519327059e-02 4.385290842412436487e-04 -1.078000000000000000e+03 3.590296164655401578e-02 4.379362369103643625e-04 -1.079000000000000000e+03 3.596241610115500503e-02 4.453104997070488828e-04 -1.080000000000000000e+03 3.653693458020594587e-02 4.512004759485544565e-04 -1.081000000000000000e+03 3.652455959653668621e-02 4.553953438629825619e-04 -1.082000000000000000e+03 3.651218461286743350e-02 4.458842083632784696e-04 -1.083000000000000000e+03 3.649980962919818078e-02 4.570186605607101963e-04 -1.084000000000000000e+03 3.648743464552892807e-02 4.754696431392953573e-04 -1.085000000000000000e+03 3.647505966185967535e-02 4.535532179073188566e-04 -1.086000000000000000e+03 3.646268467819042264e-02 4.514732532388483267e-04 -1.087000000000000000e+03 3.645030969452116992e-02 4.471991029299272891e-04 -1.088000000000000000e+03 3.643793471085191721e-02 4.358203587333960819e-04 -1.089000000000000000e+03 3.642555972718266449e-02 4.149538629036672718e-04 -1.090000000000000000e+03 3.641318474351341178e-02 4.168680000230486006e-04 -1.091000000000000000e+03 0.000000000000000000e+00 1.000000000000000021e-02 -1.092000000000000000e+03 0.000000000000000000e+00 1.000000000000000021e-02 -1.093000000000000000e+03 0.000000000000000000e+00 1.000000000000000021e-02 -1.094000000000000000e+03 0.000000000000000000e+00 1.000000000000000021e-02 -1.095000000000000000e+03 0.000000000000000000e+00 1.000000000000000021e-02 -1.096000000000000000e+03 0.000000000000000000e+00 1.000000000000000021e-02 -1.097000000000000000e+03 0.000000000000000000e+00 1.000000000000000021e-02 -1.098000000000000000e+03 0.000000000000000000e+00 1.000000000000000021e-02 -1.099000000000000000e+03 0.000000000000000000e+00 1.000000000000000021e-02 +1.001000000000000000e+03 2.626858331583472594e-01 1.000000000000000000e+00 +1.002000000000000000e+03 2.566380882610728720e-01 1.000000000000000000e+00 +1.003000000000000000e+03 2.506406642678879471e-01 1.000000000000000000e+00 +1.004000000000000000e+03 2.445805906376559147e-01 1.000000000000000000e+00 +1.005000000000000000e+03 2.384449151187563454e-01 1.000000000000000000e+00 +1.006000000000000000e+03 2.324181618625841272e-01 1.000000000000000000e+00 +1.007000000000000000e+03 2.263790747128379688e-01 1.000000000000000000e+00 +1.008000000000000000e+03 2.203749307534488555e-01 1.000000000000000000e+00 +1.009000000000000000e+03 2.144023626539646177e-01 1.000000000000000000e+00 +1.010000000000000000e+03 2.085083162517175626e-01 1.000000000000000000e+00 +1.011000000000000000e+03 2.027598266556651652e-01 1.000000000000000000e+00 +1.012000000000000000e+03 1.971316607775393526e-01 1.000000000000000000e+00 +1.013000000000000000e+03 1.915961281823060358e-01 1.000000000000000000e+00 +1.014000000000000000e+03 1.860896486576171516e-01 1.000000000000000000e+00 +1.015000000000000000e+03 1.806084251255839213e-01 1.000000000000000000e+00 +1.016000000000000000e+03 1.751840996217163549e-01 1.000000000000000000e+00 +1.017000000000000000e+03 1.699292533656071025e-01 1.000000000000000000e+00 +1.018000000000000000e+03 1.648253291334529913e-01 1.000000000000000000e+00 +1.019000000000000000e+03 1.599413311535699544e-01 1.000000000000000000e+00 +1.020000000000000000e+03 1.550995389730692731e-01 1.000000000000000000e+00 +1.021000000000000000e+03 1.501884077670336826e-01 1.000000000000000000e+00 +1.022000000000000000e+03 1.451769617188636563e-01 1.000000000000000000e+00 +1.023000000000000000e+03 1.400422500111145885e-01 1.000000000000000000e+00 +1.024000000000000000e+03 1.349361203646674001e-01 1.000000000000000000e+00 +1.025000000000000000e+03 1.299316336185109000e-01 1.000000000000000000e+00 +1.026000000000000000e+03 1.250822021568329667e-01 1.000000000000000000e+00 +1.027000000000000000e+03 1.203902626949029386e-01 1.000000000000000000e+00 +1.028000000000000000e+03 1.158435635843868411e-01 1.000000000000000000e+00 +1.029000000000000000e+03 1.113628634525782590e-01 1.000000000000000000e+00 +1.030000000000000000e+03 1.071331508999577159e-01 1.000000000000000000e+00 +1.031000000000000000e+03 1.030328734580701622e-01 1.000000000000000000e+00 +1.032000000000000000e+03 9.897703059925638813e-02 1.000000000000000000e+00 +1.033000000000000000e+03 9.502098388115687300e-02 1.000000000000000000e+00 +1.034000000000000000e+03 9.121032303002588049e-02 1.000000000000000000e+00 +1.035000000000000000e+03 8.758718231083717498e-02 1.000000000000000000e+00 +1.036000000000000000e+03 8.422038789529767699e-02 1.000000000000000000e+00 +1.037000000000000000e+03 8.114766280502058726e-02 1.000000000000000000e+00 +1.038000000000000000e+03 7.831952673163725120e-02 1.000000000000000000e+00 +1.039000000000000000e+03 7.564386588068071349e-02 1.000000000000000000e+00 +1.040000000000000000e+03 7.292613926279578607e-02 1.000000000000000000e+00 +1.041000000000000000e+03 7.016850977876504247e-02 1.000000000000000000e+00 +1.042000000000000000e+03 6.745740654215512389e-02 1.000000000000000000e+00 +1.043000000000000000e+03 6.495798992699892971e-02 1.000000000000000000e+00 +1.044000000000000000e+03 6.270525431671919447e-02 1.000000000000000000e+00 +1.045000000000000000e+03 6.066431717329990453e-02 1.000000000000000000e+00 +1.046000000000000000e+03 5.894564991770784995e-02 1.000000000000000000e+00 +1.047000000000000000e+03 5.746473567181502318e-02 1.000000000000000000e+00 +1.048000000000000000e+03 5.613709189995956528e-02 1.000000000000000000e+00 +1.049000000000000000e+03 5.498369486041716769e-02 1.000000000000000000e+00 +1.050000000000000000e+03 5.397177732146830192e-02 1.000000000000000000e+00 +1.051000000000000000e+03 5.280612241128356671e-02 1.000000000000000000e+00 +1.052000000000000000e+03 5.169321034488788547e-02 1.000000000000000000e+00 +1.053000000000000000e+03 5.064899427349616595e-02 1.000000000000000000e+00 +1.054000000000000000e+03 4.963468792895304321e-02 1.000000000000000000e+00 +1.055000000000000000e+03 4.874155299496014948e-02 1.000000000000000000e+00 +1.056000000000000000e+03 4.792922545752861807e-02 1.000000000000000000e+00 +1.057000000000000000e+03 4.715536370557339013e-02 1.000000000000000000e+00 +1.058000000000000000e+03 4.636232041424764166e-02 1.000000000000000000e+00 +1.059000000000000000e+03 4.555588605030019833e-02 1.000000000000000000e+00 +1.060000000000000000e+03 4.477065780367314729e-02 1.000000000000000000e+00 +1.061000000000000000e+03 4.402301902457297217e-02 1.000000000000000000e+00 +1.062000000000000000e+03 4.333220388136843626e-02 1.000000000000000000e+00 +1.063000000000000000e+03 4.280785989472904451e-02 1.000000000000000000e+00 +1.064000000000000000e+03 4.236036332700753720e-02 1.000000000000000000e+00 +1.065000000000000000e+03 4.198928768615071971e-02 1.000000000000000000e+00 +1.066000000000000000e+03 4.168687308875029113e-02 1.000000000000000000e+00 +1.067000000000000000e+03 4.128830020406685369e-02 1.000000000000000000e+00 +1.068000000000000000e+03 4.077523432980383750e-02 1.000000000000000000e+00 +1.069000000000000000e+03 4.017064276046052734e-02 1.000000000000000000e+00 +1.070000000000000000e+03 3.938520105824146189e-02 1.000000000000000000e+00 +1.071000000000000000e+03 3.860265371760809860e-02 1.000000000000000000e+00 +1.072000000000000000e+03 3.794444885152389174e-02 1.000000000000000000e+00 +1.073000000000000000e+03 3.745606571401392804e-02 1.000000000000000000e+00 +1.074000000000000000e+03 3.718445982832373209e-02 1.000000000000000000e+00 +1.075000000000000000e+03 3.690507733666610612e-02 1.000000000000000000e+00 +1.076000000000000000e+03 3.648760106433639877e-02 1.000000000000000000e+00 +1.077000000000000000e+03 3.612551329519327059e-02 1.000000000000000000e+00 +1.078000000000000000e+03 3.590296164655401578e-02 1.000000000000000000e+00 +1.079000000000000000e+03 3.596241610115500503e-02 1.000000000000000000e+00 +1.080000000000000000e+03 3.653693458020594587e-02 1.000000000000000000e+00 +1.081000000000000000e+03 3.652455959653668621e-02 1.000000000000000000e+00 +1.082000000000000000e+03 3.651218461286743350e-02 1.000000000000000000e+00 +1.083000000000000000e+03 3.649980962919818078e-02 1.000000000000000000e+00 +1.084000000000000000e+03 3.648743464552892807e-02 1.000000000000000000e+00 +1.085000000000000000e+03 3.647505966185967535e-02 1.000000000000000000e+00 +1.086000000000000000e+03 3.646268467819042264e-02 1.000000000000000000e+00 +1.087000000000000000e+03 3.645030969452116992e-02 1.000000000000000000e+00 +1.088000000000000000e+03 3.643793471085191721e-02 1.000000000000000000e+00 +1.089000000000000000e+03 3.642555972718266449e-02 1.000000000000000000e+00 +1.090000000000000000e+03 3.641318474351341178e-02 1.000000000000000000e+00 +1.091000000000000000e+03 0.000000000000000000e+00 1.000000000000000000e+00 +1.092000000000000000e+03 0.000000000000000000e+00 1.000000000000000000e+00 +1.093000000000000000e+03 0.000000000000000000e+00 1.000000000000000000e+00 +1.094000000000000000e+03 0.000000000000000000e+00 1.000000000000000000e+00 +1.095000000000000000e+03 0.000000000000000000e+00 1.000000000000000000e+00 +1.096000000000000000e+03 0.000000000000000000e+00 1.000000000000000000e+00 +1.097000000000000000e+03 0.000000000000000000e+00 1.000000000000000000e+00 +1.098000000000000000e+03 0.000000000000000000e+00 1.000000000000000000e+00 +1.099000000000000000e+03 0.000000000000000000e+00 1.000000000000000000e+00 diff --git a/spectractor/simulation/image_simulation.py b/spectractor/simulation/image_simulation.py index 8db114bfe..dcdf1f5fd 100644 --- a/spectractor/simulation/image_simulation.py +++ b/spectractor/simulation/image_simulation.py @@ -1,6 +1,6 @@ from spectractor import parameters from spectractor.config import set_logger -from spectractor.tools import (pixel_rotation, set_wcs_file_name, set_sources_file_name, +from spectractor.tools import (rebin, pixel_rotation, set_wcs_file_name, set_sources_file_name, set_gaia_catalog_file_name, load_wcs_from_file, ensure_dir, plot_image_simple, iraf_source_detection) from spectractor.extractor.images import Image, find_target @@ -15,7 +15,8 @@ import astropy.units as units from astropy.coordinates import SkyCoord from astropy.table import Table -from scipy.signal import fftconvolve, gaussian +from scipy.signal import fftconvolve +from scipy.signal.windows import gaussian import matplotlib.pyplot as plt from matplotlib.ticker import MaxNLocator import numpy as np @@ -69,11 +70,10 @@ def __init__(self, centroid_coords, psf, amplitude): self.x0 = centroid_coords[0] self.y0 = centroid_coords[1] self.amplitude = amplitude - # self.target = target self.psf = copy.deepcopy(psf) self.psf.params.values[1] = self.x0 self.psf.params.values[2] = self.y0 - self.psf.params.values[0] = amplitude + self.psf.params.values[0] = self.amplitude # to be realistic, usually fitted fwhm is too big, divide gamma by 2 self.fwhm = self.psf.params.values[3] # self.sigma = self.model.stddev / 2 @@ -123,51 +123,62 @@ def __init__(self, base_image, flux_factor=1): def set_star_list(self): x0, y0 = self.image.target_pixcoords sources_file_name = set_sources_file_name(self.image.file_name) - if os.path.isfile(sources_file_name): + wcs_file_name = set_wcs_file_name(self.image.file_name) + gaia_catalog_file_name = set_gaia_catalog_file_name(self.image.file_name) + if os.path.isfile(wcs_file_name) and os.path.isfile(gaia_catalog_file_name): + # load gaia catalog + gaia_catalog = ascii.read(gaia_catalog_file_name, format="ecsv") + gaia_coord_after_motion = get_gaia_coords_after_proper_motion(gaia_catalog, self.image.date_obs) + # load WCS + wcs = load_wcs_from_file(wcs_file_name) + # catalog matching to set star positions using Gaia + target_coord = wcs.all_pix2world([x0 * parameters.CCD_REBIN], [y0 * parameters.CCD_REBIN], 0) + target_coord = SkyCoord(ra=target_coord[0] * units.deg, dec=target_coord[1] * units.deg, + frame="icrs", obstime=self.image.date_obs, equinox="J2000") + gaia_target_index, dist_2d, dist_3d = target_coord.match_to_catalog_sky(gaia_coord_after_motion) + dx, dy = 0, 0 + for gaia_i in range(len(gaia_catalog)): + x, y = np.array(wcs.all_world2pix(gaia_coord_after_motion[gaia_i].ra, + gaia_coord_after_motion[gaia_i].dec, 0)) / parameters.CCD_REBIN + if gaia_i == gaia_target_index[0]: + dx = x0 - x + dy = y0 - y + A = 10 ** (-gaia_catalog['phot_g_mean_mag'][gaia_i] / 2.5) + self.stars.append(StarModel([x, y], self.image.target_star2D, A)) + self.pixcoords.append([x, y]) + # rescale using target fitted amplitude + amplitudes = np.array([star.amplitude for star in self.stars]) + target_flux = self.image.target_star2D.params.values[0] + amplitudes *= target_flux / self.stars[gaia_target_index[0]].amplitude * self.flux_factor + for k, star in enumerate(self.stars): + star.amplitude = amplitudes[k] + # shift x,y star positions according to target position + star.x0 += dx + star.y0 += dy + star.psf.params.values[1] += dx + star.psf.params.values[2] += dy + star.psf.params.values[0] = amplitudes[k] + elif os.path.isfile(sources_file_name): # load sources positions and flux sources = Table.read(sources_file_name) sources['X'].name = "xcentroid" sources['Y'].name = "ycentroid" sources['FLUX'].name = "flux" - # test presence of WCS and gaia catalog files - wcs_file_name = set_wcs_file_name(self.image.file_name) - gaia_catalog_file_name = set_gaia_catalog_file_name(self.image.file_name) - if os.path.isfile(wcs_file_name) and os.path.isfile(gaia_catalog_file_name): - # load gaia catalog - gaia_catalog = ascii.read(gaia_catalog_file_name, format="ecsv") - gaia_coord_after_motion = get_gaia_coords_after_proper_motion(gaia_catalog, self.image.date_obs) - # load WCS - wcs = load_wcs_from_file(wcs_file_name) - # catalog matching to set star positions using Gaia - sources_coord = wcs.all_pix2world(sources['xcentroid'], sources['ycentroid'], 0) - sources_coord = SkyCoord(ra=sources_coord[0] * units.deg, dec=sources_coord[1] * units.deg, - frame="icrs", obstime=self.image.date_obs, equinox="J2000") - gaia_index, dist_2d, dist_3d = sources_coord.match_to_catalog_sky(gaia_coord_after_motion) - for k, gaia_i in enumerate(gaia_index): - x, y = wcs.all_world2pix(gaia_coord_after_motion[gaia_i].ra, gaia_coord_after_motion[gaia_i].dec, 0) - A = sources['flux'][k] * self.flux_factor - self.stars.append(StarModel([x, y], self.image.target_star2D, A)) - self.pixcoords.append([x, y]) - else: - for k, source in enumerate(sources): - x, y = sources['xcentroid'][k], sources['ycentroid'][k] - A = sources['flux'][k] * self.flux_factor - self.stars.append(StarModel([x, y], self.image.target_star2D, A)) - self.pixcoords.append([x, y]) + for k, source in enumerate(sources): + x, y = np.array([sources['xcentroid'][k], sources['ycentroid'][k]]) / parameters.CCD_REBIN + A = sources['flux'][k] * self.flux_factor + self.stars.append(StarModel([x, y], self.image.target_star2D, A)) + self.pixcoords.append([x, y]) else: + # try extraction using iraf source detection # mask background, faint stars, and saturated pixels data = np.copy(self.image.data) - # self.saturation = 0.99 * parameters.CCD_MAXADU / base_image.expo - # self.saturated_pixels = np.where(image_thresholded > self.saturation) - # image_thresholded[self.saturated_pixels] = 0. - # image_thresholded -= threshold - # image_thresholded[np.where(image_thresholded < 0)] = 0. # mask order0 and spectrum margin = 30 mask = np.zeros(data.shape, dtype=bool) for y in range(int(y0) - 100, int(y0) + 100): - for x in range(parameters.CCD_IMSIZE): - u, v = pixel_rotation(x, y, self.image.disperser.theta(x0, y0) * np.pi / 180., x0, y0) + for x in range(self.image.data.shape[1]): + u, v = pixel_rotation(x, y, self.image.disperser.theta([x0, y0]) * np.pi / 180., x0, y0) if margin > v > -margin: mask[y, x] = True # remove background and detect sources @@ -186,9 +197,9 @@ def model(self, x, y): self.field = self.stars[0].psf.evaluate(np.array([x, y])) for k in range(1, len(self.stars)): left = max(0, int(self.pixcoords[0][k]) - window) - right = min(parameters.CCD_IMSIZE, int(self.pixcoords[0][k]) + window) + right = min(np.max(x), int(self.pixcoords[0][k]) + window) low = max(0, int(self.pixcoords[1][k]) - window) - up = min(parameters.CCD_IMSIZE, int(self.pixcoords[1][k]) + window) + up = min(np.max(y), int(self.pixcoords[1][k]) + window) if up < low or left > right: continue yy, xx = np.mgrid[low:up, left:right] @@ -196,21 +207,8 @@ def model(self, x, y): return self.field def plot_model(self): - xx, yy = np.mgrid[0:parameters.CCD_IMSIZE:1, 0:parameters.CCD_IMSIZE:1] - starfield = self.model(xx, yy) fig, ax = plt.subplots(1, 1) - plot_image_simple(ax, starfield, scale="log10", target_pixcoords=self.pixcoords) - # im = plt.imshow(starfield, origin='lower', cmap='jet') - # ax.grid(color='white', ls='solid') - # ax.grid(True) - # ax.set_xlabel('X [pixels]') - # ax.set_ylabel('Y [pixels]') - # ax.set_title(f'Star field model: fwhm={self.fwhm.value:.2f}') - # cb = plt.colorbar(im, ax=ax) - # cb.formatter.set_powerlimits((0, 0)) - # cb.locator = MaxNLocator(7, prune=None) - # cb.update_ticks() - # cb.set_label('Arbitrary units') # ,fontsize=16) + plot_image_simple(ax, self.field, scale="log10", target_pixcoords=self.pixcoords) if parameters.DISPLAY: plt.show() if parameters.PdfPages: @@ -220,10 +218,12 @@ def plot_model(self): class BackgroundModel: """Class to model the background of the simulated image. - The background model size is set with the parameters.CCD_IMSIZE global keyword. - Attributes ---------- + Nx: int + Size of the background along X axis in pixels. + Ny: int + Size of the background along Y axis in pixels. level: float The mean level of the background in image units. frame: array_like @@ -231,13 +231,15 @@ class BackgroundModel: and the smoothing gaussian width (default: None). """ - def __init__(self, level, frame=None): + def __init__(self, Nx, Ny, level, frame=None): """Create a BackgroundModel instance. - The background model size is set with the parameters.CCD_IMSIZE global keyword. - Parameters ---------- + Nx: int + Size of the background along X axis in pixels. + Ny: int + Size of the background along Y axis in pixels. level: float The mean level of the background in image units. frame: array_like, None @@ -247,17 +249,19 @@ def __init__(self, level, frame=None): Examples -------- >>> from spectractor import parameters - >>> parameters.CCD_IMSIZE = 200 - >>> bgd = BackgroundModel(10) + >>> Nx, Ny = 200, 300 + >>> bgd = BackgroundModel(Nx, Ny, 10) >>> model = bgd.model() >>> np.all(model==10) True >>> model.shape (200, 200) - >>> bgd = BackgroundModel(10, frame=(160, 180, 3)) + >>> bgd = BackgroundModel(Nx, Ny, 10, frame=(160, 180, 3)) >>> bgd.plot_model() """ self.my_logger = set_logger(self.__class__.__name__) + self.Nx = Nx + self.Ny = Ny self.level = level if self.level <= 0: self.my_logger.warning('\n\tBackground level must be strictly positive.') @@ -269,7 +273,6 @@ def model(self): """Compute the background model for the image simulation in image units. A shadowing vignetting frame is roughly simulated if self.frame is set. - The background model size is set with the parameters.CCD_IMSIZE global keyword. Returns ------- @@ -277,7 +280,7 @@ def model(self): The array of the background model. """ - yy, xx = np.mgrid[0:parameters.CCD_IMSIZE:1, 0:parameters.CCD_IMSIZE:1] + xx, yy = np.mgrid[0:self.Ny:1, 0:self.Nx:1] bkgd = self.level * np.ones_like(xx) if self.frame is None: return bkgd @@ -285,9 +288,9 @@ def model(self): xlim, ylim, width = self.frame bkgd[ylim:, :] = self.level / 100 bkgd[:, xlim:] = self.level / 100 - kernel = np.outer(gaussian(parameters.CCD_IMSIZE, width), gaussian(parameters.CCD_IMSIZE, width)) + kernel = np.outer(gaussian(self.Nx, width), gaussian(self.Ny, width)) bkgd = fftconvolve(bkgd, kernel, mode='same') - bkgd *= self.level / bkgd[parameters.CCD_IMSIZE // 2, parameters.CCD_IMSIZE // 2] + bkgd *= self.level / bkgd[self.Ny // 2, self.Nx // 2] return bkgd def plot_model(self): @@ -313,6 +316,108 @@ def plot_model(self): parameters.PdfPages.savefig() +class FlatModel: + """Class to model the pixel flat of the simulated image. Flat is dimensionless and its average must be one. + + Attributes + ---------- + Nx: int + Size of the background along X axis in pixels. + Ny: int + Size of the background along Y axis in pixels. + gains: array_like + The list of gains to apply. The average must be one. + randomness_level: float + Level of random quantum efficiency to apply to pixels (default: 0.). + """ + + def __init__(self, Nx, Ny, gains, randomness_level=0.): + """Create a FlatModel instance. Flat is dimensionless and its average must be one. + + Parameters + ---------- + Nx: int + Size of the background along X axis in pixels. + Ny: int + Size of the background along Y axis in pixels. + gains: array_like + The list of gains to apply. The average must be one. + randomness_level: float + Level of random quantum efficiency to apply to pixels (default: 0.). + + Examples + -------- + >>> from spectractor import parameters + >>> Nx, Ny = 200, 300 + >>> flat = FlatModel(Nx, Ny, gains=[[1, 2, 3, 4], [4, 3, 2, 1]]) + >>> model = flat.model() + >>> print(f"{np.mean(model):.4f}") + 1.0000 + >>> model.shape + (200, 200) + >>> flat.plot_model() + """ + self.my_logger = set_logger(self.__class__.__name__) + self.Nx = Nx + self.Ny = Ny + self.gains = np.atleast_2d(gains).astype(float) + if len(self.gains) <= 0: + raise ValueError(f"Gains list is empty") + if np.any(self.gains <= 0): + raise ValueError(f"One the gain values is negative. Got {self.gains}.") + if np.mean(self.gains) != 1.: + self.my_logger.warning(f"\n\tGains list average is not one but {np.mean(self.gains)}. " + "I scaled them to have an average of one.") + self.gains /= np.mean(self.gains) + self.my_logger.warning(f'\n\tRelative gains are set to {self.gains}.') + self.randomness_level = randomness_level + + def model(self): + """Compute the flat model for the image simulation (no units). + + Returns + ------- + flat: array_like + The array of the flat model. + """ + yy, xx = np.mgrid[0:self.Nx:1, 0:self.Ny:1] + flat = np.ones_like(xx, dtype=float) + hflats = np.array_split(flat, self.gains.shape[0]) + for h in range(self.gains.shape[0]): + vflats = np.array_split(hflats[h].T, self.gains.shape[1]) + for v in range(self.gains.shape[1]): + vflats[v] *= self.gains[h,v] + hflats[h] = np.concatenate(vflats).T + flat = np.concatenate(hflats).T + if self.randomness_level != 0: + flat += np.random.uniform(-self.randomness_level, self.randomness_level, size=flat.shape) + + return flat + + def plot_model(self): + """Plot the flat model. + + """ + flat = self.model() + fig, ax = plt.subplots(1, 1) + im = plt.imshow(flat, origin='lower', cmap='jet') + ax.grid(color='white', ls='solid') + ax.grid(True) + ax.set_xlabel('X [pixels]') + ax.set_ylabel('Y [pixels]') + ax.set_title('Flat model') + cb = plt.colorbar(im, ax=ax) + cb.formatter.set_powerlimits((0, 0)) + cb.locator = MaxNLocator(7, prune=None) + cb.update_ticks() + cb.set_label('Dimensionless') # ,fontsize=16) + if parameters.DISPLAY: + plt.show() + if parameters.PdfPages: + parameters.PdfPages.savefig() + + + class ImageModel(Image): def __init__(self, filename, target_label=None): @@ -321,17 +426,27 @@ def __init__(self, filename, target_label=None): self.true_lambdas = None self.true_spectrum = None - def compute(self, star, background, spectrogram, starfield=None): + def compute(self, star, background, spectrogram, starfield=None, flat=None): yy, xx = np.mgrid[0:parameters.CCD_IMSIZE:1, 0:parameters.CCD_IMSIZE:1] - self.data = star.psf.evaluate(np.array([xx, yy])) + background.model() + if starfield is not None: + starfield_mod = starfield.model(xx, yy) + self.data = starfield_mod + self.starfield = np.copy(starfield_mod) + if parameters.DEBUG: + self.plot_image(scale='symlog', target_pixcoords=starfield.pixcoords) + starfield.plot_model() + else: + self.data = star.psf.evaluate(np.array([xx, yy])) + self.data += background.model() if spectrogram.full_image: - self.data[spectrogram.spectrogram_ymin:spectrogram.spectrogram_ymax, :] += spectrogram.spectrogram + self.data[spectrogram.spectrogram_ymin:spectrogram.spectrogram_ymax, :] += spectrogram.spectrogram_data else: self.data[spectrogram.spectrogram_ymin:spectrogram.spectrogram_ymax, - spectrogram.spectrogram_xmin:spectrogram.spectrogram_xmax] += spectrogram.spectrogram - # - spectrogram.spectrogram_bgd) - if starfield is not None: - self.data += starfield.model(xx, yy) + spectrogram.spectrogram_xmin:spectrogram.spectrogram_xmax] += spectrogram.spectrogram_data + if flat is not None: + flat_mod = flat.model() + self.data *= flat_mod + self.flat = flat_mod def add_poisson_and_read_out_noise(self): # pragma: no cover if self.units != 'ADU': @@ -366,8 +481,8 @@ def load_image(self, filename): # self.true_lambdas, self.true_spectrum = hdu_list[1].data -def ImageSim(image_filename, spectrum_filename, outputdir, pwv=5, ozone=300, aerosols=0.03, A1=1, A2=1, A3=1, angstrom_exponent=None, - psf_poly_params=None, psf_type=None, diffraction_orders=None, with_rotation=True, with_stars=True, with_adr=True, with_noise=True): +def ImageSim(image_filename, spectrum_filename, output_filename, pwv=5, ozone=300, aerosols=0.03, A1=1, A2=1, A3=1, angstrom_exponent=None, + psf_poly_params=None, psf_type=None, diffraction_orders=None, with_rotation=True, with_starfield=True, with_adr=True, with_noise=True, with_flat=True): """ The basic use of the extractor consists first to define: - the path to the fits image from which to extract the image, - the path of the output directory to save the extracted spectrum (created automatically if does not exist yet), @@ -382,17 +497,25 @@ def ImageSim(image_filename, spectrum_filename, outputdir, pwv=5, ozone=300, aer - with_rotation: rotate the spectrum according to the disperser characteristics (True by default) - with_stars: include stars in the image field (True by default) - with_adr: include ADR effect (True by default) + - with_flat: include flat (True by default) """ my_logger = set_logger(__name__) my_logger.info(f'\n\tStart IMAGE SIMULATOR') # Load reduced image spectrum = Spectrum(spectrum_filename) + parameters.CALLING_CODE = "" if diffraction_orders is None: diffraction_orders = np.arange(spectrum.order, spectrum.order + 3 * np.sign(spectrum.order), np.sign(spectrum.order)) image = ImageModel(image_filename, target_label=spectrum.target.label) guess = np.array([spectrum.header['TARGETX'], spectrum.header['TARGETY']]) - if "CCDREBIN" in spectrum.header: - guess *= spectrum.header["CCDREBIN"] + if parameters.CCD_REBIN != 1: + # these lines allow to simulate images using rebinned spectrum files + guess *= parameters.CCD_REBIN + new_shape = np.asarray((parameters.CCD_IMSIZE, parameters.CCD_IMSIZE)) + old_edge = parameters.CCD_IMSIZE * parameters.CCD_REBIN + image.gain = rebin(image.gain[:old_edge, :old_edge], new_shape, FLAG_MAKESUM=False) + image.read_out_noise = rebin(image.read_out_noise[:old_edge, :old_edge], new_shape, FLAG_MAKESUM=False) + if parameters.DEBUG: image.plot_image(scale='symlog', target_pixcoords=guess) # Fit the star 2D profile @@ -401,25 +524,31 @@ def ImageSim(image_filename, spectrum_filename, outputdir, pwv=5, ozone=300, aer # Background model my_logger.info('\n\tBackground model...') bgd_level = float(np.mean(spectrum.spectrogram_bgd)) - background = BackgroundModel(level=bgd_level, frame=None) # (1600, 1650, 100)) + background = BackgroundModel(parameters.CCD_IMSIZE, parameters.CCD_IMSIZE, level=bgd_level, frame=None) if parameters.DEBUG: background.plot_model() # Target model my_logger.info('\n\tStar model...') - # Spectrogram is simulated with spectrum.x0 target position: must be this position to simualte the target. - star = StarModel(image.target_pixcoords, image.target_star2D, image.target_star2D.params.values[0]) + # Spectrogram is simulated with spectrum.x0 target position: must be this position to simulate the target. + star = StarModel(np.array(image.target_pixcoords) / parameters.CCD_REBIN, image.target_star2D, image.target_star2D.params.values[0]) # reso = star.fwhm if parameters.DEBUG: star.plot_model() + # Star field model starfield = None - if with_stars: + if with_starfield: my_logger.info('\n\tStar field model...') - starfield = StarFieldModel(image) + starfield = StarFieldModel(image, flux_factor=1) + + # Flat model + flat = None + if with_flat: + my_logger.info('\n\tFlat model...') + flat = FlatModel(parameters.CCD_IMSIZE, parameters.CCD_IMSIZE, gains=[[1, 2, 3, 4], [4, 3, 2, 1]], randomness_level=1e-2) if parameters.DEBUG: - image.plot_image(scale='symlog', target_pixcoords=starfield.pixcoords) - starfield.plot_model() + flat.plot_model() # Spectrum model my_logger.info('\n\tSpectrum model...') @@ -455,14 +584,14 @@ def ImageSim(image_filename, spectrum_filename, outputdir, pwv=5, ozone=300, aer # Simulate spectrogram atmosphere = Atmosphere(airmass, pressure, temperature) - spectrogram = SpectrogramModel(spectrum, atmosphere=atmosphere, with_background=False, fast_sim=False, - full_image=True, with_adr=with_adr, diffraction_orders=diffraction_orders) + spectrogram = SpectrogramModel(spectrum, atmosphere=atmosphere, fast_sim=False, full_image=True, + with_adr=with_adr, diffraction_orders=diffraction_orders) spectrogram.simulate(A1, A2, A3, aerosols, angstrom_exponent, ozone, pwv, - spectrum.disperser.D, 0, 0, rotation_angle, 1, psf_poly_params) + spectrum.disperser.D, 0, 0, rotation_angle, psf_poly_params) # Image model my_logger.info('\n\tImage model...') - image.compute(star, background, spectrogram, starfield=starfield) + image.compute(star, background, spectrogram, starfield=starfield, flat=flat) # Recover true spectrum spectrogram.set_true_spectrum(spectrogram.lambdas, aerosols, ozone, pwv, shift_t=0) @@ -470,11 +599,11 @@ def ImageSim(image_filename, spectrum_filename, outputdir, pwv=5, ozone=300, aer true_spectrum = np.copy(spectrogram.true_spectrum) # Saturation effects - saturated_pixels = np.where(spectrogram.spectrogram > image.saturation)[0] + saturated_pixels = np.where(spectrogram.spectrogram_data > image.saturation)[0] if len(saturated_pixels) > 0: my_logger.warning(f"\n\t{len(saturated_pixels)} saturated pixels detected above saturation " f"level at {image.saturation} ADU/s in the spectrogram." - f"\n\tSpectrogram maximum is at {np.max(spectrogram.spectrogram)} ADU/s.") + f"\n\tSpectrogram maximum is at {np.max(spectrogram.spectrogram_data)} ADU/s.") image.data[image.data > image.saturation] = image.saturation # Convert data from ADU/s in ADU @@ -486,6 +615,8 @@ def ImageSim(image_filename, spectrum_filename, outputdir, pwv=5, ozone=300, aer # Round float ADU into closest integers # image.data = np.around(image.data) + if parameters.OBS_NAME == "AUXTEL": + image.data = image.data.T[::-1, ::-1] # Plot if parameters.VERBOSE and parameters.DISPLAY: # pragma: no cover @@ -493,12 +624,6 @@ def ImageSim(image_filename, spectrum_filename, outputdir, pwv=5, ozone=300, aer image.plot_image(scale="symlog", title="Image simulation", target_pixcoords=target_pixcoords, units=image.units) image.convert_to_ADU_units() - # Set output path - ensure_dir(outputdir) - output_filename = image_filename.split('/')[-1] - output_filename = (output_filename.replace('reduc', 'sim')).replace('trim', 'sim') - output_filename = os.path.join(outputdir, output_filename) - # Save images and parameters image.header['A1_T'] = A1 image.header['A2_T'] = A2 @@ -511,16 +636,16 @@ def ImageSim(image_filename, spectrum_filename, outputdir, pwv=5, ozone=300, aer image.header['VAOD_T'] = aerosols image.header['ROT_T'] = rotation_angle image.header['ROTATION'] = int(with_rotation) - image.header['STARS'] = int(with_stars) + image.header['STARS'] = int(with_starfield) image.header['BKGD_LEV'] = background.level image.header['PSF_DEG'] = spectrogram.chromatic_psf.deg image.header['PSF_TYPE'] = parameters.PSF_TYPE psf_poly_params_truth = np.array(psf_poly_params) if psf_poly_params_truth.size > spectrum.spectrogram_Nx: psf_poly_params_truth = psf_poly_params_truth[spectrum.spectrogram_Nx:] - image.header['LBDAS_T'] = np.array_str(true_lambdas, max_line_width=1000000, precision=2) - image.header['AMPLIS_T'] = np.array_str(true_spectrum, max_line_width=1000000, precision=2) - image.header['PSF_P_T'] = np.array_str(psf_poly_params_truth, max_line_width=1000000, precision=4) + image.header['LBDAS_T'] = str(np.round(true_lambdas, decimals=2).tolist()) + image.header['AMPLIS_T'] = str(true_spectrum.tolist()) + image.header['PSF_P_T'] = str(psf_poly_params_truth.tolist()) image.save_image(output_filename, overwrite=True) return image diff --git a/spectractor/simulation/simulator.py b/spectractor/simulation/simulator.py index c7a9b4a3f..4a1c718cd 100644 --- a/spectractor/simulation/simulator.py +++ b/spectractor/simulation/simulator.py @@ -100,7 +100,7 @@ def simulate_without_atmosphere(self, lambdas): return self.data, self.err def simulate(self, A1=1.0, A2=0., aerosols=0.05, angstrom_exponent=None, ozone=300, pwv=5, reso=0., - D=parameters.DISTANCE2CCD, shift_x=0., B=0.): + D=parameters.DISTANCE2CCD, shift_x=0.): """Simulate the cross spectrum of an object and its uncertainties after its transmission throught the instrument and the atmosphere. @@ -125,8 +125,6 @@ def simulate(self, A1=1.0, A2=0., aerosols=0.05, angstrom_exponent=None, ozone=3 Distance between the CCD and the disperser in mm (default: parameters.DISTANCE2CCD) shift_x: float Shift in pixels of the order 0 position estimate (default: 0). - B: float - Amplitude level for the background (default: 0). Returns ------- @@ -143,7 +141,7 @@ def simulate(self, A1=1.0, A2=0., aerosols=0.05, angstrom_exponent=None, ozone=3 >>> atmosphere = AtmosphereGrid(atmgrid_filename="./tests/data/reduc_20170530_134_atmsim.fits") >>> sim = SpectrumSimulation(spectrum, atmosphere=atmosphere, fast_sim=True) >>> lambdas, model, model_err = sim.simulate(A1=1, A2=1, ozone=300, pwv=5, aerosols=0.05, reso=0., - ... D=parameters.DISTANCE2CCD, shift_x=0., B=0.) + ... D=parameters.DISTANCE2CCD, shift_x=0.) >>> sim.plot_spectrum() .. doctest:: @@ -205,8 +203,6 @@ def integrand(lbda): self.data = (sim_conv(lambdas) + A2 * spectrum_order2) / lambdas self.data_order2 = A2 * spectrum_order2 / lambdas self.err = (err_conv(lambdas) + A2 * err_order2) / lambdas - if B != 0: - self.data += B / (lambdas * np.gradient(lambdas)) if np.any(self.err <= 0) and not np.all(self.err<=0): min_positive = np.min(self.err[self.err > 0]) self.err[np.isclose(self.err, 0., atol=0.01 * min_positive)] = min_positive @@ -226,7 +222,7 @@ def integrand(lbda): class SpectrogramModel(Spectrum): def __init__(self, spectrum, target=None, disperser=None, throughput=None, atmosphere=None, diffraction_orders=None, - with_background=True, fast_sim=True, full_image=False, with_adr=True): + fast_sim=True, full_image=False, with_adr=True): """Class to simulate a spectrogram. Parameters @@ -243,8 +239,6 @@ def __init__(self, spectrum, target=None, disperser=None, throughput=None, atmos Atmosphere or AtmosphereGrid instance to make the atmospheric simulation (default: None). diffraction_orders: array_like, optional List of diffraction orders to simulate. If None, takes first three (default: None). - with_background: bool, optional - If True, add the background model to the simulated spectrogram (default: True). fast_sim: bool, optional If True, perform a fast simulation of the spectrum without integrated the spectrum in pixel bins (default: True). @@ -258,7 +252,7 @@ def __init__(self, spectrum, target=None, disperser=None, throughput=None, atmos -------- >>> spectrum = Spectrum("./tests/data/reduc_20170530_134_spectrum.fits") >>> atmosphere = Atmosphere(airmass=1.2, pressure=800, temperature=10) - >>> sim = SpectrogramModel(spectrum, atmosphere=atmosphere, with_background=True, fast_sim=True) + >>> sim = SpectrogramModel(spectrum, atmosphere=atmosphere, fast_sim=True) """ Spectrum.__init__(self) if diffraction_orders is None: @@ -321,7 +315,6 @@ def __init__(self, spectrum, target=None, disperser=None, throughput=None, atmos self.fix_atm_sim = False self.atmosphere_sim = None self.fast_sim = fast_sim - self.with_background = with_background self.full_image = full_image self.with_adr = with_adr if self.full_image: @@ -395,7 +388,7 @@ def integrand(lbda): return spectrum, spectrum_err def simulate(self, A1=1.0, A2=0., A3=0., aerosols=0.05, angstrom_exponent=None, ozone=300, pwv=5, - D=parameters.DISTANCE2CCD, shift_x=0., shift_y=0., angle=0., B=1., psf_poly_params=None): + D=parameters.DISTANCE2CCD, shift_x=0., shift_y=0., angle=0., psf_poly_params=None): """ Parameters @@ -423,8 +416,6 @@ def simulate(self, A1=1.0, A2=0., A3=0., aerosols=0.05, angstrom_exponent=None, Shift in pixels along y axis of the order 0 position estimate (default: 0). angle: float Angle of the dispersion axis in degree (default: 0). - B: float - Amplitude level for the background (default: 0). psf_poly_params: array_like Polynomial parameters describing the PSF dependence in wavelength (default: None). @@ -443,7 +434,7 @@ def simulate(self, A1=1.0, A2=0., A3=0., aerosols=0.05, angstrom_exponent=None, >>> spec.disperser.ratio_ratio_order_3over2 = lambda lbda: 0.1 >>> psf_poly_params = list(spec.chromatic_psf.from_table_to_poly_params()) * 3 >>> atmosphere = Atmosphere(airmass=1.2, pressure=800, temperature=10) - >>> sim = SpectrogramModel(spec, atmosphere=atmosphere, with_background=True, fast_sim=True) + >>> sim = SpectrogramModel(spec, atmosphere=atmosphere, fast_sim=True) >>> lambdas, model, model_err = sim.simulate(A2=1, angle=-1.5, psf_poly_params=psf_poly_params) >>> sim.plot_spectrogram() @@ -522,11 +513,9 @@ def simulate(self, A1=1.0, A2=0., A3=0., aerosols=0.05, angstrom_exponent=None, self.profile_params[order][:, 0] = spec # self.spectrogram is in ADU/s units here - self.spectrogram = A1 * ima + self.spectrogram_data = A1 * ima self.spectrogram_err = A1 * np.sqrt(ima_err2) - if self.with_background: - self.spectrogram += B * self.spectrogram_bgd # Save the simulation parameters self.psf_poly_params = np.copy(poly_params[0]) self.header['OZONE_T'] = ozone @@ -540,7 +529,7 @@ def simulate(self, A1=1.0, A2=0., A3=0., aerosols=0.05, angstrom_exponent=None, self.header['Y0_T'] = shift_y self.header['ROTANGLE'] = angle - return self.lambdas, self.spectrogram, self.spectrogram_err + return self.lambdas, self.spectrogram_data, self.spectrogram_err if __name__ == "__main__": diff --git a/spectractor/tools.py b/spectractor/tools.py index d3b89ccb8..02d2ad894 100644 --- a/spectractor/tools.py +++ b/spectractor/tools.py @@ -1,4 +1,5 @@ import os +import copy import shutil from photutils.detection import IRAFStarFinder from scipy.optimize import curve_fit @@ -8,6 +9,7 @@ from astropy.io import fits from astropy import wcs as WCS +from matplotlib import cm import matplotlib.pyplot as plt import matplotlib.colors from matplotlib.ticker import MaxNLocator @@ -270,7 +272,7 @@ def rescale_x_from_legendre(x_norm, Xmin, Xmax): Parameters ---------- - x: np.ndarray + x_norm: np.ndarray Xmin: float Xmax: float @@ -1726,7 +1728,7 @@ def clean_target_spikes(data, saturation): # pragma: no cover return data -def plot_image_simple(ax, data, scale="lin", title="", units="Image units", cmap=None, +def plot_image_simple(ax, data, scale="lin", title="", units="Image units", cmap=None, mask=None, target_pixcoords=None, vmin=None, vmax=None, aspect=None, cax=None): """Simple function to plot a spectrum with error bars and labels. @@ -1744,6 +1746,8 @@ def plot_image_simple(ax, data, scale="lin", title="", units="Image units", cmap Units of the image to be written in the color bar label (default: "Image units") cmap: colormap Color map label (default: None) + mask: array_like + Mask array (default: None) target_pixcoords: array_like, optional 2D array giving the (x,y) coordinates of the targets on the image: add a scatter plot (default: None) vmin: float @@ -1771,6 +1775,18 @@ def plot_image_simple(ax, data, scale="lin", title="", units="Image units", cmap ... title="tests/data/reduc_20170605_028.fits") >>> if parameters.DISPLAY: plt.show() """ + if cmap is not None and isinstance(cmap, str): + colormap = copy.copy(cm.get_cmap(cmap)) + elif isinstance(cmap, matplotlib.colors.Colormap): + colormap = cmap + else: + colormap = copy.copy(cm.get_cmap('viridis')) + cmap_nan = copy.copy(colormap) + cmap_nan.set_bad(color='lightgrey') + + data = np.copy(data) + if mask is not None: + data[mask] = np.nan if scale == "log" or scale == "log10": # removes the zeros and negative pixels first zeros = np.where(data <= 0) @@ -1784,7 +1800,7 @@ def plot_image_simple(ax, data, scale="lin", title="", units="Image units", cmap norm = matplotlib.colors.SymLogNorm(vmin=vmin, vmax=vmax, linthresh=10, base=10) else: norm = matplotlib.colors.Normalize(vmin=vmin, vmax=vmax) - im = ax.imshow(data, origin='lower', cmap=cmap, norm=norm, aspect=aspect) + im = ax.imshow(data, origin='lower', cmap=cmap, norm=norm, aspect=aspect, interpolation="none") ax.grid(color='silver', ls='solid') ax.grid(True) ax.set_xlabel(parameters.PLOT_XLABEL) @@ -1800,7 +1816,7 @@ def plot_image_simple(ax, data, scale="lin", title="", units="Image units", cmap if title != "": ax.set_title(title) if target_pixcoords is not None: - ax.scatter(target_pixcoords[0], target_pixcoords[1], marker='o', s=100, edgecolors='k', facecolors='none', + ax.scatter(target_pixcoords[0], target_pixcoords[1], marker='o', s=100, edgecolors='r', facecolors='none', label='Target', linewidth=2) diff --git a/tests/data/reduc_20170530_134_wcs/reduc_20170530_134_gaia.ecsv b/tests/data/reduc_20170530_134_wcs/reduc_20170530_134_gaia.ecsv new file mode 100644 index 000000000..d3848e1ac --- /dev/null +++ b/tests/data/reduc_20170530_134_wcs/reduc_20170530_134_gaia.ecsv @@ -0,0 +1,180 @@ +# %ECSV 1.0 +# --- +# datatype: +# - name: ra +# unit: deg +# datatype: float64 +# description: Right ascension +# meta: !!omap +# - {ucd: pos.eq.ra;meta.main} +# - {utype: Char.SpatialAxis.Coverage.Location.Coord.Position2D.Value2.C1} +# - name: dec +# unit: deg +# datatype: float64 +# description: Declination +# meta: !!omap +# - {ucd: pos.eq.dec;meta.main} +# - {utype: Char.SpatialAxis.Coverage.Location.Coord.Position2D.Value2.C2} +# - name: pmra +# unit: mas / yr +# datatype: float64 +# description: Proper motion in right ascension direction +# meta: !!omap +# - {ucd: pos.pm;pos.eq.ra} +# - name: pmdec +# unit: mas / yr +# datatype: float64 +# description: Proper motion in declination direction +# meta: !!omap +# - {ucd: pos.pm;pos.eq.dec} +# - name: ref_epoch +# unit: yr +# datatype: float64 +# description: Reference epoch +# meta: !!omap +# - {ucd: meta.ref;time.epoch} +# - name: parallax +# unit: mas +# datatype: float64 +# description: Parallax +# meta: !!omap +# - {ucd: pos.parallax} +# - name: phot_g_mean_mag +# unit: mag +# datatype: float32 +# description: G-band mean magnitude +# meta: !!omap +# - {ucd: phot.mag;stat.mean;em.opt} +# - {name: dist, datatype: float64} +# schema: astropy-2.0 +ra dec pmra pmdec ref_epoch parallax phot_g_mean_mag dist +193.31387874127503 -18.52522966943086 314.6217104148161 -802.7940081262793 2015.5 10.952603073572996 11.850179 0.003194503077334316 +193.31408002656195 -18.525652464350433 299.48903077653887 -796.0918271978387 2015.5 12.925448038432572 8.209325 0.0036572194992613833 +193.3277945272934 -18.51814688394671 -5.160688804105089 -1.14750264511897 2015.5 1.0688747619611119 19.440645 0.014856773289668808 +193.3204468220089 -18.50884073371206 -10.682364603936644 3.2097113709856444 2015.5 -0.0694777743150532 17.879246 0.015256268583383152 +193.3040125259853 -18.50927392586909 -11.427188237352146 0.5699115873427919 2015.5 0.10802389415888732 20.819374 0.01536534889835026 +193.3157394183568 -18.537629646356873 5.8144923359535134 -11.052391369410625 2015.5 1.7119929585735418 19.119549 0.015664910778359787 +193.29617831112887 -18.528615059374513 -31.696126246519107 -4.70913052839484 2015.5 1.720546752840018 19.287481 0.016943230165895606 +193.32737740917463 -18.532134915027743 -12.082740620346542 -0.7558372784127914 2015.5 0.43928834587071036 19.431416 0.017061152151825246 +193.3097396900157 -18.501509382686073 -19.168150326342403 9.221302373174847 2015.5 1.431036176223781 20.081364 0.020910630442809715 +193.31539418930976 -18.497549321035812 -2.6199018306752353 -2.3145552734671337 2015.5 0.41014208072796726 18.762243 0.024806798409123216 +193.3032847361622 -18.499023939385406 24.649227785555613 -20.481895967993694 2015.5 3.8916123975959076 18.201487 0.02487132967479237 +193.30858653779057 -18.54797389015663 -6.595876065039609 0.28142358292914493 2015.5 0.9895469503815828 20.598286 0.026044684383603103 +193.30970726860335 -18.496122689087873 -9.515909114958472 -18.071671618565425 2015.5 0.6321948998346161 17.669962 0.026261103390160648 +193.28932201859828 -18.536556572024647 -2.0109487629633476 -1.5103820905474827 2015.5 1.2768604475432879 20.57137 0.026417449258433354 +193.34019980738998 -18.517446113856916 -9.872288371001845 -0.7764269730320621 2015.5 0.2978591332523562 16.403965 0.026483518523732052 +193.30515802414263 -18.547835692288228 0.051216598504189026 -3.762493890154479 2015.5 -0.45839166775664525 19.045279 0.026595648310797384 +193.3223765417061 -18.547747801687624 "" "" 2015.5 "" 20.08203 0.027110588433522372 +193.2912522639206 -18.540765296724448 -7.201886333740895 -8.337250629410883 2015.5 1.301048795195839 15.39927 0.027537552190521387 +193.2968959184522 -18.49684165208324 -8.903935163024627 -6.3889874365702015 2015.5 -0.1447436783319508 19.167841 0.029492917659330115 +193.3422578627708 -18.532670090311566 -14.12998057808509 -6.5866462780425055 2015.5 0.5629848034343903 20.495178 0.029882797357607346 +193.34150680485675 -18.538590395559364 -19.655325533213052 -13.655913900666137 2015.5 2.6064756538197633 20.438272 0.031816470871387406 +193.34850074415692 -18.523685148937787 -1.6949458762500034 -10.70348640867291 2015.5 0.10321164991768625 19.081028 0.03395018114998625 +193.2760239774249 -18.51841354894035 -4.804930918057392 -3.9781042330896703 2015.5 -0.2904115355408065 19.073843 0.03501219315746438 +193.28158431842976 -18.50255387370315 -18.366004582612995 7.671362827510471 2015.5 -0.6267297869547805 19.606089 0.03548554782449654 +193.30042865592898 -18.48844424919503 -0.9840456976868367 -6.21908767222436 2015.5 0.544974839605643 18.035854 0.03573971959352718 +193.29610740357413 -18.555687172577745 -24.425084211028608 -3.303634021118067 2015.5 -1.7476770541361897 20.20495 0.03698544489856827 +193.30526231006476 -18.485628188903462 "" "" 2015.5 "" 21.384804 0.0372774383993838 +193.3125778926402 -18.48249728710623 -8.694595847243399 1.385804527181762 2015.5 1.0301235642606748 19.302637 0.039729990869435364 +193.34675284640363 -18.496980313980707 -3.0900555825713782 2.2850099710650755 2015.5 0.45613185443777127 16.694885 0.040967831959646935 +193.2717375844366 -18.50445002084672 -19.57249524325576 -0.3548836171101366 2015.5 0.7950063399211105 17.203684 0.04274213112411268 +193.3569047764256 -18.532881104634455 -6.422258536058061 -1.453111133839209 2015.5 -0.2663779384228213 18.698923 0.04322013548249458 +193.2833157042159 -18.48858836641649 0.3060973626544119 -3.1044536189374132 2015.5 0.4378343134876523 20.287819 0.04369823208866542 +193.3341752926928 -18.48251119808841 0.5918590632584885 -21.190231203705697 2015.5 2.392970657314053 19.490725 0.04462038857446248 +193.34258452145735 -18.48729218239866 6.877210302811914 -14.55832976577129 2015.5 1.7490732964229587 17.355742 0.04496686788671832 +193.2686399734325 -18.505424390305336 -9.623707637718237 -1.8451185081669865 2015.5 0.9372076642842796 19.048332 0.04505729677837554 +193.32298678488038 -18.567674671255205 -22.85430541406342 -8.832210093309333 2015.5 0.10000654073020168 20.750092 0.04647656973362755 +193.34304543584827 -18.4851732399555 -19.806709408565446 3.546394341822805 2015.5 3.211855506995056 16.59929 0.04689893131240749 +193.34279583580093 -18.484793595387043 -23.583022954090946 4.959201549954996 2015.5 4.077412845117796 18.917725 0.047055674370844146 +193.2618691150194 -18.52473016475954 -9.754860055965692 -8.42317301181425 2015.5 0.15646640968258646 15.913697 0.04828972149714924 +193.35271768338865 -18.552229702512157 -0.49539382554123734 -3.314737796846325 2015.5 1.1260708933804089 20.068752 0.04834920446629307 +193.35321594820257 -18.492654701003378 -3.8319273114758325 -4.9038525825038874 2015.5 0.31598306328150066 17.041807 0.04846200178059192 +193.27163849353528 -18.49312532299253 -8.193279947653968 -7.961657658560421 2015.5 0.37332829768651604 19.686077 0.048633227076299336 +193.29477631334734 -18.568161983256594 -15.817072760619082 2.3055226084191625 2015.5 1.4175494765638903 20.0301 0.048986830411314575 +193.3514851556911 -18.555136634884562 -12.306382207978471 -5.520114916197348 2015.5 0.5872520384019237 19.990967 0.04932806922476461 +193.3591631639113 -18.545189257151016 -5.140904622415734 0.37990909082765933 2015.5 0.5620991680378893 19.772348 0.04965447088505243 +193.2637826053216 -18.54075935897978 0.5860331940430004 -0.16723092858737693 2015.5 -0.9974952174488456 19.595648 0.04997173967846638 +193.26209749749935 -18.538260978549157 2.6294058676578427 -5.446665774274372 2015.5 1.567546532121662 20.90238 0.050613214960639946 +193.31306860517319 -18.57677594250233 -9.150754811865975 -5.447445203427211 2015.5 -0.8637274969543044 20.36047 0.05454987358261117 +193.29481509868873 -18.469547038814103 "" "" 2015.5 "" 20.613518 0.05535146946955866 +193.2980674560779 -18.575823399508252 -13.412138363360619 -11.6064805381313 2015.5 1.39023120984776 17.04831 0.055369424961944476 +193.28609113393253 -18.571914706728922 "" "" 2015.5 "" 20.445902 0.05573722593642022 +193.283774679821 -18.570995167416843 -7.529259203061585 5.8047784692052815 2015.5 1.092669503312204 20.265375 0.05596297825987852 +193.30205850701685 -18.577646395683804 -7.907447889070238 -9.50318616332535 2015.5 0.7354816189217039 16.601625 0.05633505876680276 +193.25436458859113 -18.53369384027024 -11.416100478607238 -5.150776118074804 2015.5 -1.9241383998470587 20.572058 0.05651462913087596 +193.25371212996365 -18.51386611119541 4.528639709865158 -4.1788382545531135 2015.5 -0.18362838495214068 19.69459 0.05658211724128889 +193.34065319027115 -18.57262420284615 "" "" 2015.5 "" 20.581701 0.056927592225123363 +193.30276134556442 -18.466070484379408 -9.44321532264481 -1.9418241550984645 2015.5 0.30382808228549923 17.73599 0.056946549748764404 +193.33873018898043 -18.47060145504552 -6.374149326725131 -0.7835088899204141 2015.5 0.1004016261450385 20.182205 0.057212143163595866 +193.25467147893045 -18.50560184137736 -15.702984745165136 1.279477693828889 2015.5 1.3371201105743395 20.17862 0.05750816277500755 +193.3342384784335 -18.46836257170362 -15.32865745479114 -0.8710087778766653 2015.5 0.29256838655871165 19.4277 0.05759762671783454 +193.34222817236105 -18.573074187545593 2.8452049082725384 6.676492075064564 2015.5 1.5769169219410797 18.820784 0.05803100566646977 +193.27126246628632 -18.47946128757159 "" "" 2015.5 "" 21.113806 0.058096718840600275 +193.25261284519547 -18.50900318480033 -5.155072036948111 -4.542833831673805 2015.5 0.8886920949483617 20.344685 0.058517892575201014 +193.33544940357737 -18.57706659483904 -0.6860107178277368 -3.2704890395934614 2015.5 0.9253762319834703 17.72585 0.058918260765823675 +193.24973844760063 -18.529800194628383 -30.34130309536305 -3.1075262633766885 2015.5 6.294050243038902 20.516384 0.06020435477223766 +193.29785518540132 -18.46264197881629 -0.34828176087469 -4.673549189975991 2015.5 0.8477690569142541 20.485212 0.06123189606235932 +193.375111034307 -18.505483410845102 -8.667074894504264 -2.694940586990444 2015.5 0.7332990091094694 16.846233 0.06147778895105242 +193.28621533637823 -18.46591655374091 17.443905989507584 -16.505656189372605 2015.5 -0.5736526229568147 20.450089 0.06166927058633878 +193.24960760345002 -18.507243771917214 "" "" 2015.5 "" 20.104843 0.06170102590328457 +193.28988151047383 -18.46382527402963 -1.9073374332883801 -1.5827137390309807 2015.5 -0.8043879192178933 20.12438 0.062291602655783214 +193.2469988845399 -18.51515447029254 -6.161133802988571 0.7878531458191129 2015.5 0.2651593008351387 17.734467 0.06272640130412929 +193.35493042703303 -18.570998906783192 "" "" 2015.5 "" 20.8295 0.06308320125724055 +193.29368547688426 -18.461015438748337 -13.947906479028818 5.4653806166192 2015.5 0.915546282384468 19.056154 0.06382025269891257 +193.37937014908488 -18.513228305237387 -3.831219046440603 -0.5032772748107259 2015.5 0.8688091376652296 16.348978 0.06382856019230403 +193.2512016656803 -18.495980555655017 -21.805006594952072 -12.225023056278541 2015.5 2.115739429912935 16.847715 0.06397623537806946 +193.37658568389594 -18.501420198791124 -5.226799142241804 -11.236494624169072 2015.5 0.6953628927772167 15.534013 0.06402788079422662 +193.30849509913517 -18.587381767844917 -28.799370957427232 -0.8154468233607778 2015.5 3.4178796268780407 20.111591 0.06527825191023817 +193.37499837687892 -18.494010798154143 -14.159337535984113 2.6009045873191265 2015.5 0.31274536409548503 18.89604 0.06544411294049797 +193.32809408938647 -18.45835016260978 -34.08463716026513 -24.167733022930076 2015.5 0.77142691664275 20.232376 0.06551793284735445 +193.3096284156054 -18.5880834015776 -25.891579504080926 -4.196176757475371 2015.5 1.7894205118036695 20.0816 0.06592193733570205 +193.34522515843062 -18.580784661518887 3.594764212604222 -9.878614270933955 2015.5 1.3197229921128455 20.332003 0.06616735016257408 +193.26991463672894 -18.469899492300957 -20.08120431870621 5.635056742369507 2015.5 0.5926951076747647 17.821411 0.06623247405205199 +193.28101694260533 -18.462630973288196 -3.1888703432485626 2.1081366218847117 2015.5 0.040028465766947026 17.129591 0.06675446694159952 +193.30138393500658 -18.456253814724647 -11.284005821463047 -5.461925195340669 2015.5 -1.1918735472069983 15.436011 0.06684478609385924 +193.30162429555799 -18.45616285515967 "" "" 2015.5 "" 17.693565 0.06689829805953086 +193.36981780814375 -18.482107926832665 -26.276296993679672 -6.300519282382787 2015.5 -0.020274356980310444 18.006039 0.06738312599631312 +193.26114429157016 -18.56863216007125 -9.73605309971682 -3.5491817322255126 2015.5 0.12007337022076488 18.691391 0.06741819731841249 +193.344042613359 -18.582770727950066 -0.5175584180357036 -4.101695889465862 2015.5 -0.16573890237061104 20.267782 0.06743019281457185 +193.2472418271921 -18.54901489098607 -4.513881481753824 -3.7662245531134024 2015.5 0.54740893136138 18.91358 0.06762207079097611 +193.36626131364773 -18.476173935961125 -8.333138871412189 8.171234216263926 2015.5 1.1527188296928303 18.383675 0.06854279492863287 +193.34440237896092 -18.58387975850099 -4.142844410482176 -2.989704585005237 2015.5 0.1048097386670374 20.59729 0.06857631736133162 +193.35549745512537 -18.579451774202692 -3.4190461629226556 -13.781916544970036 2015.5 -0.20369669806691604 17.47182 0.07013337588095457 +193.38776703543675 -18.528123059158876 -8.82377931273977 -0.809102492977574 2015.5 0.7490962409236632 19.99619 0.0713939656181207 +193.30158617011193 -18.593426343253103 -21.65528734437662 12.92639251127718 2015.5 1.9846991821343603 15.727292 0.07197864423362826 +193.23822281914894 -18.507754254579254 -6.750761179795323 -2.5928290844030495 2015.5 -1.7908303649137223 20.859224 0.07211673140170481 +193.25785512751654 -18.470879182106952 "" "" 2015.5 "" 21.156693 0.07310718420607737 +193.36738415662515 -18.47060502096567 -10.761214240600998 1.600032433416448 2015.5 0.6134282356903833 16.520748 0.07315322725846632 +193.23590076531767 -18.514110048704758 -3.0417370645502713 -34.31821410738064 2015.5 2.4249011649068946 18.112406 0.07330088693070919 +193.38743253613785 -18.502823510580765 "" "" 2015.5 "" 21.234129 0.07344753918765257 +193.3352327092996 -18.451930356556993 -9.664531425290205 0.7920909938626207 2015.5 -0.017911985632117426 18.785091 0.0734651510525724 +193.30239416609896 -18.59543665934755 -8.803103293228064 -2.8686956325166038 2015.5 -0.16924535671699395 19.039885 0.07386227723775582 +193.293191532436 -18.59383137163806 -9.23463458031917 3.4400547139186957 2015.5 0.437154672477869 17.129267 0.07396095689270266 +193.37856063775897 -18.561946558783088 -9.772939207489415 -5.034248292150143 2015.5 0.0435123192778215 19.555023 0.07398119886520084 +193.37433302035652 -18.4765080403008 -19.939487789276754 -6.716930766952941 2015.5 1.07471699208673 19.420132 0.07418379633694194 +193.38375695586316 -18.490830480505036 -5.961246545338723 1.6414756005751654 2015.5 0.7654989078390342 20.352316 0.0743132342895139 +193.26335137259463 -18.46452325209116 -0.1908388761602607 -0.7869383222076025 2015.5 4.248256677931948 18.283983 0.07431383395696717 +193.2446818940562 -18.55960935467553 -1.8259120118508299 -5.415296855498066 2015.5 2.327088350577277 18.95821 0.07456291200536323 +193.3834332660322 -18.555491497270783 -10.725587657106095 1.6936358838037404 2015.5 0.49652811092113025 19.699902 0.07483505076451395 +193.26585457635323 -18.583356768952168 2.3072808314013526 -6.732274562401316 2015.5 1.3190399740554706 19.950048 0.07557511813718185 +193.36582353406882 -18.57921214466769 -18.58758787589614 -7.615454882707199 2015.5 1.6924212280780095 20.661837 0.07603305415529674 +193.3688835706723 -18.46746006472781 -5.7111505651657195 -3.0246890029142306 2015.5 0.495592301311842 19.389353 0.07639020547448523 +193.30665558276095 -18.598516562998206 "" "" 2015.5 "" 20.945768 0.07650647702477237 +193.23225740726016 -18.516043751429343 -26.374100025071275 6.555866792701145 2015.5 0.7243670794431314 18.013857 0.07655448733016727 +193.37653698342294 -18.569318926718957 0.6923834115575546 -1.586481566637147 2015.5 0.700506934145352 18.444387 0.0766632162322302 +193.2756085635824 -18.590631100664567 28.947070945170385 0.8876871442011489 2015.5 3.130041880077366 14.860598 0.07692515354578484 +193.30665417587446 -18.59912680263045 "" "" 2015.5 "" 21.056816 0.0771150988093329 +193.3055767219674 -18.59920574421312 0.07439785230487614 -0.19018106873930551 2015.5 -0.07072094853772486 18.32928 0.07727673021266655 +193.37196190904143 -18.57591454001483 "" "" 2015.5 "" 20.857197 0.07769075260536432 +193.3946295038761 -18.5192269563226 -1.924764446585279 -1.4540518250901335 2015.5 0.19506612065574874 18.271738 0.07771691826647817 +193.36901330067244 -18.579279301406782 -17.272164245842397 -14.827587841290185 2015.5 0.7161140420299488 16.9933 0.07811698518989549 +193.25637401253093 -18.465081904173267 -32.907144790357684 -21.470481648218463 2015.5 2.3864712321203156 17.34522 0.07824245788216501 +193.3181928064275 -18.44404585181748 -7.783309717287271 -4.47623780579611 2015.5 0.8962538646133067 19.137789 0.07835272871334766 +193.24058884395225 -18.483362203481086 -1.9070370655365945 -8.08575324871106 2015.5 0.590797755483222 17.736132 0.07867987721903368 +193.27476446297698 -18.592240440320758 -3.2565233792382755 -13.297345090038661 2015.5 0.43123534773967526 17.336054 0.07872222008736775 +193.23001246193613 -18.529178742640546 -3.002400192394866 2.255418217988204 2015.5 -0.1033811580843624 20.16529 0.07873753711760782 +193.33743246447423 -18.44505620618127 -55.706141698607 -6.191137634338219 2015.5 2.496840558748934 19.590519 0.08064904187481035 +193.31322158138576 -18.44091880091281 0.18174750032041165 -3.26959977306105 2015.5 2.3060617984903686 20.844696 0.08130956276854712 +193.23710737382063 -18.560939973450257 -1.5646251500176827 -8.511980955639956 2015.5 0.24152735423363764 17.793322 0.08148022725943328 +193.39145532275825 -18.559288538955506 "" "" 2015.5 "" 20.340668 0.08333519002760909 +193.39229056976905 -18.486686577393655 -12.554875369825231 6.313919829469455 2015.5 0.46760227460443793 20.865679 0.08340011389002859 diff --git a/tests/test_fullchain.py b/tests/test_fullchain.py index ac9d3b586..980e67464 100644 --- a/tests/test_fullchain.py +++ b/tests/test_fullchain.py @@ -6,7 +6,7 @@ from spectractor import parameters # noqa: E402 from spectractor.extractor.images import Image # noqa: E402 from spectractor.extractor.spectrum import Spectrum # noqa: E402 -from spectractor.extractor.extractor import Spectractor # noqa: E402 +from spectractor.extractor.extractor import SpectractorRun, SpectractorInit # noqa: E402 from spectractor.logbook import LogBook # noqa: E402 from spectractor.config import load_config, apply_rebinning_to_parameters # noqa: E402 from spectractor.simulation.image_simulation import ImageSim # noqa: E402 @@ -26,9 +26,16 @@ PSF_POLY_ORDER = 2 PSF_POLY_PARAMS_TRUTH = [1, 0, 0, 0, 0, 0, - 3, 1, 1, + 3, 0, 0, 3, 0, 0, 1e6] * N_DIFF_ORDERS + +PSF_POLY_PARAMS_AUXTEL_TRUTH = [1, 0, 0, + 0, 0, 0, + 8, 0, 0, + 3, 0, 0, + 1e6] * N_DIFF_ORDERS + A1_T = 1 A2_T = 1 A3_T = 0 @@ -48,7 +55,7 @@ def plot_residuals(spectrum, lambdas_truth, amplitude_truth): Parameters ---------- - spectrum + spectrum: Spectrum lambdas_truth amplitude_truth @@ -58,8 +65,8 @@ def plot_residuals(spectrum, lambdas_truth, amplitude_truth): >>> from spectractor.extractor.spectrum import Spectrum >>> image = Image("./tests/data/sim_20170530_134.fits") >>> spectrum = Spectrum("./tests/data/sim_20170530_134_spectrum.fits") - >>> lambdas_truth = np.fromstring(image.header['LBDAS_T'][1:-1], sep=' ') - >>> amplitude_truth = np.fromstring(image.header['AMPLIS_T'][1:-1], sep=' ', dtype=float)[:lambdas_truth.size] + >>> lambdas_truth = np.fromstring(image.header['LBDAS_T'][1:-1], sep=',') + >>> amplitude_truth = np.fromstring(image.header['AMPLIS_T'][1:-1], sep=',', dtype=float)[:lambdas_truth.size] >>> plot_residuals(spectrum, lambdas_truth, amplitude_truth) #doctest: +ELLIPSIS array([... """ @@ -94,32 +101,50 @@ def plot_residuals(spectrum, lambdas_truth, amplitude_truth): def make_image(): spectrum_filename = "./tests/data/reduc_20170530_134_spectrum.fits" image_filename = "./tests/data/reduc_20170530_134.fits" - ImageSim(image_filename, spectrum_filename, "./tests/data/", A1=A1_T, A2=A2_T, A3=A3_T, - psf_poly_params=PSF_POLY_PARAMS_TRUTH, with_stars=False, with_rotation=True, with_noise=False) + sim = ImageSim(image_filename, spectrum_filename, "./tests/data/sim_20170530_134.fits", A1=A1_T, A2=A2_T, A3=A3_T, + psf_poly_params=PSF_POLY_PARAMS_TRUTH, with_starfield=True, with_rotation=True, with_noise=False, + with_flat=True) + return sim + + +def make_auxtel_image(): + spectrum_filename = "./tests/data/test_auxtel_spectrum.fits" + image_filename = "./tests/data/exposure_2023092800266_dmpostisrccd.fits" + sim = ImageSim(image_filename, spectrum_filename, "./tests/data/", A1=A1_T, A2=A2_T, A3=A3_T, + psf_poly_params=PSF_POLY_PARAMS_AUXTEL_TRUTH, with_starfield=False, with_rotation=True, + with_noise=False, with_flat=False) + return sim + + +def make_stardice_image(): + spectrum_filename = "./tests/data/IMG_0019584_spectrum.fits" + image_filename = "./tests/data/IMG_0019584.fits" + ImageSim(image_filename, spectrum_filename, "./tests/data/IMG_0019584_sim.fits", A1=A1_T, A2=A2_T, A3=A3_T, + psf_poly_params=PSF_POLY_PARAMS_TRUTH, with_starfield=False, with_rotation=True, with_noise=False, with_flat=False) @unittest.skipIf(uvspec_available() is False, 'Skipping to avoid libradtran dependency') @astropy.config.set_temp_cache(os.path.join(os.path.abspath(os.path.dirname(__file__)), "data", "cache")) def test_ctio_fullchain(): parameters.VERBOSE = True - parameters.DEBUG = False + parameters.DEBUG = True parameters.SPECTRACTOR_ATMOSPHERE_SIM = "libradtran" - sim_image = "./tests/data/sim_20170530_134.fits" + sim_image_filename = "./tests/data/sim_20170530_134.fits" # load test and make image simulation - if not os.path.isfile(sim_image): - make_image() - image = Image(sim_image, config="./config/ctio.ini") - lambdas_truth = np.fromstring(image.header['LBDAS_T'][1:-1], sep=' ') - amplitude_truth = np.fromstring(image.header['AMPLIS_T'][1:-1], sep=' ', dtype=float) + # if not os.path.isfile(sim_image_filename): + sim = make_image() + image = Image(sim_image_filename, config="./config/ctio.ini") + lambdas_truth = np.fromstring(image.header['LBDAS_T'][1:-1], sep=',') + amplitude_truth = np.fromstring(image.header['AMPLIS_T'][1:-1], sep=',', dtype=float) parameters.AMPLITUDE_TRUTH = np.copy(amplitude_truth) parameters.LAMBDA_TRUTH = np.copy(lambdas_truth) # extractor - tag = os.path.basename(sim_image) + tag = os.path.basename(sim_image_filename) tag = tag.replace('sim_', 'reduc_') logbook = LogBook(logbook="./tests/data/ctiofulllogbook_jun2017_v5.csv") - disperser_label, target, xpos, ypos = logbook.search_for_image(tag) + disperser_label, target_label, xpos, ypos = logbook.search_for_image(tag) load_config("./config/ctio.ini") parameters.SPECTRACTOR_ATMOSPHERE_SIM = "libradtran" parameters.PSF_POLY_ORDER = PSF_POLY_ORDER @@ -130,8 +155,16 @@ def test_ctio_fullchain(): if parameters.CCD_REBIN > 1: for k in range(2 * (PSF_POLY_ORDER + 1), 3 * (PSF_POLY_ORDER +1)): PSF_POLY_PARAMS_TRUTH[k] /= parameters.CCD_REBIN - spectrum = Spectractor(sim_image, "./tests/data", guess=[xpos, ypos], target_label=target, - disperser_label=disperser_label, config="") # config already loaded, do not overwrite PSF_POLY_ORDER + + image = SpectractorInit(sim_image_filename, target_label=target_label, + disperser_label=disperser_label, config="") # config already loaded, do not overwrite PSF_POLY_ORDER + image.flat = sim.flat + image.starfield = sim.starfield + image.mask = np.zeros_like(image.data).astype(bool) + image.mask[680:685, 1255:1260] = True # test masking of some pixels like cosmic rays + parameters.SPECTRACTOR_SIMULATE_STARFIELD = False # here we want to test fit with an exact starfield simulation + spectrum, w = SpectractorRun(image, guess=[xpos, ypos], output_directory="./tests/data") + # tests residuals = plot_residuals(spectrum, lambdas_truth, amplitude_truth) @@ -168,7 +201,7 @@ def test_ctio_fullchain(): spectrum_file_name = "./tests/data/sim_20170530_134_spectrum.fits" assert os.path.isfile(spectrum_file_name) - atmgrid_filename = sim_image.replace('sim', 'reduc').replace('.fits', '_atmsim.fits') + atmgrid_filename = sim_image_filename.replace('sim', 'reduc').replace('.fits', '_atmsim.fits') assert os.path.isfile(atmgrid_filename) spectrum = Spectrum(spectrum_file_name) w = SpectrumFitWorkspace(spectrum, atmgrid_file_name=atmgrid_filename, fit_angstrom_exponent=False, @@ -200,7 +233,7 @@ def test_ctio_fullchain(): nsigma = 2 labels = ["A1_T", "A2_T", "VAOD_T", "OZONE_T", "PWV_T"] indices = [0, 1, 3, 5, 6] - A1, A2, A3, aerosols, angstrom_exponent, ozone, pwv, D, shift_x, shift_y, shift_t, B, *psf_poly_params = w.params.values + A1, A2, A3, aerosols, angstrom_exponent, ozone, pwv, B, Astar, D, shift_x, shift_y, shift_t, *psf_poly_params = w.params.values ipar = w.params.get_free_parameters() # non fixed param indices cov_indices = [list(ipar).index(k) for k in indices] # non fixed param indices in cov matrix assert w.costs[-1] / w.data.size < 1e-3 @@ -215,6 +248,265 @@ def test_ctio_fullchain(): assert np.isclose(shift_y, 0, atol=parameters.PIXSHIFT_PRIOR) # shift_y assert np.isclose(D, spectrum.header["D2CCD_T"], atol=0.1) # D2CCD assert np.isclose(B, 1, atol=1e-3) # B + assert np.isclose(Astar, 1, atol=1e-2) # Astar assert np.all(np.isclose(psf_poly_params[(PSF_POLY_ORDER + 1):len(PSF_POLY_PARAMS_TRUTH)//N_DIFF_ORDERS - 1], np.array(PSF_POLY_PARAMS_TRUTH)[(PSF_POLY_ORDER + 1):len(PSF_POLY_PARAMS_TRUTH)//N_DIFF_ORDERS - 1], rtol=0.01, atol=0.01)) + +@unittest.skipIf(uvspec_available() is False, 'Skipping to avoid libradtran dependency') +@astropy.config.set_temp_cache(os.path.join(os.path.abspath(os.path.dirname(__file__)), "data", "cache")) +def auxtel_fullchain(): + """ + + Returns + ------- + + Examples + -------- + >>> test_auxtel_fullchain() + """ + parameters.VERBOSE = True + parameters.DEBUG = True + parameters.SPECTRACTOR_ATMOSPHERE_SIM = "getObsAtmo" + sim_image_filename = "./tests/data/sim_2023092800266_dmpostisrccd.fits" + + # load test and make image simulation + # if not os.path.isfile(sim_image_filename): + sim = make_auxtel_image() + image = Image(sim_image_filename, config="./config/auxtel.ini") + lambdas_truth = np.fromstring(image.header['LBDAS_T'][1:-1], sep=',') + amplitude_truth = np.fromstring(image.header['AMPLIS_T'][1:-1], sep=',', dtype=float) + parameters.AMPLITUDE_TRUTH = np.copy(amplitude_truth) + parameters.LAMBDA_TRUTH = np.copy(lambdas_truth) + + # extractor + load_config("./config/auxtel.ini") + parameters.PSF_POLY_ORDER = PSF_POLY_ORDER + parameters.CCD_REBIN = 1 + # JN: > 1 not working well for now: I guess CTIO spectra are too narrow + # and under-sampled to extract unbiased rebinned spectrum, but pipeline is ok. + apply_rebinning_to_parameters() + if parameters.CCD_REBIN > 1: + for k in range(2 * (PSF_POLY_ORDER + 1), 3 * (PSF_POLY_ORDER +1)): + PSF_POLY_PARAMS_TRUTH[k] /= parameters.CCD_REBIN + + image = SpectractorInit(sim_image_filename, config="") # config already loaded, do not overwrite PSF_POLY_ORDER + xpos, ypos = np.array([image.header["TARGETX"], image.header["TARGETY"]]) / 2 + parameters.SPECTRACTOR_SIMULATE_STARFIELD = False # here we want to test fit with an exact starfield simulation + spectrum, w = SpectractorRun(image, guess=[xpos, ypos], output_directory="./tests/data") + + # tests + residuals = plot_residuals(spectrum, lambdas_truth, amplitude_truth) + + spectrum.my_logger.warning(f"\n\tQuantities to test with {parameters.CCD_REBIN=}:" + f"\n\t\tspectrum.header['X0_T']={spectrum.header['X0_T'] / parameters.CCD_REBIN:.5g} vs {spectrum.x0[0]:.5g}" + f"\n\t\tspectrum.header['Y0_T']={spectrum.header['Y0_T'] / parameters.CCD_REBIN:.5g} vs {spectrum.x0[1]:.5g}" + f"\n\t\tspectrum.header['ROT_T']={spectrum.header['ROT_T']:.5g} " + f"vs {spectrum.rotation_angle:.5g}" + f"\n\t\tspectrum.header['BKGD_LEV']={spectrum.header['BKGD_LEV'] * parameters.CCD_REBIN**2:.5g} " + f"vs {np.mean(spectrum.spectrogram_bgd):.5g}" + f"\n\t\tspectrum.header['D2CCD_T']={spectrum.header['D2CCD_T']:.5g} " + f"vs {spectrum.disperser.D:.5g}" + f"\n\t\tspectrum.header['A2_FIT']={spectrum.header['A2_FIT']:.5g} vs {A2_T:.5g}" + f"\n\t\tspectrum.header['CHI2_FIT']={spectrum.header['CHI2_FIT']:.4g}" + f"\n\t\tspectrum.chromatic_psf.poly_params=" + f"{spectrum.chromatic_psf.params.values[spectrum.chromatic_psf.Nx + 2 * (PSF_POLY_ORDER + 1):-1]}" + f" vs {PSF_POLY_PARAMS_TRUTH[2 * (PSF_POLY_ORDER + 1):len(PSF_POLY_PARAMS_TRUTH)//N_DIFF_ORDERS - 1]}" + f"\n\t\tresiduals wrt truth: mean={np.mean(residuals[100:-100]):.5g}, " + f"std={np.std(residuals[100:-100]):.5g}") + assert np.isclose(float(spectrum.header['X0_T'] / parameters.CCD_REBIN), spectrum.x0[0], atol=0.2 * parameters.CCD_REBIN) + assert np.isclose(float(spectrum.header['Y0_T'] / parameters.CCD_REBIN), spectrum.x0[1], atol=0.2 * parameters.CCD_REBIN) + assert np.isclose(float(spectrum.header['ROT_T']), spectrum.rotation_angle, atol=1e-3) + assert np.isclose(float(spectrum.header['BKGD_LEV'] * parameters.CCD_REBIN**2), np.mean(spectrum.spectrogram_bgd), rtol=1e-3) + assert np.isclose(float(spectrum.header['D2CCD_T']), spectrum.disperser.D, atol=0.1) + if parameters.CCD_REBIN == 1: + assert float(spectrum.header['CHI2_FIT']) < 1.5e-3 + else: + assert float(spectrum.header['CHI2_FIT']) < 1.5e-1 + assert np.all( + np.isclose(spectrum.chromatic_psf.params.values[spectrum.chromatic_psf.Nx + 2 * (PSF_POLY_ORDER + 1):-1], + np.array(PSF_POLY_PARAMS_TRUTH)[2 * (PSF_POLY_ORDER + 1):len(PSF_POLY_PARAMS_TRUTH)//N_DIFF_ORDERS - 1], rtol=0.01, atol=0.01)) + assert np.abs(np.mean(residuals[100:-100])) < 0.25 + assert np.std(residuals[100:-100]) < 3 + + spectrum_file_name = "./tests/data/sim_2023092800266_dmpostisrccd_spectrum.fits" + assert os.path.isfile(spectrum_file_name) + spectrum = Spectrum(spectrum_file_name) + parameters.SPECTRACTOR_ATMOSPHERE_SIM = "getObsAtmo" + w = SpectrumFitWorkspace(spectrum, fit_angstrom_exponent=False, verbose=True, plot=True, live_fit=False) + run_spectrum_minimisation(w, method="newton") + nsigma = 2 + labels = ["VAOD_T", "OZONE_T", "PWV_T"] + indices = [2, 4, 5] + ipar = w.params.get_free_parameters() # non fixed param indices + cov_indices = [list(ipar).index(k) for k in indices] # non fixed param indices in cov matrix + assert w.costs[-1] / w.data.size < 0.5 + k = 0 + for i, l in zip(indices, labels): + icov = cov_indices[k] + spectrum.my_logger.info(f"Test {l} best-fit {w.params.values[i]:.3f}+/-{np.sqrt(w.params.cov[icov, icov]):.3f} " + f"vs {spectrum.header[l]:.3f} at {nsigma}sigma level: " + f"{np.abs(w.params.values[i] - spectrum.header[l]) / np.sqrt(w.params.cov[icov, icov]) < nsigma}") + assert np.abs(w.params.values[i] - spectrum.header[l]) / np.sqrt(w.params.cov[icov, icov]) < nsigma + k += 1 + assert np.abs(w.params.values[1]) / np.sqrt(w.params.cov[1, 1]) < 2 * nsigma # A2 + assert np.isclose(np.abs(w.params.values[8]), 0, atol=parameters.PIXSHIFT_PRIOR) # pixshift + assert np.isclose(np.abs(w.params.values[9]), 0, atol=1e-3) # B + + parameters.DEBUG = False + parameters.SPECTRACTOR_ATMOSPHERE_SIM = "getObsAtmo" + w = SpectrogramFitWorkspace(spectrum, fit_angstrom_exponent=False, verbose=True, plot=True, live_fit=False) + run_spectrogram_minimisation(w, method="newton") + nsigma = 2 + labels = ["A1_T", "A2_T", "VAOD_T", "OZONE_T", "PWV_T"] + indices = [0, 1, 3, 5, 6] + A1, A2, A3, aerosols, angstrom_exponent, ozone, pwv, B, Astar, D, shift_x, shift_y, shift_t, *psf_poly_params = w.params.values + ipar = w.params.get_free_parameters() # non fixed param indices + cov_indices = [list(ipar).index(k) for k in indices] # non fixed param indices in cov matrix + assert w.costs[-1] / w.data.size < 1e-3 + k = 0 + for i, l in zip(indices, labels): + icov = cov_indices[k] + spectrum.my_logger.info(f"Test {l} best-fit {w.params.values[i]:.3f}+/-{np.sqrt(w.params.cov[icov, icov]):.3f} " + f"vs {spectrum.header[l]:.3f} at {nsigma}sigma level: " + f"{np.abs(w.params.values[i] - spectrum.header[l]) / np.sqrt(w.params.cov[icov, icov]) < nsigma}") + assert np.abs(w.params.values[i] - spectrum.header[l]) / np.sqrt(w.params.cov[icov, icov]) < nsigma + k += 1 + assert np.isclose(shift_y, 0, atol=parameters.PIXSHIFT_PRIOR) # shift_y + assert np.isclose(D, spectrum.header["D2CCD_T"], atol=0.1) # D2CCD + assert np.isclose(B, 1, atol=1e-3) # B + assert np.isclose(Astar, 1, atol=1e-2) # Astar + assert np.all(np.isclose(psf_poly_params[(PSF_POLY_ORDER + 1):len(PSF_POLY_PARAMS_TRUTH)//N_DIFF_ORDERS - 1], + np.array(PSF_POLY_PARAMS_TRUTH)[(PSF_POLY_ORDER + 1):len(PSF_POLY_PARAMS_TRUTH)//N_DIFF_ORDERS - 1], + rtol=0.01, atol=0.01)) + + + +@unittest.skipIf(uvspec_available() is False, 'Skipping to avoid libradtran dependency') +@astropy.config.set_temp_cache(os.path.join(os.path.abspath(os.path.dirname(__file__)), "data", "cache")) +def test_stardice_fullchain(): + """ + + Returns + ------- + + Examples + -------- + >>> test_stardice_fullchain() #doctest: +ELLIPSIS + OHP site... + """ + parameters.VERBOSE = True + parameters.DEBUG = True + parameters.SPECTRACTOR_ATMOSPHERE_SIM = "getObsAtmo" + sim_image = "./tests/data/IMG_0019584_sim.fits" + + # load test and make image simulation + #if not os.path.isfile(sim_image): + make_stardice_image() + image = Image(sim_image, config="./config/stardice.ini") + lambdas_truth = np.fromstring(image.header['LBDAS_T'][1:-1], sep=',') + amplitude_truth = np.fromstring(image.header['AMPLIS_T'][1:-1], sep=',', dtype=float)[:lambdas_truth.size] + parameters.AMPLITUDE_TRUTH = np.copy(amplitude_truth) + parameters.LAMBDA_TRUTH = np.copy(lambdas_truth) + + # extractor + load_config("./config/stardice.ini") + parameters.SPECTRACTOR_ATMOSPHERE_SIM = "getObsAtmo" + parameters.PSF_POLY_ORDER = PSF_POLY_ORDER + parameters.CCD_REBIN = 1 + if image.header['MOUNTTAU'] < 90: + parameters.OBS_CAMERA_ROTATION = 180 + elif image.header['MOUNTTAU'] >= 90: + parameters.OBS_CAMERA_ROTATION = 0 + + # JN: > 1 not working well for now: I guess CTIO spectra are too narrow + # and under-sampled to extract unbiased rebinned spectrum, but pipeline is ok. + apply_rebinning_to_parameters() + if parameters.CCD_REBIN > 1: + for k in range(2 * (PSF_POLY_ORDER + 1), 3 * (PSF_POLY_ORDER +1)): + PSF_POLY_PARAMS_TRUTH[k] /= parameters.CCD_REBIN + spectrum, w = SpectractorRun(image, "./tests/data", guess=(530, 610)) # config already loaded, do not overwrite PSF_POLY_ORDER + # tests + residuals = plot_residuals(spectrum, lambdas_truth, amplitude_truth) + + spectrum.my_logger.warning(f"\n\tQuantities to test with {parameters.CCD_REBIN=}:" + f"\n\t\tspectrum.header['X0_T']={spectrum.header['X0_T'] / parameters.CCD_REBIN:.5g} vs {spectrum.x0[0]:.5g}" + f"\n\t\tspectrum.header['Y0_T']={spectrum.header['Y0_T'] / parameters.CCD_REBIN:.5g} vs {spectrum.x0[1]:.5g}" + f"\n\t\tspectrum.header['ROT_T']={spectrum.header['ROT_T']:.5g} " + f"vs {spectrum.rotation_angle:.5g}" + f"\n\t\tspectrum.header['BKGD_LEV']={spectrum.header['BKGD_LEV'] * parameters.CCD_REBIN**2:.5g} " + f"vs {np.mean(spectrum.spectrogram_bgd):.5g}" + f"\n\t\tspectrum.header['D2CCD_T']={spectrum.header['D2CCD_T']:.5g} " + f"vs {spectrum.disperser.D:.5g}" + f"\n\t\tspectrum.header['A2_FIT']={spectrum.header['A2_FIT']:.5g} vs {A2_T:.5g}" + f"\n\t\tspectrum.header['CHI2_FIT']={spectrum.header['CHI2_FIT']:.4g}" + f"\n\t\tspectrum.chromatic_psf.poly_params=" + f"{spectrum.chromatic_psf.params.values[spectrum.chromatic_psf.Nx + 2 * (PSF_POLY_ORDER + 1):-1]}" + f" vs {PSF_POLY_PARAMS_TRUTH[2 * (PSF_POLY_ORDER + 1):len(PSF_POLY_PARAMS_TRUTH)//N_DIFF_ORDERS - 1]}" + f"\n\t\tresiduals wrt truth: mean={np.mean(residuals[20:-20]):.5g}, " + f"std={np.std(residuals[20:-20]):.5g}") + assert np.isclose(float(spectrum.header['X0_T'] / parameters.CCD_REBIN), spectrum.x0[0], atol=0.2 * parameters.CCD_REBIN) + assert np.isclose(float(spectrum.header['Y0_T'] / parameters.CCD_REBIN), spectrum.x0[1], atol=0.2 * parameters.CCD_REBIN) + assert np.isclose(float(spectrum.header['ROT_T']), spectrum.rotation_angle, atol=3e-3) + assert np.isclose(float(spectrum.header['BKGD_LEV'] * parameters.CCD_REBIN**2), np.mean(spectrum.spectrogram_bgd), rtol=1e-3) + assert np.isclose(float(spectrum.header['D2CCD_T']), spectrum.disperser.D, atol=0.2) + if parameters.CCD_REBIN == 1: + assert float(spectrum.header['CHI2_FIT']) < 3e-4 + else: + assert float(spectrum.header['CHI2_FIT']) < 3e-1 + assert np.all( + np.isclose(spectrum.chromatic_psf.params.values[spectrum.chromatic_psf.Nx + 2 * (PSF_POLY_ORDER + 1):-1], + np.array(PSF_POLY_PARAMS_TRUTH)[2 * (PSF_POLY_ORDER + 1):len(PSF_POLY_PARAMS_TRUTH)//N_DIFF_ORDERS - 1], rtol=0.05, atol=0.1)) + assert np.abs(np.mean(residuals[20:-20])) < 0.1 + assert np.std(residuals[20:-20]) < 1 + + spectrum_file_name = "./tests/data/IMG_0019584_sim_spectrum.fits" + assert os.path.isfile(spectrum_file_name) + spectrum = Spectrum(spectrum_file_name) + w = SpectrumFitWorkspace(spectrum, fit_angstrom_exponent=False, + verbose=True, plot=True, live_fit=False) + run_spectrum_minimisation(w, method="newton") + nsigma = 3 + labels = ["VAOD_T", "OZONE_T", "PWV_T"] + indices = [2, 4, 5] + ipar = w.params.get_free_parameters() # non fixed param indices + cov_indices = [list(ipar).index(k) for k in indices] # non fixed param indices in cov matrix + assert w.costs[-1] / w.data.size < 3 + k = 0 + for i, l in zip(indices, labels): + icov = cov_indices[k] + spectrum.my_logger.info(f"Test {l} best-fit {w.params.values[i]:.3f}+/-{np.sqrt(w.params.cov[icov, icov]):.3f} " + f"vs {spectrum.header[l]:.3f} at {nsigma}sigma level: " + f"{np.abs(w.params.values[i] - spectrum.header[l]) / np.sqrt(w.params.cov[icov, icov]) < nsigma}") + assert np.abs(w.params.values[i] - spectrum.header[l]) / np.sqrt(w.params.cov[icov, icov]) < nsigma + k += 1 + assert np.abs(w.params.values[1]) / np.sqrt(w.params.cov[1, 1]) < 2 * nsigma # A2 + assert np.isclose(np.abs(w.params.values[8]), 0, atol=parameters.PIXSHIFT_PRIOR) # pixshift + assert np.isclose(np.abs(w.params.values[9]), 0, atol=1e-3) # B + + parameters.DEBUG = False + parameters.SPECTRACTOR_ATMOSPHERE_SIM = "getObsAtmo" + w = SpectrogramFitWorkspace(spectrum, fit_angstrom_exponent=False, + verbose=True, plot=True, live_fit=False) + run_spectrogram_minimisation(w, method="newton") + nsigma = 3 + labels = ["A1_T", "A2_T", "VAOD_T", "OZONE_T", "PWV_T"] + indices = [0, 1, 3, 5, 6] + A1, A2, A3, aerosols, angstrom_exponent, ozone, pwv, B, Astar, D, shift_x, shift_y, shift_t, *psf_poly_params = w.params.values + ipar = w.params.get_free_parameters() # non fixed param indices + cov_indices = [list(ipar).index(k) for k in indices] # non fixed param indices in cov matrix + assert w.costs[-1] / w.data.size < 3 + k = 0 + for i, l in zip(indices, labels): + icov = cov_indices[k] + spectrum.my_logger.info(f"Test {l} best-fit {w.params.values[i]:.3f}+/-{np.sqrt(w.params.cov[icov, icov]):.3f} " + f"vs {spectrum.header[l]:.3f} at {nsigma}sigma level: " + f"{np.abs(w.params.values[i] - spectrum.header[l]) / np.sqrt(w.params.cov[icov, icov]) < nsigma}") + assert np.abs(w.params.values[i] - spectrum.header[l]) / np.sqrt(w.params.cov[icov, icov]) < nsigma + k += 1 + assert np.isclose(shift_y, 0, atol=parameters.PIXSHIFT_PRIOR) # shift_y + assert np.isclose(D, spectrum.header["D2CCD_T"], atol=0.2) # D2CCD + assert np.isclose(B, 1, atol=1e-3) # B + assert np.all(np.isclose(psf_poly_params[(PSF_POLY_ORDER + 1):len(PSF_POLY_PARAMS_TRUTH)//N_DIFF_ORDERS - 1], + np.array(PSF_POLY_PARAMS_TRUTH)[(PSF_POLY_ORDER + 1):len(PSF_POLY_PARAMS_TRUTH)//N_DIFF_ORDERS - 1], + rtol=0.1, atol=0.1)) diff --git a/tests/test_simulator.py b/tests/test_simulator.py index dad952b9a..85e921b1f 100644 --- a/tests/test_simulator.py +++ b/tests/test_simulator.py @@ -63,7 +63,7 @@ def test_simulator(): atmosphere = AtmosphereGrid(atmgrid_filename="./tests/data/reduc_20170530_134_atmsim.fits") spectrum_simulation = SpectrumSimulation(spectrum, atmosphere=atmosphere, fast_sim=True) spectrum_simulation.simulate(A1=1, A2=1, ozone=300, pwv=5, aerosols=0.05, angstrom_exponent=None, - reso=0., D=56, shift_x=0., B=0.) + reso=0., D=56, shift_x=0.) assert np.sum(spectrum_simulation.data) > 0 assert np.sum(spectrum_simulation.data) < 1e-10