X-ray Emissions in Measurements of the Neutron Capture Cross Sections for the Production of 197 Hg and 197 Pt and Scoping the Science Parameter Space of Future X-ray Astrophysics Calorimeter Missions by Mason L. Keck A PROJECT submitted to Oregon State University University Honors College in partial fulfillment of the requirements for the degree of Honors Baccalaureate of Science in Physics (Honors Scholar) Presented May 30, 2012 Commencement June 2012 AN ABSTRACT OF THE THESIS OF Mason L. Keck for the degree of Honors Baccalaureate of Science in Physics presented on May 30, 2012. Title: X-ray Emissions in Measurements of the Neutron Capture Cross Sections for the Production of 197 Hg and 197 Pt and Scoping the Science Parameter Space of Future X-ray Astrophysics Calorimeter Missions Abstract approved: Ken Krane A spectral fitting routine was developed to analyze X-ray emissions in neutron capture decay processes that produce 197 Hg and 197 Pt. Through correcting for X-ray emissions, the 77.3 keV γ ray intensities were analyzed. The thermal cross sections for the production of 197 Hg and 197 Pt were found to be 2088 ± 133 b and 0.62 ± 5 b, respectively. Similarly, The resonance integrals for the production of 197 Hg and 197 Pt agree with some historical measurements and disagree with others. These cross section values agree with those determined through the analysis of the 191 keV γ ray produced in the neutron capture processes that produce 197 Hg and 197 Pt. A computational routine, ’Drive XSPEC’, was developed to help determine the feasibility of pursuing various science goals with future X-ray calorimeter spectrometer missions, most significantly the NASA Advanced X-ray Spectroscopic Imaging Observatory (AXSIO) mission concept, in anticipation of a Mission Design Laboratory (MDL) investigation. ’Drive XSPEC’ can run large scale spectral simulations, which can be applied to developing research proposals, performing data analysis, and comparing instrument designs. Key Words: Neutron capture cross sections, X-ray spectroscopy, OSU TRIGA reactor, high purity germanium detector, Oregon State University, X-ray astrophysics, International X-ray Observatory, calorimeter spectrometer, NASA Goddard Space Flight Center Corresponding e-mail address: masonkeck@gmail.com c Copyright by Mason L. Keck May 30, 2012 All Rights Reserved X-ray Emissions in Measurements of the Neutron Capture Cross Sections for the Production of 197 Hg and 197 Pt and Scoping the Science Parameter Space of Future X-ray Astrophysics Calorimeter Missions by Mason L. Keck A PROJECT submitted to Oregon State University University Honors College in partial fulfillment of the requirements for the degree of Honors Baccalaureate of Science in Physics (Honors Scholar) Presented May 30, 2012 Commencement June 2012 Honors Baccalaureate of Science in Physics project of Mason L. Keck presented on May 30, 2012. APPROVED: Mentor, representing Physics Committee Member, representing X-ray Astrophysics, NASA Goddard Space Flight Center Committee Member, representing Physics Chair, Department of Physics Dean, University Honors College I understand that my project will become part of the permanent collection of Oregon State University, University Honors College. My signature below authorizes release of my project to any reader upon request. Mason L. Keck, Author Acknowledgements I give much thanks to the NASA Goddard Space Flight Center college summer internship program and the IXO/AXSIO team for the opportunity to be involved with the development of AXSIO during the summer of 2011. I would like to thank my mentor Dr. Ken Krane for all his help throughout this project and giving me the opportunity to have a significant role in the data analysis in determining the nuclear energy level and half-life values of 38 Cl. I am grateful for the opportunity to have worked with my NASA mentor Dr. Andy Ptak and his thorough explanations of data analysis in X-ray Astrophysics. I also would like to thank my committee member and mentor Dr. William Hetherington, who gave me the opportunity to work with the OSU Radio Telescope Project. I would like to thank the Oregon State Physics faculty for creating a supportive and challenging environment for learning physics, and I would like to thank my fellow physics majors in general, as they have made physics much more enjoyable than I expected. I also would like to thank Linda, Gerald, Daren, Jeff, and Roo Keck for their patience, support, and proofreading help. Finally, I would like to thank Natalie Rich for her patience, support, and help throughout this project and college. Contents X-ray Emissions in Measurements of the Neutron Capture Cross Sections for the Production of 197 Hg and 197 Pt 1 1 Introduction 1 2 Background 2.1 Neutron Capture Cross Sections . . . . . . . . . . . . . . . . . . . . . . . . 2.2 X-ray Production in Radioactive Decay and X-ray Nomenclature . . . . . . 2.2.1 X-ray production in mercury and platinum experiments . . . . . . . 3 3 6 9 3 Experimental Details 3.1 Irradiations . . . . . . . . . . . . . . . . . . 3.1.1 Flux monitors . . . . . . . . . . . . . 3.2 Radiation Counting . . . . . . . . . . . . . 3.2.1 Germanium detector characteristics 3.2.2 Efficiency calibration measurements 3.3 Modeling the X-ray Emissions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12 12 13 14 15 18 19 4 Data Analysis 4.1 Efficiency Calibrations . . . . . . . . . . . . . . . 4.2 Modeling and subtracting X-ray emissions . . . . 4.3 γ ray mass attenuation . . . . . . . . . . . . . . . 4.4 Meta-stable decays . . . . . . . . . . . . . . . . . 4.5 Uncertainty and Goodness of Fit of Calculations 4.6 Error Propagation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24 24 25 27 27 28 28 . . . . . . . . . . . . 5 Results 31 6 Analysis and Discussion 6.1 196 Hg → 197g Hg . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6.2 196 Pt → 197g Pt . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33 33 34 7 Conclusion 35 Scoping the Science Parameter Space of Future X-ray Astrophysics Calorimeter Missions 36 8 Introduction 36 CONTENTS (CONTINUED) 9 Background 9.1 X-Ray Astrophysics . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9.1.1 X-ray background . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37 38 41 10 Methods 10.1 Forward Fitting . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10.2 Error Fitting . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10.3 Experimental Approach with ’Drive XSPEC’ . . . . . . . . . . . . . . . . . 43 43 46 47 11 Results 11.1 Simulations of a Velocity Broadened Thermal-Plasma Model, ASTRO-H . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11.2 ’Bapec’ Simulations with Various ASTRO-H SXS Designs . . 11.3 Likelihood-ratio Test for an Emission Line in SNR 1987-A . . 49 ’bapec’, . . . . . . . . . . . . . . . with . . . . . . . . . 49 51 52 12 Analysis and Discussion 55 13 Conclusion 56 Bibliography 57 Appendices 59 A ’Simulate’ details A.1 Code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . A.1.1 simulate.py . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . A.1.2 model.py . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60 60 61 62 B XSPEC and ’Drive XSPEC’ details B.1 Example XSPEC Models . . . . . B.2 Counting Error . . . . . . . . . . . B.3 Code . . . . . . . . . . . . . . . . . B.3.1 drive xspec.py . . . . . . . B.3.2 dx comm.py . . . . . . . . . 67 67 68 70 71 72 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . List of Figures 2.1 Neutron capture process. An incident neutron excites the 196 Pt nucleus to the resonant state. The nucleus then decays to a meta-stable state or the ground state. Spin is indicated next to each state. Photons do not want to carry more than 1 unit of spin angular momentum, so photons actually usually take six steps between the resonant state and the meta-stable state and the meta-stable state and the ground state, which is not shown. . . . . 2.2 Cross section as a function of energy for the production of 2.3 197g Hg 2.4 2.5 3.1 3.2 3.3 3.4 197g Hg . . . . 5 . . . . . . . . . . . . . . . . . . . . . . 6 X-ray emissions from electron transitions. Vacancies in the K-shell are filled by electrons from the L-shell, which creates vacancies in higher energy shells, creating a ’cascade’ of electrons with corresponding X-ray peak profiles shown atop each X-ray series. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8 An energy-level diagram of K-shell transitions and the energy spectrum these transitions produce (in platinum). Kβ2 emission line is actually an unresolved doublet. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9 The locations of the TRIGA reactor facilities. The thermal column is a column behind a graphite barrier, which is located off the image. . . . . . 13 The detector configuration used for data collection. The detector is in a lead housing for safety to attenuate X-rays scattering away from the detector. Copper sheets line the inside of the lead enclosure in order to greatly attenuate the intensity of lead X-rays that the detector collects. . . . . . . 15 A model detector response to input narrow Gaussian functions of equal amplitude. Influences of binning of data, detector resolution, and detector efficiency all influence the detector response. . . . . . . . . . . . . . . . . . . . 16 The process of an incident photon being counted in a given channel, ci . The linear speed of the ramp is represented as vr . ∆ti corresponds to channel ci . 17 and 197g Pt decay properties. . 5 LIST OF FIGURES 3.5 (CONTINUED) Spectrum showing the Compton continuum and X-ray and γ ray emission lines produced near 77 keV in the Hg and Pt experiments. . . . . . . . . . . 18 Detector efficiency as a function of energy. Detector 3 and detector 4 have almost identical efficiencies, and the efficiency increases as the separation distance between the sample and the detector decreases, as expected. . . . 19 wscale was varied to minimize the chi-square of each data set in a specific energy region. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21 3.8 ’Simulate’ flowchart. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22 3.9 Spectral data and spectral model plotted for the Hg CLICIT data. The residuals are plotted in green, which are near zero except where the 77.3 keV γ ray peak is present. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23 3.10 Spectral data and spectral model plotted for the last Pt CLICIT run. The 77.3 keV γ ray peak intensity was similar to the background intensity for this run, giving large uncertainty in the γ ray peak area. . . . . . . . . . . . . . 23 5.1 Spectral data and spectral model plotted for the Pt TC data. . . . . . . . 32 9.1 Physical model of AGN and energy spectrum from iron in AGN accretion disks. The energy spectral model is shown with the solid line and simulated data is shown with points with error bars. . . . . . . . . . . . . . . . . . . 40 Physical model and simulated energy spectrum of galactic-scale outflows in starburst galaxies as observed with the IXO calorimeter and Chandra ACIS CCD imager, illustrating improvement in resolving spectral lines with the AXSIO calorimeter. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41 10.1 In fitting physical models to data, XSPEC convolves a physical model with the detector efficiency, the detector response (not shown) of the detector, and the exposure time of an observation to give the ’folded model’. The ’folded model’ is fit to the observed data through minimizing a goodness of fit function. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44 10.2 The problem with the gradient search method for minimizing a goodness of fit function. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46 10.3 Steps to ’Drive XSPEC’, which automates error fitting in XSPEC. . . . . . 48 11.1 Results of fitting the ’Velocity’ parameter of simulated ’bapec’ models with ASTRO-H. Error in the ’Velocity’ parameter decreases below 100 km/s near 8000 spectral counts. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50 3.6 3.7 9.2 LIST OF FIGURES (CONTINUED) 11.2 Velocity as a function of total flux (ergs/cm2 ) in the 0.5-2.0 keV region for 3 ASTRO-H calorimeter designs. . . . . . . . . . . . . . . . . . . . . . . . . . 52 11.3 SNR 1987-A spectrum fit with null model, ’powerlaw’, and the alternative model, ’powerlaw+Gaussian.’ . . . . . . . . . . . . . . . . . . . . . . . . . 53 11.4 Distribution of likelihood ratio values from simulations. . . . . . . . . . . . 53 List of Tables 2.1 Isotopes present in Hg and Pt experiments. . . . . . . . . . . . . . . . . . . 6 2.2 Nuclear transitions producing daughter isotopes with intense X-ray emissions in the Hg and Pt experiments. . . . . . . . . . . . . . . . . . . . . . . . . . 10 Energies and relative energies of the Kα and Kβ X-ray emissions present near 77 keV for elements present in the mercury and platinum experiments. In the Hg experiments, significant X-ray emissions from Au, Hg, Pb, and Tl near 77 keV were observed. In the Pt experiments, significant X-ray emissions Pt, Hg, Au, Ir, and Pb X-rays near 77 keV were observed. . . . . . . . . . . . 11 Hg and Pt isotope properties. Abundance is the relative isotopic abundance of the given isotope. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12 3.2 Details of each irradiation . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13 3.3 Efficiency sources and method of preparation. . . . . . . . . . . . . . . . . . 18 4.1 Series which were analyzed. . . . . . . . . . . . . . . . . . . . . . . . . . . . 25 4.2 γ ray mass attenuation, I/I0 , at 77.3 keV for Hg and Pt in each experiment. Attenuation fluctuated in the Hg experiments as varying thicknesses of HgO powder were used while a Pt foil was used in the Pt experiments. . . . . . 27 4.3 Uncertainties and relative error in both experiments. . . . . . . . . . . . . 30 5.1 Cross sections of 196 Hg and 196 Pt. Uncertainties in the least significant digits are given in italics. For example, I= 0.615 54 =0.615±0.054. Two values for the resonance integral are quoted for the present work due to systematic differences between measurements from the CLICIT and R2 facilities. Values in the second sub column of the present work columns are from analysis of the 191 keV γ ray produced in the decay processes of 196 Hg and 196 Pt . . . 31 2.3 3.1 LIST OF TABLES 9.1 (CONTINUED) Spectral resolution, angular resolution, and effective area of calorimeter spectrometer instruments aboard the ASTRO-H, AXSIO, and Athena missions. XMM-Newton, which was launched in 1999 and uses a CCD, is listed for comparison. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38 11.1 Parameter values for the ’bapec’ simulations. . . . . . . . . . . . . . . . . . 50 11.2 Parameter values used for likelihood ratio test simulations. . . . . . . . . . 54 11.3 Likelihood ratio of fitting null model and alternative model to spectrum of SNR 1987-A. Both models include photon absorption. . . . . . . . . . . . . 54 B.1 The background model used in AXSIO calculations. . . . . . . . . . . . . . 69 X-ray Emissions in Measurements of the Neutron Capture Cross Sections for the Production of 197 Hg and 197 Pt Chapter 1 Introduction Neutron capture cross sections of many nuclei have been measured in the Physics Department at Oregon State University over the last decade. Precise measurements of neutron capture cross sections are important for testing theoretical models of nuclear structure as well as applications in numerous fields, including the production of radioisotopes in medical physics, development of radioactive shielding, and understanding of the neutron activation of materials. The values for the resonance integral and thermal neutron capture cross sections of many nuclei do not agree well between previous measurements, which were made mostly in the 1960’s and 1970’s using low energy-resolution scintillation detectors. The thermal cross section and resonance integral for the production of 197 Hg and 197 Pt were analyzed in this work using High Purity Germanium detectors. Neutron capture cross sections are determined through accurate measurement of γ ray peak intensities in energy spectra. However, neutron capture spectra can feature significant X-ray emission in the energy region, 50-100 keV, where X-rays and γ rays overlap. The most intense gamma rays produced in the neutron capture processes in 197 Hg and 197 Pt, which provide the most accurate measure of the neutron cross section, reside at 77.3 keV amidst significant X-ray background. As a result, previous measurements have involved 2 measurement of the second most intense γ ray peak at 191 keV in the neutron capture processes in 197 Hg and 197 Pt. However, the 77.3 keV γ ray peak intensities in the production of 197 Hg and 197 Pt are about 30 and 5 times stronger, respectively, than the γ ray peaks produced at 191 keV. Thus, a computational spectral fitting routine was developed to fit observed X-ray peaks in the 50-100 keV region in order to best analyze the X-ray emission at 77.3 keV. Once the energy spectra were corrected for X-ray emission, the 77.3 keV γ ray peak intensities were measured in order to determine the thermal cross section and resonance integral for the production of 197 Hg and 197 Pt by neutron capture. These cross section values agree with those determined through the analysis of the 191 keV γ ray produced in the neutron capture processes in 197 Hg and 197 Pt. This thesis describes the X-ray emission fitting procedure and the determination of the thermal cross section and resonance integral for the production of 197 Hg and 197 Pt by neutron capture. 3 Chapter 2 Background In neutron capture, an atom absorbs a neutron, which excites the atom to a highly-excited, resonant state. The atom quickly proceeds to the ground state. Due to the added neutron, the atom beta decays to a daughter nucleus in an excited state. The daughter nucleus can decay to the ground state by emitting a γ ray or an electron, where the latter causes for the emission of X-rays from electrons filling in the vacated orbital. This γ ray and X-ray emission was studied in this analysis. 2.1 Neutron Capture Cross Sections The reaction rate for neutron capture is simply the product of the number of target atoms, cross section of each atom, and neutron flux. In terms of thermal, φth and epithermal φepi flux in the reactor, R = N0 (σφth + Iφepi ) (2.1) where N0 is the number of stable nuclei in the irradiated sample, φth and φepi are the thermal flux and the epithermal flux, respectively, and σ and I are the effective thermal cross section and resonance integral, respectively [1]. 4 The change in number, dN , of radioactive nuclei in a time interval dt is dN = Rdt − λN dt (2.2) Solving for N gives the activity, a, of a radioactive source: a(t) = λN (t) = R(1 − e−λti )e−λt (2.3) where R is the reaction rate, a is the activity of the source at time t after the irradiation, and ti is the irradiation time. The thermal cross section and resonance integral are measures of the probability of a nucleus absorbing a thermal neutron, with energy below 1eV, and an epithermal neutron, with energy between 1eV and 10keV, respectively. The process of neutron capture involves an atom absorbing a neutron, which excites to a resonant state. The atom then can proceed to the ground state through emitting γ rays as shown in Figure 2.1. Some energy states have significant angular momentum. Photons are less likely to carry a significant amount of angular momentum, so these states, called meta-stable states, have significant half-lives. Neutron capture cross sections depend on energy as shown in Figure 2.2. The thermal cross section has a 1/v dependence, where v is the neutron velocity. The epithermal region is parameterized by the integral, I, of the cross section over the entire epithermal region. 5 Resonant State 1 2 primary γ ' s n Meta-Stable State 95.41 min 196 Pt Ground State 19.9 h 13 2 secondary γ ' s 197 Pt 1 2 Figure 2.1: Neutron capture process. An incident neutron excites the 196 Pt nucleus to the resonant state. The nucleus then decays to a meta-stable state or the ground state. Spin is indicated next to each state. Photons do not want to carry more than 1 unit of spin angular momentum, so photons actually usually take six steps between the resonant state and the meta-stable state and the meta-stable state and the ground state, which is not shown. Figure 2.2: Cross section as a function of energy for the production of 197g Hg . Atoms with an additional neutron from neutron capture are unstable, so they beta decay to produce daughter nuclei in an excited state. These daughter nuclei then proceed to their ground state through either the emission of a γ ray, as shown in Figure 2.3 or the ejection of an orbital electron, called internal conversion. The γ ray gives information about neutron cross sections while internal conversion produces X-rays which are background in the data. The decay schemes of 197g Hg and 197g Pt are shown in Figure 2.3. Both isotopes beta decay 6 to an excited state of 197g Au, which then proceeds to its ground state through either the emission of γ rays with energies in keV as indicated next to each transition in 197g Au or the emission of electrons, which is called internal conversion. 197g Hg and 197g Pt have a number of possible decay paths with probabilities indicated next to each path. 197 197 Pt 19.9 h 8.2 % 1.4% Hg 64.4 h 93% 81.2% 191 77 268 197 Figure 2.3: 197g Hg Au and 197g Pt decay properties. Isotopes produced by neutron capture of several isotopes of Hg and Pt present in these experiments are shown in Table 2.1. Hg Isotope 197g Hg 197m Hg 199m Hg 203 Hg 205 Hg experiments t1/2 64.94 ± 0.07 h 23.8 ± 0.1 h 42.67 ± 0.09 min 46.594 ± 0.012 d 5.14 ± 0.09 min Pt Isotope 191 Pt 193 Pt 195 Pt 197g Pt 197m Pt 199 Pt 199 Au experiments t1/2 2.861 ± 0.009 d 4.33 ± 0.03 d 4.010 ± 0.005 d 19.96 ± 0.05 h 95.41 ± 0.18 min 30.80 ± 0.21 min 3.139 ± 0.007 d Table 2.1: Isotopes present in Hg and Pt experiments. 2.2 X-ray Production in Radioactive Decay and X-ray Nomenclature Internal conversion produces a vacancy in one of the electron orbitals, which is quickly filled by a ’cascade’ of electrons. This produces many X-ray spectral line emissions as shown in Figure 2.4. X-ray lines are commonly designated using Siegbahn notation [2]. This notation 7 was developed in the 1930’s with detectors with much poorer resolution than those used today. With Siegbahn notation, an X-ray corresponding to an electron transition to the n = 1 orbital is designated with a K, an X-ray corresponding to an electron transition to the n = 2 orbital is designated with a L. Similarly, n = 3 is designated with M . The strongest unresolved X-ray line is labeled with an α and typically corresponds to an electron transition with ∆n = 1. The second strongest unresolved X-ray line is labeled with a β and typically corresponds to ∆n = 2. Similarly, γ usually indicates ∆n = 3. For example, a transition from the n=3 to the n=1 level is labeled a Kβ transition. Atomic energy levels further have fine structure due to effects of relativistic motion of electrons and electron spin-orbit coupling. As shown in Figure 2.4, the given electron transition series α, β, γ, etc. are further broken up into transitions of slightly different energies corresponding to transitions from states with different values for the total angular momentum of the electron, j, where j = l ± s for spin 1/2 systems. The most intense X-rays from electron transitions obey the electric dipole radiation selection rules: ∆l = ±1, and ∆j = 0 , ±1 [3]. The transitions within a given series are approximately numbered in order from the strongest to weakest peak. For example, in platinum, the Kα1 peak is stronger than the the Kα2 peak. However, the Kβ3 peak is stronger than the the Kβ2 peak as shown in Figure 2.5. 8 Figure 2.4: X-ray emissions from electron transitions. Vacancies in the K-shell are filled by electrons from the L-shell, which creates vacancies in higher energy shells, creating a ’cascade’ of electrons with corresponding X-ray peak profiles shown atop each X-ray series. Image credit: [4]. 9 n l j N7 N6 N5 4 3 7/2 4 3 5/2 4 2 5/2 N4 N3 4 2 3/2 4 1 3/2 N2 4 1 1/2 N1 4 0 1/2 M5 3 2 5/2 M4 3 2 3/2 M3 M2 M1 3 1 3/2 3 1 1/2 3 0 1/2 0.5 197 0.4 2 1 3/2 2 1 1/2 2 0 1/2 K 1 0 1/2 Counts 0.3 L3 L2 L1 Hg, 199 Hg Kα1 Kα2 Kβ1 Kβ2 Kβ3 0.2 0.1 Kα 2 Kα 1 Kβ 3 Kβ 1 Kβ 2 (a) Energy-level diagram 0.065 70 75 Energy (keV) 80 85 (b) Energy spectrum Figure 2.5: An energy-level diagram of K-shell transitions and the energy spectrum these transitions produce (in platinum). Kβ2 emission line is actually an unresolved doublet. In general, X-rays are produced from electron processes that produce discrete spectral features, including internal conversion and photoelectric absorption, and continuum spectral features, including Compton scattering and bremsstrahlung. In contrast, γ rays are produced from atomic processes, such as radioactive decay. X-rays and γ rays overlap in energy in the 50-100 keV region. X-rays peak in energy around 100 keV while gamma rays peak in energy at several MeV. 2.2.1 X-ray production in mercury and platinum experiments In the Hg experiments, significant X-ray emissions from Au, Hg, Pb, and Tl near 77 keV were observed. In the Pt experiments, significant X-ray emissions from Pt, Hg, Au, Ir, and Pb X-rays near 77 keV were observed. X-ray peaks are produced from the nuclear transitions listed in Table 2.2. X-ray emissions are also produced by photoelectric absorption of γ rays in lead. Pb is used to attenuate gamma rays to minimize exposure to gamma radiation. However, photoelectric absorption of γ rays in Pb ejects an electron from an electron orbital, which results in X-ray 10 transition transition type Hg experiments 197 Hg → 197 Au → 203 Tl 197m Hg , 199m Hg → 203 Hg 197 Hg , 199 Hg Pt experiments 191 Pt → 191 Ir , 195m Pt → 193 Pt , 197 Pt → 197 Au 199 Pt → 199 Au → 199 Hg 193m Pt 195 Pt beta decay beta decay isomeric transition beta decay isomeric transition beta decay beta decay Table 2.2: Nuclear transitions producing daughter isotopes with intense X-ray emissions in the Hg and Pt experiments. emission [5]. Each X-ray emission ’line’ present in the Hg and Pt experiments and their intensities relative to other spectral lines within a given atom are shown in Table 2.3. 11 Element Pb Pb Pb Pb Pb Au Au Au Au Au Hg Hg Hg Hg Hg Tl Tl Tl Tl Tl Pt Pt Pt Pt Pt Ir Ir Ir Ir Ir Transition Kα1 Kα2 Kβ1 Kβ2 Kβ3 Kα1 Kα2 Kβ1 Kβ2 Kβ3 Kα1 Kα2 Kβ1 Kβ2 Kβ3 Kα1 Kα2 Kβ1 Kβ2 Kβ3 Kα1 Kα2 Kβ1 Kβ2 Kβ3 Kα1 Kα2 Kβ1 Kβ2 Kβ3 Energy(KeV) 74.969 72.805 84.938 87.300 84.450 68.806 66.991 77.982 80.130 77.577 70.818 68.894 80.255 82.473 79.824 72.873 70.832 82.574 84.865 82.115 66.831 65.122 75.749 77.831 75.368 64.896 63.287 73.560 75.575 73.202 Rel. Intensities 0.462 0.277 0.107 0.0391 0.0558 0.464 0.275 0.107 0.0384 0.0577 0.463 0.275 0.107 0.0387 0.0559 0.463 0.276 0.107 0.039 0.0559 0.465 0.274 0.107 0.0381 0.0556 0.467 0.274 0.106 0.0375 0.0552 Table 2.3: Energies and relative energies of the Kα and Kβ X-ray emissions present near 77 keV for elements present in the mercury and platinum experiments. In the Hg experiments, significant X-ray emissions from Au, Hg, Pb, and Tl near 77 keV were observed. In the Pt experiments, significant X-ray emissions Pt, Hg, Au, Ir, and Pb X-rays near 77 keV were observed. 12 Chapter 3 Experimental Details Neutron capture by 196 Hg and 196 Pt produces 197g Hg and 197g Pt, respectively, which have decay properties as shown in Table 3.1. Capture By 196 Hg 196 Hg Capture To 197g Hg 197g Pt Abundance 0.0015 ± 0.0001 0.253 ± 0.005 Half-life 64.94 ± 0.07 h 19.96 ± 0.05 h Analyzed γ rays 77.3 keV 77.3 keV Table 3.1: Hg and Pt isotope properties. Abundance is the relative isotopic abundance of the given isotope. 3.1 Irradiations Samples of HgO powder and Pt metal foil were prepared and irradiated in four separate facilities at the OSU TRIGA reactor: a thermal column, (TC), a cadmium-lined, in-core irradiation tube (CLICIT), a fast pneumatic transfer facility (’rabbit’ or R1), and the ’rabbit’ with a cadmium box (R2) of 1 mm wall thickness to isolate epithermal neutrons. Experimental details and values for the thermal and epithermal fluxes for each facility are given in Table 3.2. Four facilities were used to get multiple measurements, which gives greater certainty in the data, and because the epithermal flux gives a measure for the resonance integral while the thermal flux gives a measure of the thermal cross section. The location of each facility is 13 facility EOB date mass (mg) flux (neutrons/cm2 /s) CLICIT TC R1 R2 11/17/11 11/29/11 02/22/12 02/22/12 Hg 9.9 23.9 15.2 42.2 thermal 0 7.80E+010 8.30E+012 0 Pt 11.6 46.4 12.1 13.9 epithermal 1.16E+012 2.00E+008 3.50E+011 3.50E+011 bombardment time 1h 2h 5 min 3 min Table 3.2: Details of each irradiation shown in Figure 3.1. Figure 3.1: The locations of the TRIGA reactor facilities. The thermal column is a column behind a graphite barrier, which is located off the image. 3.1.1 Flux monitors Irradiations included samples of accurately-known cross section in order to determine the neutron fluxes given in Table 3.2. Flux monitors used were Au and Co in the form of dilute (0.134% and 0.438%) alloys in thin Al metal foils. Values assumed for the thermal cross section and resonance integral of Au were 98.65 ± 0.09 b and 1550 ± 28 b, respectively. Values assumed for the thermal cross section and resonance integral of Co were 37.18 ± 0.06 b and 74 ± 2 b, respectively. Zr was used as a secondary flux monitor in determining the epithermal flux in the thermal column. 14 3.2 Radiation Counting High purity germanium (HPGe) detectors in a coaxial configuration (which have a nominal volume of 169 cm2 , efficiency of 35% compared with NaI detectors at 1332 keV, and energy resolution of 1.68 keV at 1332 keV) were used for detecting γ ray emissions. The two detectors had nearly identical characteristics. Source-to-detector distances ranged from 10-20 cm. Coincidence summing is negligible at these distances [1]. Detector efficiency, which depends upon the solid angle of the detector ’seen’ by the source and the probability of an incident photon interacting with a detector, was determined for each separate distance, which is discussed in Section 4.1. The detectors were kept at 77 K using liquid nitrogen to reduce thermally-induced leakage current which shows up as thermal noise in data. The detector was maintained in vacuum conditions in order to prevent impurity gases from condensing on the detector [5]. Signals from the detector are processed in a digital spectrometer and then are sent to a computer. Calculation of peak areas for energy calibration were done using ORTEC Maestro Software [6]. A more in-depth description of photon counting is in Section 3.2.1. Samples typically were allowed to reduce in activity for several hours before being counted to give desirable dead times. The sample counting setup is shown in Figure 3.2. Once the samples were inserted in front of the detectors, the X-ray and γ ray emissions were counted for finite runs using Maestro. Once the runtime of a run elapsed, a new run began. The motivation for this is to get more runs in order to get more statistics and thus a more accurate calculation of the activity of each source. Each run time was set in order to balance accuracy in measuring the activity and in getting good statistics, or a large number of counts, in each run. Runs were organized into different series. For example, Pt CLICIT data were counted in four series, which were labeled A, B, C, and D in order of start time. Runs within a given series had the same real time. The real time for later series was increased in order to give similar statistics, or total counts, for each run. 15 Figure 3.2: The detector configuration used for data collection. The detector is in a lead housing for safety to attenuate X-rays scattering away from the detector. Copper sheets line the inside of the lead enclosure in order to greatly attenuate the intensity of lead X-rays that the detector collects. 3.2.1 Germanium detector characteristics Important germanium detector characteristics include efficiency and spectral resolution. Detector efficiency is the efficiency of a detector in counting a photon at a given energy. Detectors detect photon energy through the creation of electron-hole pairs. Detector efficiency is a measure of the efficiency of the detector in counting a photon and depends upon energy due to the energy dependence of the interaction probabilities of the photoelectric effect, Compton scattering, and pair production [5]. A simulated detector response to input narrow Gaussian functions of equal amplitude is shown in Figure 3.3, showing the influence of efficiency, spectral resolution, and data binning. 16 3.5 3.0 2.5 Counts 2.0 1.5 1.0 0.5 0.060 65 70 75 80 Energy (keV) 85 90 95 Figure 3.3: A model detector response to input narrow Gaussian functions of equal amplitude. Influences of binning of data, detector resolution, and detector efficiency all influence the detector response. Detector signal acquisition Detectors detect photons through the interaction of photons with matter. Photons interact with matter in three significant ways: photoelectric absorption, Compton scattering, and pair production [5]. In photoelectric absorption, an incident photon is completely absorbed by an atom, emitting an electron with energy Ee− = hν − Kb (3.1) where Kb is the binding energy of the electron. The emission of the electron leads to a ’cascade’ of electrons and the production of characteristic X-rays. Compton scattering often is the main interaction process for γ rays produced by typical radioisotopes [5]. A Compton scattered photon may escape the detector before it deposits all of its energy in the detector, producing a continuum of energies as shown in Figure 3.5. Pair production is possible only for γ rays which have greater than twice the rest-mass energy of the electron, 1.02 MeV, so pair production was not a factor in this analysis. 17 A high-purity solid-state germanium detector, preamp, digital spectrometer, and nuclear spectroscopy software, Maestro, are used for data collection. The process by which a photon is counted in a Maestro spectrum takes several steps as shown in Figure 3.4. First, a photon incident on the germanium detector creates electron-hole pairs. The number of electron-hole pairs produced depends upon the energy of the photon and the energy required to create one electron-hole pair. The average energy to create one electron hole pair in germanium is 2.98 eV. Thus, an incident photon at 75.0 keV will most probably produce about 25,000 electron-hole pairs. A high bias-voltage in the detector sweeps out the electrons from the germanium, which create an electrical pulse with an ’RC’ tail. Then, a digital spectrometer (DSPEC) measures the amplitude of the pulse by generating an electric ramp to match the height of the incoming pulse. The height of the ramp increases linearly with time. When the height of the ramp matches the amplitude of the pulse, the DSPEC sends information of the amplitude of the pulse in the form of an address corresponding to the time taken to generate the ramp. Maestro, which is used to control data acquisition, then adds a count to the channel corresponding to that address. vr Δ t i Ramp detector pre-amp DSPEC ci Maestro Figure 3.4: The process of an incident photon being counted in a given channel, ci . The linear speed of the ramp is represented as vr . ∆ti corresponds to channel ci . Spectra seen in the Hg and Pt experiments are shown in Figure 3.5. Counts are collected in channels, so energy calibrations were done through fitting peaks of known energy. Emission lines, such as the X-ray emissions from K-shell transitions, are broadened due to the spectral resolution of HPGe detectors, which is influenced by the intrinsic spread in the number of charge carriers, variation in charge collection efficiency, and electronic noise [5]. The time 18 during which the detector is building the ramp is known as dead-time, as the detector is inactive during this time. Large dead-times, ∼ 30%, can lead to statistical bias and asymmetric peaks. Most dead-times present in counting were below 10%, and all were below 25%, so dead-time correction was not significant. Dead-times in energy calibration measurements were less than 5%. Data 300000 Data 800000 250000 600000 Counts Counts 200000 150000 400000 100000 200000 50000 060 65 70 75 Energy (keV) 80 85 90 060 (a) Hg CLICIT 65 70 75 Energy (keV) 80 85 90 (b) Pt CLICIT Figure 3.5: Spectrum showing the Compton continuum and X-ray and γ ray emission lines produced near 77 keV in the Hg and Pt experiments. 3.2.2 Efficiency calibration measurements Efficiency calibrations were done to determine the efficiency of the detector in counting a photon at a given energy. Commercially produced barium and europium sources with precisely-known activities were used. Also, thallium, terbium, and ytterbium samples were prepared as shown in Table 3.3 to accurately determine the efficiency in the region near 77 keV. Calibration Source Yb Tb Ta Preparation liquid metal foil metal foil Table 3.3: Efficiency sources and method of preparation. Detector efficiency depends upon energy due to the energy dependence of the interaction probabilities of the photoelectric effect, Compton scattering, and pair production [5]. Efficiency also depends on the solid angle ’seen’ by the source. The relationship of spectrum 19 counts, C, to detector efficiency, , branching ratio, b, of the decay, and source activity, a, is C = abt (3.2) where t is the exposure time of an observation. C corresponds to the peak area, as spectral lines are broadened by detector resolution as shown in Figure 3.3. Efficiency as a function of energy for detectors 3 and 4 had to be measured separately for separation distances between the detector and radioactive source of 10 cm, 15 cm, and 20 cm as shown in Figure 3.6. Efficiency 10-2 D3 @ 10 cm D3 @ 15 cm D3 @ 20 cm D4 @ 10 cm D4 @ 15 cm D4 @ 20 cm 10-3 10-4 1 10 102 Energy (keV) 103 Figure 3.6: Detector efficiency as a function of energy. Detector 3 and detector 4 have almost identical efficiencies, and the efficiency increases as the separation distance between the sample and the detector decreases, as expected. 3.3 Modeling the X-ray Emissions A computational routine, “Simulate”, was developed to estimate X-ray emissions present at 77 keV. “Simulate” reads a spectral file, fits spectral lines and constant background specified by the user, and outputs the peak area of a gamma ray peak. Prominent K-shell X-ray emissions from an atom, M (E), are modeled as a summation of Gaussian functions: 20 M (E) = T (E)N (t) 5 X fi (E) (3.3) i=1 where T is the live time, (E) is the efficiency of the detector as a function of energy (E), N (t) is the normalization of each isotope, and fi is the Gaussian function model of a K-shell spectral line: (E − E0i )2 fi (E) = Ai exp 2σi ! (3.4) where A is the normalization constant, E0 is the Gaussian peak energy, and σ is the variance √ of the Gaussian. For HPGe detectors, σi = wscale E, where wscale is a constant, and Ai is the relative intensity of a line as shown in Table 2.3. Relative intensities depend on the number of electrons allowed in each energy level. Spectral emission peaks are better modeled as Gaussian functions with exponential tails, but the uncertainty in modeling Gaussian spectral lines is below the leading uncertainty in each measurement. The model is calculated as a function of energy using a linear conversion of channel number to energy which is extrapolated from a fit to peaks of known energy in the same energy spectrum as the data. This is important as the calibration can vary from measurement to measurement. ’Simulate’ has a simple normalization fitting routine which fits the normalization of a specified model component to match the model spectrum to the data in a given channel. ’Simulate’ also has a spectral resolution fitting routine which minimizes the SP2 earson goodness-of√ fit function in fitting the component wscale in σi = wscale E for a specified spectral region as shown in Figure 3.7, where SP2 earson is defined as SP2 earson = N X (Xi − Mi )2 i Mi2 (3.5) In fitting wscale , the peak heights were first fit in order for the fit to start near the best fit values of the peak heights. 21 3750 3700 3650 3600 χ2 3550 3500 3450 3400 3350 3300 0.0385 0.0390 0.0395 wscale 0.0400 0.0405 0.0410 Figure 3.7: wscale was varied to minimize the chi-square of each data set in a specific energy region. Simulate was used to estimate the prominent X-ray peak heights, estimate their widths, and then subtract their counts, as shown in Figure 3.8. 22 Determine X-ray model 1. Constant background 2. Emission Lines User Choose spectral Lines for fitting data Change parameter Value Simulate Fit Model to Data Calculate model No Fit converged For current parameter? Record Best Fit Parameter Values Yes, fit next parameters Yes, fit done User Fine Tune Fit Subtract Background, Calculate 77 keV peak area Repeat for All runs Calculate Cross section Figure 3.8: ’Simulate’ flowchart. Results of fitting the mercury CLICIT and the platinum CLICIT data with ’Simulate’ is shown in Figures 3.9 and 3.10 and can be compared to Figure 3.5. Subtraction is necessary to calculate the neutron cross sections as X-ray emissions represented 20-40% and 10-40% of the 77 keV peak area in the mercury and platinum data, respectively. 23 Hg, 199 Hg Au Pb 203 Tl bkg1 bkg2 bkg3 bkg4 bkg5 Data Model Difference 197 300000 197 250000 Counts 200000 150000 100000 50000 0 65 75 70 80 Energy (keV) 85 Figure 3.9: Spectral data and spectral model plotted for the Hg CLICIT data. The residuals are plotted in green, which are near zero except where the 77.3 keV γ ray peak is present. 600000 Pt, 195 Pt Ir 199 Hg 197 Au Pb bkg1 bkg2 bkg3 bkg4 Data Model Difference 193 191 500000 Counts 400000 300000 200000 100000 0 60 65 70 75 Energy (keV) 80 85 90 Figure 3.10: Spectral data and spectral model plotted for the last Pt CLICIT run. The 77.3 keV γ ray peak intensity was similar to the background intensity for this run, giving large uncertainty in the γ ray peak area. 24 Chapter 4 Data Analysis Data analysis first involved efficiency calibrations. Then, a procedure for modeling the Xray emissions was developed and implemented. Then, corrections were made to determine the actual activity of each source at the end of bombardment (EOB). Finally, uncertainty in cross section values determined was estimated. 4.1 Efficiency Calibrations Calibration sources of known and unknown activity were used to calibrate detector efficiency. For both europium and barium, which have known activities and branching ratios, efficiency as a function of energy was fit for the high energy region, with E >300 keV, and the low energy region, with E <440 keV (the regions overlap so that the fits match smoothly.) Knowing equation 3.2, energy as a function of efficiency was determined by calculating the peak areas of the γ rays emitted by each calibration source of known activity (Ba, Eu) using Maestro. Fitting this data in the high energy region allowed for the activity of the sources of unknown activity (Ta, Tb, Yb) to be determined. Fitting efficiency for five elements allowed for determination of the detector efficiency in the 77 keV region. Efficiency as a function of energy was fit with a 4th-order polynomial in the low-energy region for each detector configuration as shown in Figure 3.6. 25 Determining non-trivial peak areas Several peak areas required minor calculations in order to determine the true peak area. The peak areas from energy peaks in the 60-90 keV energy range were important to accurately measure in determining the detector efficiency in the region with the 77 keV γ rays. The tantalum 67 keV γ ray peak, which sits on top of X-ray and γ ray peaks, was used in energy calibration. The tantalum 67 keV γ ray peak areas were calculated but values for the efficiency determined from these peak areas ended up increasing the total error in fitting the efficiency for each configuration by about 0.5%. 4.2 Modeling and subtracting X-ray emissions Later data series in each experiment were analyzed, as shown in Table 4.1. This ensured that the activity from 197m Hg, 197m Pt, and many isotopes with short half-lives, with half-lives shown in Table 2.1, were negligible. Exp. HgCL HgTC HgR1 HgR2 PtCL PtTC PtR1 PtR2 Series A, B, C A, B, C A, B, C, D A, B, C, D A, B, C, D A, B, C A, B, C A, B, C Series Analyzed C C D D C, D C C C Table 4.1: Series which were analyzed. For analysis of both the Hg and Pt data, the Compton continuum background was first modeled as a step-function, where the step begins at a value equal to the average value of the 3 channels directly to the left of the X-ray region. The step function takes 3 even steps down to a value equal to the average value of the channels directly on the high energy edge of the X-ray region as shown in Figures 3.9 and 3.10. Then, the normalization and width of the Gaussian line models is estimated by modeling the X-ray peaks and the 77 keV γ ray peak. The best fit width value was then used to simulate the X-ray emissions. 26 In fitting the X-ray peak normalizations and peak widths, the strongest and most isolated peaks were fit first. For example, with the mercury CLICIT data, the 197 Au normalization was first fit so that the Kα2 peak height matches the data in channel 195. This line was chosen because gold dominates the X-ray background, and this peak is isolated, as no other X-ray peaks are at this energy. Next, the Hg normalization is adjusted such that the mercury Kβ3 peak is fit to channel 235. This spectral line is chosen because mercury produces the next strongest X-ray peak after gold in the spectrum, and the only other peak at this energy is from gold, which should be reliably fit. This is additionally done for the Pb Kβ2 peak and the Tl Kα1 peak. In summary, the steps taken to determine the 77 keV peak areas for each spectra are the following: 1. Peaks in spectrum determined 2. Manually estimated Compton background 3. Manually estimated normalization and width of spectral lines 4. Automated fitting normalization and width of spectral lines, in order of most prominent and isolated X-ray peaks. 5. Used best fit normalization and width values to model X-ray emissions and calculate 77.3 keV peak area. Determining the 77 keV peak areas for all runs in the series allowed for the activity at end of bombardment (EOB) of the source to be calculated, which allows for the resonance integral and thermal cross-section to be determined. Corrections to the calculated activity of the Hg and Pt sources had to be made to account for γ ray mass attenuation and meta-stable decays. 27 4.3 γ ray mass attenuation γ rays produced in beta decay are attenuated within the sample itself. For the both experiments, attenuation of the 77 keV γ ray was significant, especially for the HgO powder, where the γ ray intensity was attenuated by 5-15% as shown in Table 4.2. γ ray attenuation was also significant for efficiency calibrations. γ ray attenuation in a material is determined by the mass attenuation coefficient of the material [5]. The relationship of the intensity of the attenuated γ ray beam, I, to an unattenuated beam, I0 , is I = e(−µ/ρ)ρx I0 (4.1) where x is the sample thickness, µ is the linear mass attenuation coefficient, and ρ is the density of the material. µ is a function of energy due to its dependence on the photoelectric effect, Compton scattering, and pair production. µ(E) was determined through a linear fit of ln(µ) as a function of ln(E), from values of µ(E) from NIST [7]. Irradiation CLICIT TC R1 R2 I/I0 HgO Pt 0.946 0.940 0.920 0.940 0.902 0.940 0.843 0.940 Table 4.2: γ ray mass attenuation, I/I0 , at 77.3 keV for Hg and Pt in each experiment. Attenuation fluctuated in the Hg experiments as varying thicknesses of HgO powder were used while a Pt foil was used in the Pt experiments. 4.4 Meta-stable decays In the neutron capture process, an atom is excited into a resonant state. In some isotopes, it then proceeds to a meta-stable state before proceeding to the ground state. The meta-stable state proceeds to the ground state before beta decaying. As a result, some of the activity from the ground state is from atoms which initially started in the meta-stable state. The contribution of the meta-stable state atoms was determined knowing the neutron capture 28 cross section values for the meta-stable state. Then, knowing the initial activity of the ground state, the time elapsed between the end of bombardment (EOB) and start time of detection, and a = λN , an estimate of the contribution of the atoms starting in the metastable state to the ground state activity was estimated. The initial number of meta-stable atoms was about 4% and 10% of the the atoms initially in the ground state, respectively, for 196 Hg and 196 Pt. This added uncertainty to the final cross section determinations. 4.5 Uncertainty and Goodness of Fit of Calculations The resonance integral and thermal cross section are determined knowing Equation 2.3. Uncertainties in quantities used to calculate cross section values were determined from error in published values in the literature and simple error propagation calculations derived in Section 4.6. 4.6 Error Propagation Error propagation is calculated starting with Equation 2.3. In determining the resonance integral, I, the thermal flux is zero. Knowing equation 3.2 gives an independent measure of the activity, which allows for I and the the thermal cross section, σ, to be determined. Solving for the relative uncertainty of determining a for a single run gives δI I 2 = δN0 N0 2 + δa a 2 + δ 2 (4.2) where uncertainty in the activity within a given run is δa a 2 = δC C 2 + δ 2 + δb b 2 (4.3) with C being the 77 keV γ ray peak counts, and b being the branching ratio of the 77 keV γ ray peak. Uncertainty in the activity for a data series of several runs is determined with 29 a weighted chi-square, which gives greater weight to activity values with less uncertainty. Uncertainty in peak counts is q δD2 + δM 2 δC = (4.4) where M is the uncertainty in modeling spectral counts from X-ray emissions. Uncertainty modeling the X-ray emissions was determined as the uncertainty in the model in the channels corresponding to the 77 keV γ ray peak: δM = M s δ 2 + δN (t) N (t) 2 + δσ σ 2 (4.5) where N (t) is the normalization for a given isotope model as shown in equation 3.3. Finite uncertainty in the Gaussian width, about 1%, was present due to uncertainty in fitting. Model uncertainty was insignificant (below 2 %) except for late runs in the Pt CLICIT data where the γ ray peak becomes similar in height to the background as shown in Figure 3.10, resulting in uncertainty near 4% from the model for this data series. The uncertainty in measuring the thermal cross section σ is more complicated because it includes both the thermal and epithermal flux. Uncertainty in σ is determined from equation 2.3 giving δσ σ 2 = Q21 where Q1 = φ δa a 2 + δφth φth a −λti )(e−λt N ) 0 th (1−e 2 + δN0 N0 and Q2 = 2 ! Iφepi φth . 2 2 δI +Q + 2 I φepi φepi !2 + φth φth 2 Thus, the uncertainty in the resonance integral carries into the error in calculating the thermal cross section. This was significant in the case of the PtR1 data, where I is significant compared to σ, and the epithermal flux is only an order-of-magnitude lower than the thermal flux. Significant uncertainty in the resonance integral calculation, about 11 %, caused for uncertainty in the thermal cross 30 section to be near 20% for the PtR1 runs. Multiple measurements of I and σ allowed for the uncertainty in σ to be lowered to 9 % relative uncertainty. Errors are summarized in Table 4.3. Uncertainty Efficiency Peak Statistics Half-life abundance mass branching ratio flux Meta-stable decay 197 Hg 197 Pt 3% 2.0-2.5 % 0.1 % 6% 0.1 % 2% 3% 3% 2.5% 0.5-4.0 % 0.01 % 1.4 % 0.5 % 10% 3% 6% Table 4.3: Uncertainties and relative error in both experiments. The activity of the sample at the beginning of a data series was determined through calculating the expected count rate, xi , for the first data run within a given series. Calculating the uncertainty, δxi , for each run allows for a weighted average of expected count rate, x̄, which is then used to calculate the activity of the source at the end of bombardment (EOB). This also allows for the calculation of the goodness-of-fit of the data to the model of exponential decay through calculating the chi-square, χ2 where χ2 = N X (xi − x̄)2 i (δxi )2 (4.6) Final cross section values and uncertainties were calculated as a weighted-average of the values from each facility. 31 Chapter 5 Results Values for the cross sections of 196 Hg and 196 Pt determined are summarized in Table 5.1. Process 196 Hg → 196 Pt → 197 Hg 197 Pt Resonance integral I (b) Present work Previous work 507 43 558 56 413 15 [8] 409 35 420 42 1010 50 [9] 7.4 9 8.52 94 5.56 44 [8] 6.0 8 7.07 78 6.7 2 [11] Thermal cross section σ (b) Present work Previous work 2089 133 2330 233 2973 180 [8] 3070 290 [10] 0.62 5 0.74 8 0.54 3 [8] 0.61 8 [9] Table 5.1: Cross sections of 196 Hg and 196 Pt. Uncertainties in the least significant digits are given in italics. For example, I= 0.615 54 =0.615±0.054. Two values for the resonance integral are quoted fro the present work due to systematic differences between measurements from the CLICIT and R2 facilities. Values in the second sub column of the present work columns are from analysis of the 191 keV γ ray produced in the decay processes of 196 Hg [12] and 196 Pt [13]. A spectral fitting routine, ’Simulate’, was developed to fit spectral emission peaks. Results of fitting a more complex emission spectrum is shown in Figure 5.1. 32 8000 Ir Pt, 195 Pt 199 Hg 196 Au Pb bkg1 bkg2 bkg3 bkg4 Data Model Difference 191 7000 193 6000 Counts 5000 4000 3000 2000 1000 0 60 65 70 75 Energy (keV) 80 85 90 Figure 5.1: Spectral data and spectral model plotted for the Pt TC data. 33 Chapter 6 Analysis and Discussion Values between the CLICIT and R2 measurements of the resonance integral are systematically different for both experiments. All values agree with the values found by my colleagues within one standard deviation. Values for the Hg resonance integral agree with some historical values and disagree with others while the Hg thermal cross section completely disagrees with historical values. The Pt cross section values determined mostly agree with historical values. Error is similar to past historical measurements due to large uncertainties in the isotopic abundance of processes of 6.1 196 196 Hg and the branching ratio of the 77 keV γ ray in the decay 196 Pt. Hg → 197g Hg Values determined for I are in relative agreement with two reported values in the literature from Kim [10], 413 ± 15 b, and Mughabghab [8], 413 ± 15 b, but largely disagree with the value from Heft, [9] 1010 ± 50 b. Values determined for σ largely disagree with all previous found values in the literature, as all values in the literature report a value near 3000 ± 300 b. The cause of this discrepancy is currently being investigated. 34 6.2 196 Pt → 197g Pt Values determined for I are in agreement with values from Van Der Linden [11], 6.7 ± 0.2 b, and within two standard deviations of the values determined by Mughabghab, 5.56±0.44 b. Values determined for σ agree with literature values determined by Mughabghab, 0.54±0.03 b, and Heft 0.397 ± 0.010 b. The branching ratio used in Heft’s calculation was significantly different than the current accepted value of the branching ratio. Using the correct branching ratio gives a value, 0.610 ± 0.015 b, which agrees well with the present work. 35 Chapter 7 Conclusion The X-ray emissions in neutron capture decay processes of 197 Hg and 197 Pt were analyzed in order to deduce neutron capture cross section values through the analysis of the 77.3 keV γ ray peak intensities. The thermal cross sections for the production of 197 Pt 197 Hg and were found to be 2088 ± 133 b and 0.62 ± 5 b, respectively. These values agree to within a standard deviation of values determined from the analysis of the less intense 191 keV γ ray produced in the production of for the production of 197 Hg and 197 Pt 197 Hg and 197 Pt. Also, the resonance integrals were found to agree with some previous historical measurements and disagree with others. The computational routine, ”Simulate”, can be further applied to follow-up measurements and future cross section measurements at Oregon State University. The routine could be further developed to include more accurate models of γ ray emission lines, such as Gaussian functions with exponential tails, and a function to calculate other physical values such as internal conversion coefficients. 36 Scoping the Science Parameter Space of Future X-ray Astrophysics Calorimeter Missions Chapter 8 Introduction High spectral resolution X-ray spectroscopy will be carried out by future X-ray calorimeter astrophysics missions. The high spectral resolution of the calorimeters developed for the ASTRO-H mission, at 5.0 eV, and the the Advanced X-ray Spectroscopy Imaging Observatory (AXSIO) and Athena mission concepts, below 3.0 eV, combined with high effective area and high spatial resolution will allow future X-ray calorimeter missions to characterize key astrophysical processes, including the effects of strong gravity at black hole accretion disks, black hole spin, and gas and metal outflows from starburst galaxies, which cannot currently be addressed with CCDs on current X-ray missions Chandra and XMM-Newton. The development of the NASA AXSIO mission concept required balancing science goals, budget goals, and several instrument designs. Furthermore, the cosmic X-ray background is spatially dependent, as cosmic X-ray background sources are significantly point-source, unresolved active galactic nuclei (AGN) [14]. Furthermore, statistical certainty is an important consideration in astrophysical data analysis, especially in low-count X-ray astrophysics. To help determine the feasibility of investigating various science topics in X-ray astrophysics with calorimeters, a computational routine, “Drive XSPEC” , was developed to run largescale simulations. 37 Chapter 9 Background High spectral resolution, effective area, and angular resolution X-ray spectroscopy with calorimeter spectrometers was first to be investigated with the International X-ray Observatory (IXO). IXO was a large-scale, international mission concept led by NASA, the European Space Agency (ESA), and the Japanese Aerospace Exploration Agency (JAXA). IXO was to feature 5 new instruments, with one being a high resolution calorimeter-spectrometer. Through a combination of high-spectral resolution, around 2.5 eV, high effective area, and high angular resolution, around 5 arc seconds at 1.0 keV, IXO would have been a significant improvement over current X-ray astrophysics telescopes Chandra and XMM-Newton, which have spectral resolution of 80-150 eV [15]. IXO was to investigate fundamental science topics, including matter near black holes and neutron stars, formation of structure in the universe, and life cycles of matter and energy in the universe. Detector characteristics for calorimeter spectrometer missions as well as XMM-Newton are shown in Table 9.1. The ESA IXO team separated from the NASA IXO team in April 2011 due to US budget outlook concerns and moved to developing their own X-ray mission concept, Athena [18]. The NASA IXO team moved to define a new, NASA-led X-ray mission concept called the Advanced X-ray Spectroscopic Imaging Observatory (AXSIO) to address the key science topics which were to be investigated by IXO. The AXSIO mission concept was fleshed out from the beginning to the end of the proposed mission, including the science topics 38 Instrument XMM-Newton EPIC: PN ASTRO-H SXS AXSIO XMS Athena XMS Spectral Resolution (FWHM) ∼ 80 eV at 1 keV ∼ 150 eV at 6.4 keV 7 eV for 0.3-12 keV Angular resolution 10 arcsec 1.7 arcmin <3.0 eV 10 arcsec < 3.0 eV for E <7.0 keV ∼ AXSIO Effective Area ∼ 1000 cm2 at 1 keV ∼ 900 cm2 at 6 keV ∼ 240 cm2 at 1 keV ∼ 250 cm2 at 6.0 keV 9300 cm2 at 1.25 keV 2000 cm2 at 6.0 keV ∼ AXSIO Table 9.1: spectral resolution, angular resolution, and effective area of calorimeter spectrometer instruments aboard the ASTRO-H [16], AXSIO [17], and Athena [18] missions. XMM-Newton [15], which was launched in 1999 and uses a CCD, is listed for comparison. which would be feasible to address with AXSIO. The AXSIO science team determined the number of physical sources in each science area that could be observed with AXSIO through determining the minimum signal to noise, exposure time, source flux, and other observation requirements for constraining key physical features of X-ray sources. This largely involved determining what science planned for IXO could still be pursued with AXSIO, which had slightly reduced design parameters compared to IXO. 9.1 X-Ray Astrophysics Key AXSIO science includes cataloging black hole spin in active galactic nuclei (AGN) and metal outflows in starburst galaxies. A physical model of an AGN is shown in Figure 9.1. Xrays are produced in the corona of AGN through inverse Compton scattering. The torus of a typical AGN, which is about 3 light years outside the black hole region, is at temperatures around 105 − 106 K, which has a blackbody spectrum peaking in the UV [19]. Some of the UV radiation is emitted toward the corona of the accretion disk, which is at 109 K. Highly energetic particles in the corona inverse Compton scatter off the UV photon, which imparts energy to the UV photon. Assuming the energy of the photon after scattering, E1 , is proportional to the energy of the photon before scattering, E0 , E1 = AE0 , where A is a constant, the energy after n scattering events is En = An E0 . Assuming that the probability, τ , of a scattering event is constant leads to a power-law model for the X-ray flux from the corona of the accretion disk: 39 F (E) = KE −Γ (9.1) where K is a normalization constant and Γ = −lnA/lnτ . X-rays are also produced in photoelectric interactions of particles, significantly iron, in AGN accretion disks, which feel strong gravity and move at relativistic speeds. As a result, emission spectra from iron in AGN accretion disks show energy shifting and broadening due to relativistic and gravitational redshift. Gravitational redshift is most significant in the inner accretion disk, which has at a radius comparable to the Schwarzchild radius of a black hole. Iron does not orbit at radii below the inner most stable orbit of black holes, which is smaller for greater values of the black hole spin, a [20]. High spectral resolution detectors will allow for comparisons of various physical models of black hole accretion disk spectra to be made, including testing whether the relativistically broadened iron line in AGN emission comes from gravitational redshift or from absorption by clumpy material outside the black hole [21]. Cataloging black hole spin will allow for a greater understanding of the formation of stellar-mass black holes, evolution of super massive black holes, and could provide tests for general relativity in strong gravity [20]. 40 (a) AGN physical model. Image Credit: [22] (b) Model emission spectrum of iron in AGN accretion disk. Image Credit: [20] Figure 9.1: Physical model of AGN and energy spectrum from iron in AGN accretion disks. The energy spectral model is shown with the solid line and simulated data is shown with points with error bars. Starburst galaxies have high star-formation rates, temperatures ranging from 106 − 108 K, and galactic scale outflows of gas, energy, and elements, or metals, into the intergalactic medium (IGM) [23]. Key science in starburst galaxies lies in accurately measuring the velocity of galactic scale outflows, which is critical for understanding galactic and IGM evolution. Outflow velocity can be measured from the Doppler-shifting and broadening of spectral lines due to outflows moving in a direction toward and away from the observer as shown in Figure 9.2. Models of hot (T ∼ 106 K) starburst galaxies predict starburst outflow velocity is on the order of 3,000 km/s, requiring calorimeter missions to be able to constrain the velocity of the outflows to within about 100 km/s. Spectral line velocity broadening is unmeasurable if the line broadening profile cannot be determined due to the resolution of the instrument, which is true for current X-ray observatories. Future X-ray calorimeter missions will resolve velocity line broadening and shifting, make it possible to determine whether the outflow velocities are greater than the escape velocity of a galaxy [23]. Measuring starburst galaxy outflows will give a much better understanding of galactic 41 and IGM evolution, including the galaxy mass versus effective yield relationship, which has not yet been satisfactorily explained in astrophysics. (a) Starburst galaxy physical model. Image credit: (b) Model starburst galaxy spectrum. Image credit: [23] [23] Figure 9.2: Physical model and simulated energy spectrum of galactic-scale outflows in starburst galaxies as observed with the IXO calorimeter and Chandra ACIS CCD imager, illustrating improvement in resolving spectral lines with the AXSIO calorimeter. 9.1.1 X-ray background X-ray background for orbiting observatories depends upon contributions from solar system, galactic, and extra-galactic sources. AXSIO and Athena are modeled for an L2 orbit [24]. X-ray background is analyzed in terms of the cosmic X-ray background and non-X-ray background. The X-ray background includes X-rays from local, galactic, and extra-galactic sources [14]. The local background primarily includes line emission from the solar system and the ’Local Hot Bubble.’ The galactic background is primarily line emission and depends significantly on galactic latitude. The extragalactic X-ray background is primarily continuum emission and is spatially dependent, as extragalactic X-ray background sources above 2 keV are significantly point-source, unresolved active galactic nuclei (AGN). The flux from a particular extragalactic background source can be 50 times stronger than the 42 flux from an average source [14]. Non-X-ray background includes particles and and emissions from cosmic rays incident on the telescope and detector. Galactic cosmic rays (GCR) are the expected dominant source for non-X-ray background [14]. GCR activate materials in the telescope. GCR rate is not well known in the solar system but it varies with the solar cycle. Also, the number of particles incident on the X-ray detector varies significantly due to solar activity. It is also relatively flat in the soft X-ray spectral region [18]. Due to these factors, background must be modeled for a given measurement. 43 Chapter 10 Methods Statistical analysis in low-count rate X-ray astrophysics uses the method of forward fitting. ”Drive XSPEC” automates forward fitting of simulated spectra in XSPEC with instrumental parameters, fit model parameters, and fit settings as simulation parameters. Forward fitting involves convolving a spectral model to a detector response, and then fitting the model to the data. Once a fit is performed, parameter error and goodness of fit are determined. 10.1 Forward Fitting XSPEC convolves a physically motivated spectral model, such as the ’bapec’ model of a thermally-ionized, diffuse gas, with a detector response function to produce a simulated spectrum as shown in Figure 10.1 [25]. 44 X Figure 10.1: In fitting physical models to data, XSPEC convolves a physical model with the detector efficiency, the detector response (not shown) of the detector, and the exposure time of an observation to give the ’folded model’. The ’folded model’ is fit to the observed data through minimizing a goodness of fit function. Convolution is represented mathematically as Z ∞ C(I) = T f (E)R(I, E)A(E)dE (10.1) 0 where T is the exposure time of an observation, C is the number of counts in a given instrument channel, I , and f (E) is the source spectrum [25]. R(I, E) and A(E) are the response and effective area of the instrument, where R(I, E) is the probability of a photon of energy E being counted in channel I, and A(E) is the effective area of the detector as a function of energy. Ci represents the observed, or simulated, spectrum. To fit an observed spectrum, a model, M (E) is calculated and convolved with the detector response [25]. 45 Scientists want to fit physical parameterized models, such as ’bapec’, to data. Fitting routines, such as the Levenberg-Marquardt algorithm, adjust model parameter values to minimize a goodness of fit function such as S 2 or C-statistic [26], which describe the goodness of fit of the model to the data. In counting experiments, the counts in each bin in a spectrum can be described to come from a Poisson probability distribution, and in the limit of high count rates, the Gaussian probability distribution. In low count-rate X-ray astrophysics, errors in data are Poisson. The likelihood of data with N channels with Poisson errors given a parameterized model is calculated with the Cash (C) statistic: C = −2L = 2 N X (Mi − Xi lnMi ) (10.2) i where Mi and Xi are the value of the model and data, respectively, in channel i, and L is the likelihood the data arose from the model. Likelihood with data with Gaussian errors is determined using the S 2 statistic [26]. Minimizing a goodness of fit function, which is a function of all model parameters, ~a, involves finding the set of parameters, a~t , that minimize the goodness of fit function. Minima of functions of more than one parameter can be found from the gradient of the function. The Levenberg-Marquardt algorithm finds minima in fitting models by starting at a position in parameter space, a~0 , and following the gradient of the goodness of fit function to a minimum of the function [27]. Because of its dependence on the starting values a~0 and the gradient search method, the Levenberg-Marquardt algorithm is limited to finding relative minima which are not necessarily global minima. A contrived example with one parameter is given in Figure 10.2 [26]. If the gradient search starts at point ’A’, the algorithm will follow the function down to the minimum to the left, which is the global minimum. If the algorithm starts at point ’B’, it will find the relative minimum on the right. 46 Figure 10.2: The problem with the gradient search method for minimizing a goodness of fit function. Fitting low count-rate data has less certainty because many different parameter sets, a~t , can describe the data about equally well, as error in fit parameter values are large. This is analogous to being unable to recognize someone in a photograph taken at night without a flash. Low count rate data especially is where issues with minimization routines such as the Levenberg-Marquardt algorithm are significant. 10.2 Error Fitting Once best fit parameter values are determined , a~t , error in each parameter ai is found by varying the value of each parameter, holding other parameters constant, until the fit function (i.e. χ2 ) changes by a critical value, ∆χ2 . ∆χ2 indicates the confidence level with which the parameter value is quoted [25]. The confidence level depends on the number of degrees of freedom, ν, in the fit. For X-ray spectral data, ν = nc − np , where nc is the number of noticed channels in a spectrum and np is the number of interesting parameters in a fit. For 2 interesting parameters, a confidence level of 90% is associated with ∆χ2 = 4.605 [28]. Critical values for ∆χ2 are determined from the chi-square distribution. Simulations and statistical tests can be used to determine the correct model to describe data. For example, the likelihood ratio test is used to determine whether a more complex, alternative model, m1, can be determined to fit observed data, s1, better than a simpler, 47 null model, m0. In the likelihood-ratio test, s1 is fit with m0 and m1, and the likelihoodratio, lo , is determined [26], where lo is simply the difference in C-statistic for the two fits. Then, a large number of data sets (∼1000) with random errors are simulated to m0 and fit with m0 and m1. The likelihood-ratio, ls is calculated for each simulation s. Finally, the probability, or p-value, of the observed likelihood-ratio is then determined from the distribution of simulated likelihood-ratios. The p-value can be used to accept or reject the more complex model, m1. A p-value below 0.05 rejects the null model [26]. Otherwise, the alternative model is rejected. In general, a more complex model will always fit the data better, giving it a higher likelihood. However, the likelihood-ratio test is used to discern whether a physical feature is being fit or just noise. 10.3 Experimental Approach with ’Drive XSPEC’ ”Drive XSPEC”, is a pyXspec routine which automates error fitting of simulated X-ray spectra for a range of ’simulation parameters’, including fit model parameters, telescope response functions, and source flux. Input simulation parameters include different spectral models and fit models; model parameter values for each spectral model and fit model, including source flux and line equivalent widths; ’fakeit’ settings, including response, arf, and background files; and fit parameters, including channels to ignore. ’Drive XSPEC’ was designed to carry out forward fitting for a large number of simulation parameters and runs. The mechanics of ’Drive XSPEC’ are outlined in Figure 10.3. pyXspec is a Python interface to XSPEC, which is an X-ray spectral-fitting package which has been used in data analysis in X-ray missions since the 1980’s [25]. Analytic and semianalytic models in XSPEC describe the energy spectra produced by high-energy astrophysical processes. For example, the ’kerrdisk’ model describes the Kα emissions near 6.5 keV from highly-ionized Fe present in black hole accretion disks as shown in Figure 9.1b. Also, various thermal and collision-ionized gas models (including ’bapec’) and emission line models (’gaussian’, a Gaussian function) are used to model the thermal plasma and spectral line emission from starburst galaxies as shown in Figure 9.2b. All spectral models 48 typically include photoelectric absorption (’phabs’) and a powerlaw component from AGN (’powerlaw’). Photoelectric absorption is assumed for all models discussed. XSPEC determines best fit model parameter values using the CURFIT Levenberg-Marquardt algorithm [26]. Errors in best fit parameter values are determined with the ’smart fit’ algorithm for 90% confidence level [29]. ’Smart fit’ automates the determination of parameter errors in XSPEC. If a new best fit value is found during this process, ’smart fit’ restarts calculating the confidence regions for the new best fit. This makes it so the XSPEC Levenberg-Marquardt algorithm routine can escape local minima in fitting. Define all simulation values User 'Drive XSPEC' Calculate simulated spectrum (s1) Calculate fit model (m1) Fit model (m1) to data (s1) Change simulation values Figure 10.3: Steps to ’Drive XSPEC’, which automates error fitting in XSPEC. 49 Chapter 11 Results A computational routine, ’Drive XSPEC’, was developed to run statistical tests in fitting astrophysical data. Various simulations were run which show the use of ’Drive XSPEC’. 11.1 Simulations of a Velocity Broadened Thermal-Plasma Model, ’bapec’, with ASTRO-H An example best outlines the usage of ’Drive XSPEC’. Key science in starburst galaxies lies in measuring the velocity outflow of chemical elements, gases, and energy from starburst galaxies. Simulations were run to quantify the exposure time and source flux necessary to constrain the velocity parameter for a model of a velocity- and thermally-broadened emission spectrum from collision-ionized diffused gas, called ’bapec’. ’Bapec’ simulations were run with the ’bapec’ ’Velocity’ parameter being ’thaw’ for fitting and set to 500 km/s along with all of the other parameters as given in Table 11.1. Error in the ’Velocity’ parameter decreases below 100 km/s near 8000 spectral counts as shown in Figure 11.1. 50 spectral model phabs bapec bapec par. name nH kT Abundance parameter values 1.00E+000 5.00E+000 1.00E+000 Units cm−2 keV relative to Solar bapec bapec bapec fakeit settings fakeit settings fakeit settings fakeit settings fit settings fit settings fit settings Redshift Velocity norm Flux 0.5-2.0 keV response arf exposure channels ignored critical delta χ2 fit iterations 0.00E+000 5.00E+002 1.00E+000 2.00E-13 to 1.0E-12 in 10 steps ASTRO-H SXS 5ev base filter ASTRO-H sxt-s with optical filter 2.00E+004 0.0-0.5 10.0-** 0.1 100 km/s ergs / cm2 / s s Table 11.1: Parameter values for the ’bapec’ simulations. 1800 Outflow Velocity (km/s) 1600 ASTRO-H SXS, 5eV base filter 1400 1200 1000 800 600 400 200 0 103 Spectrum Counts 104 Figure 11.1: Results of fitting the ’Velocity’ parameter of simulated ’bapec’ models with ASTRO-H. Error in the ’Velocity’ parameter decreases below 100 km/s near 8000 spectral counts. 51 11.2 ’Bapec’ Simulations with Various ASTRO-H SXS Designs A short simulation for fitting the ’bapec’ ’Velocity’ parameter for different ASTRO-H SXS instrument designs was run. The simulated physical model describes emissions from the southern nucleus of the ultraluminous infrared galaxy (ULIRG) IRAS 192547245 [30]. The ’bapec’ model with outflow velocity set to 250 km/s was used instead of the ’apec’ model. Background was included that was calculated for the ASTRO-H SXS instrument [16]. Simulations were run to illustrate the use of ’Drive XSPEC’ for comparing ASTRO-H spectral resolution and filter design parameters as shown in 11.2. Velocity is better constrained with better resolution, and velocity is better constrained with the thin filter opposed to the base filter. 52 450 ASTRO-H SXS 7eV FWHM, Thin Filter 500 400 300 200 100 00.6 ASTRO-H SXS 4eV FWHM, Base Filter 400 Outflow Velocity (km/s) Outflow Velocity (km/s) 600 350 300 250 200 150 100 50 0.8 1.0 1.2 1.4 1.6 Flux × T (ergs/cm2 ) 1.8 2.0 00.6 2.2 1e 7 (a) SXS 7eV FWHM, Thin Filter. Outflow Velocity (km/s) 400 0.8 1.0 1.2 1.4 1.6 Flux × T (ergs/cm2 ) 1.8 2.0 2.2 1e 7 (b) SXS 4eV FWHM, Base Filter ASTRO-H SXS 4eV FWHM, Thin Filter 350 300 250 200 150 100 500.6 0.8 1.0 1.2 1.4 1.6 Flux × T (ergs/cm2 ) 1.8 2.0 2.2 1e 7 (c) SXS 4eV FWHM, Thin Filter Figure 11.2: Velocity as a function of total flux (ergs/cm2 ) in the 0.5-2.0 keV region for 3 ASTRO-H calorimeter designs. 11.3 Likelihood-ratio Test for an Emission Line in SNR 1987A A likelihood ratio test was run to test for an emission line at 2.43 keV in a spectrum from a 3.3 × 104 s observation of supernova remnant 1987-A with the Chandra ACIS spectrometer. The spectrum was downloaded from XAssist [31]. The spectrum was fit with a null model, an absorbed powerlaw, and an alternative model, an absorbed powerlaw and a Gaussian, as shown in Figure 11.3 below. 1000 simulations to the null model were run, and fit with the best fit values from fitting the alternative and null model to the observed data as shown in Table 11.2. 53 data and folded model data and folded model 1 normalized counts s−1 keV−1 normalized counts s−1 keV−1 1 0.1 0.01 10−3 0.1 0.01 10−3 10−4 3 ratio ratio 2 2 1 1 0.5 1 2 5 0.5 1 Energy (keV) 2 5 Energy (keV) mason 28−May−2012 11:12 mason 28−May−2012 11:11 (a) Null model fit (b) Alternative model fit Figure 11.3: SNR 1987-A spectrum fit with null model, ’powerlaw’, and the alternative model, ’powerlaw+Gaussian.’ Likelihood ratios of fitting null model and alternative model to the spectrum of SNR 1987-A are given in Table 11.3. Distribution of likelihood ratio values from simulations are shown in Figure 11.4. 0% of the simulated likelihood ratio values were above the likelihood ratio from fitting the observed spectrum, so the alternative model can be accepted, which indicates that an emission line is present. Further tests with other models would need to be done to show that an emission line best models the data. 500 simulated 400 Number 300 200 100 02 0 2 4 6 Likelihood Ratio 8 10 12 Figure 11.4: Distribution of likelihood ratio values from simulations. 54 comp name phabs powerlaw powerlaw fakeit settings fakeit settings fakeit settings fit settings fit settings fit settings comp name phabs powerlaw powerlaw Gaussian Gaussian Gaussian powerlaw fakeit settings fakeit settings fakeit settings fit settings fit settings fit settings spectral model, fit model 1 par name par. values nH 3.55E-001 PhoIndex 4.14E+000 norm 4.54E-003 Flux 0.5-2.0 keV 2.30E-012 response Chandra ACIS CCD7 arf Chandra ACIS CCD7 exposure 3.35E+004 channels ignored 0.0-0.5 10.0-** critical delta χ2 0.001 fit iterations 200 spectral model, fit model 2 par name par. values nH 3.72E-001 PhoIndex 4.28E+000 norm 4.77E-003 lineE 2.43E+000 Sigma 1.00E-001 norm 2.68E-005 norm 4.54E-003 Flux0.5-2.0 2.30E-012 response Chandra ACIS CCD7 arf Chandra ACIS CCD7 exposure 3.35E+004 channels ignored 0.0-0.5 10.0-** critical delta χ2 0.001 fit iterations 200 Units cm−2 ergs / cm2 / s s Units cm−2 keV keV relative to Solar ergs / cm2 / s s Table 11.2: Parameter values used for likelihood ratio test simulations. Model null alternative XSPEC model powerlaw powerlaw+Gaussian C-statistic 3349 3217 Likelihood Ratio 132 Table 11.3: Likelihood ratio of fitting null model and alternative model to spectrum of SNR 1987-A. Both models include photon absorption. 55 Chapter 12 Analysis and Discussion In the ’bapec’ simulations in Section 11.1, error in the ’Velocity’ parameter decrease below 100 km/s near 8000 spectral counts. Simulating ’bapec’ alone, with redshift, Z, set to zero, is a simple model, so more physically realistic models would need to be simulated to give more valuable results. However these results are consistent with Strickland et al. 2009, who mention that high-quality X-ray spectra requires more than 1000 spectral counts [23]. Other goodness of fit minimization algorithms could be implemented for improved efficiency and accuracy, such as Markov chain Monte Carlo methods. 56 Chapter 13 Conclusion A computational routine, ’Drive XSPEC’, was developed to help determine the feasibility of pursuing various science goals with future X-ray calorimeter spectrometer missions, most significantly the NASA Advanced X-ray Spectroscopic Imaging Observatory (AXSIO) mission concept.’Drive XSPEC’ can run large scale astrophysical simulations which can be applied to simulating expected observations for developing research proposals, performing data analysis, and comparing instrument designs for current and future X-ray astrophysics missions. This routine may be useful in helping determine the direction of future X-ray calorimeter missions, including ASTRO-H, which will launch in 2014, and the Athena and AXSIO mission-concepts, which should launch by 2028. 57 Bibliography [1] A. Y. Dauenhauer, K. S. Krane, Neutron capture cross sections of Phys. Rev. C 85 (2012) 064301. 130,132,134,136,138 Ba, [2] B. K. Agarwal, X-Ray Spectroscopy, Springer-Verlag, Berlin, 2nd edition, 1991. [3] N. A. Dyson, X-rays in atomic and nuclear physics, Cambridge University Press, New York, 2nd edition, 1990. [4] L. Feldman, J. Mayer, Fundamentals of surface and thin film analysis, North-Holland, 1986. [5] G. Knoll, Radiation Detection and Measurement, John Wiley & Sons, 2010. [6] ORTEC, The maestro story, 2010. [7] J. Hubbell, S. Seltzer, Tables of X-ray mass attenuation coefficients and mass energyabsorption coefficients from 1 keV to 20 MeV for elements Z = 1 to 92 and 48 additional substances of dosimetric interest, 2004. [8] S. F. Mughabghab, Atlas of Neutron Resonances: Resonance Parameters and Thermal Cross Sections Z = 1-100, Elsevier, Amsterdam, 2006. [9] R. Heft, A consistent set of nuclear parameter values for absolute INAA, Conference on Computers in Activation Analysis, edited by R. Farmakes (American Nuclear Society, La Grange Park, IL) (1968) 495. [10] J. Kim, F. Adams, The thermal neutron cross sections and the resonance integrals of 196 Hg and 202 Hg, Radiochimica Acta 8 (1967) 165–169. [11] R. Van Der Linden, F. De Corte, H. J., A compilation of infinite dilution resonance integrals, II, Journal of Radioanalytical Chemistry 20 (1974) 695–706. [12] B. Devlin, Neutron capture cross sections of Hg isotopes (unpublished), TBD. [13] N. Petersen, Neutron capture cross sections of Pt isotopes (unpublished), TBD. [14] R. K. Smith, M. W. Bautz, J. Bookbinder, M. R. Garcia, M. Guainazzi, C. A. Kilbourne, Predicted X-ray backgrounds for the International X-ray Observatory, in: Society of Photo-Optical Instrumentation Engineers (SPIE) Conference Series, volume 7732 of Society of Photo-Optical Instrumentation Engineers (SPIE) Conference Series. [15] ESA, The European photon imaging camera (EPIC) onboard XMM-Newton, 2009. 58 [16] JAXA, ASTRO-H overview., 2008. [17] J. Bookbinder, AXSIO: The advanced X-ray spectroscopic imaging observatory, Physics of the Cosmos Studies (2011) 4–27. [18] ESA, Mission summary, 2012. [19] A. Ptak, Active galactic nuclei: Low resolution X-ray spectroscopy, 2011. [powerpoint slides]. [20] L. Brenneman, J. Miller, P. Nantra, M. Volonteri, M. Cappi, G. Matt, S. Kitamoto, F. Paerels, M. Mendez, R. Smith, M. Nowak, M. Garcia, M. Watson, M. Weisskopf, Y. Terashima, Y. Ueda, Spin and Relativistic Phenomena Around Black Holes, in: astro2010: The Astronomy and Astrophysics Decadal Survey, volume 2010 of ArXiv Astrophysics e-prints, p. 26. [21] L. Miller, T. J. Turner, J. N. Reeves, The absorption-dominated model for the X-ray spectra of typeI active galaxies: MCG-6-30-15, mnras 399 (2009) L69–L73. [22] C. Urry, P. Padovani, Radio-loud AGN model, 2009. NASA HEASARC. [23] D. K. Strickland, A. Hornschemeier, A. Ptak, E. Schlegel, C. Tremonti, T. Tsuru, R. Tüllmann, A. Zezas, Starburst Galaxies: Outflows of Metals and Energy into the IGM, in: astro2010: The Astronomy and Astrophysics Decadal Survey, volume 2010 of ArXiv Astrophysics e-prints, p. 289. [24] ESA, What are lagrange points?, 2009. ESA Space Science. [25] K. Arnaud, B. Dorman, C. Gordon, Xspec: User’s guide for version 12.7.1, 2012. [26] K. Arnaud, R. Smith, A. Siemiginowska, Handbook of X-Ray Astronomy, Cambridge Observing Handbooks for Research Astronomers, Cambridge University Press, 2011. [27] W. Press, Numerical Recipes: The Art of Scientific Computing, Cambridge University Press, 2007. [28] C. Croarkin, P. Tobias (Eds.), Engineering Statistics Handbook, 2012. [29] A. Ptak, XSPEC scripts, 2010. [30] J. Jia, A. Ptak, T. Heckman, V. Braito, J. Reeves, A Chandra observation of the ultraluminous infrared galaxy IRAS 19254–7245 (the Superantennae): X-ray emission from the Compton-thick AGN and the diffuse starburst, ArXiv e-prints (2012). [31] A. Ptak, G. R., XAssist, 2012. [32] ESA, Mission tools, 2012. 59 Appendices 60 Appendix A ’Simulate’ details ’Simulate’ was written in Python. Parameter information and spectral information for each isotope are stored in “isotope” objects. Checks were made to ensure that object attributes were updated as expected in calculations. For example, if an object, a, is created, and then inserted into a list, b, the object in the list and the object originally created are the same object. Modifying an attribute of the object in the list modifies the attribute of the object initially created. Data spectrum and model spectrum information are stored in a “spectrum” object. Peak fitting was automated given the fit parameters. Log files and spectral images for each simulation are created in order to check for errors in fitting. A.1 Code The script used to initiate ’Simulate’ is called ’simulate.py’ as shown in Section A.1.1, and functions used in ’simulate’ are defined in ’model.py’ as shown in Section A.1.2. 61 A.1.1 simulate.py /home/mason/.simulate_x/simulate.py Page 1 of 2 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 Mon 04 Jun 2012 09:02:10 PM PDT #!/usr/bin/env python2.6 import import import import import import numpy as np pylab as pt math time matplotlib.pyplot as plt sys import get_variables as get import model as m import parameters as p t1=time.time() fileroot=sys.argv[1].strip().split('.')[0] fileroot_t0=sys.argv[2].strip().split('.')[0] fit_q=sys.argv[3] # 'yes', it will perform fit. 'no', it will not. fit_w=sys.argv[4] pt1=sys.argv[5] pt2=sys.argv[6] pt3=sys.argv[7] a0_file=sys.argv[8] res_file=sys.argv[9] res_dir=sys.argv[10] pt_o=[pt1, pt2, pt3] sub_spec_f=res_dir+fileroot+'_sub_spec'+'.csv' x_file=res_dir+'X_squares.csv' ###############################################get spectrum spec=p.spec #creating a new variable SHOULD make it so the variable can be modified det1=m.detector('4', p.var['n_c'], p.var['en2ch'], p.var['c0']) # 42 spec=m.model_spectrum(det1, p.var['t_l'], p.dt) 43 print sys.argv, 'THIS IS SYS.ARGV IS READ FROM SIMULATE.PY' 44 45 46 #TODO- read detector information from csv file, not txt file 47 48 spec.get_spectrum(p.c_file_name) 49 50 spec.eff=p.spec.eff 51 52 53 54 isotope_list=m.updated_models(p.isotope_list, spec) 55 56 gammas=p.gammas 57 58 #get_model, subtracted spectra 59 spec.get_model_spectrum('x-ray_energies.csv', isotope_list, gammas) 60 spec.sub_spec=(spec.spectrum[0], spec.spectrum[1], spec.spectrum[2]-spec.C) 61 62 63 #fit peak heights 64 if fit_q=='yes': - 1 - /home/mason/.simulate_x/simulate.py Page 2 of 2 Mon 04 Jun 2012 09:02:10 PM PDT 65 for fit_par in p.fits_list: 66 m.fit(fit_par[0], fit_par[1], spec, isotope_list) 67 68 for fit_par in p.fits_list: 69 print 'CHECK THAT FIT IS DOING WHAT IS SUPPOSED TO' 70 print 'fit channel=%s'%fit_par[1], 'sub spec value in fit channel=', spec.sub_spec[2][f it_par[1]] 71 72 73 74 b=( '!', '!', p.w_scale) 75 if fit_q=='yes': 76 if fit_w=='yes': 77 78 r1=m.roi(p.fit_ran[0], p.fit_ran[1], spec) 79 a=r1.chi_square() 80 b=r1.min_x(isotope_list, p.fits_list, p.w_low, p.w_scale, p.w_high, x_file, p.file root, res_dir) 81 82 83 else: 84 pass 85 86 for iso in isotope_list: 87 if 'gamma' in iso.name: 88 gamma_counts=iso.c 89 90 peak77=spec.sub_spec[2][p.xl_i:p.xh_i] #make it so counts in peak77 spectrum are >= 0 91 for i in range(len(peak77)): 92 if peak77[i]<=0.0: 93 peak77[i]=0.0 94 p_rate=peak77.sum()/p.var['t_l'] 95 96 for iso in isotope_list: 97 print '%s counts in channels %s - %s='%(iso.name, p.xl_i, p.xh_i), iso.c[p.xl_i: p.xh_i ].sum() 98 99 100 unc_isos=[isotope_list[0]] 101 102 103 unc2=m.calc_uncert2(spec, isotope_list, [p.xl_i, p.xh_i], p.w_scale) 104 unc=m.calc_uncert(spec, isotope_list, [p.xl_i, p.xh_i]) 105 m.log_a0s(time.ctime(), p.c_file_name, isotope_list, a0_file, b[2], peak77.sum(), p_rate, [ p.xl_i, p.xh_i] ) 106 c_time=time.ctime() 107 m.log_ga_peak(time.ctime(), res_file, p.c_file_name, p.var['t0_date'], p.var['t0_time'], sp ec.dt, p.var['t_l'], p.var['t_r'], peak77.sum(), unc, unc2, p_rate, b[2]) 108 m.make_sub_spec(sub_spec_f, spec.sub_spec) 109 #d=raw_input('show plot?') 110 111 d='yes' 112 if d=='yes': 113 m.make_plot(spec, p.p_xl, p.p_xh, pt_o, res_dir, p.fileroot, 'yes') 114 else: 115 m.make_plot( spec, p.p_xl, p.p_xh, pt_o, res_dir, p.fileroot, 'no') 116 117 t2=time.time() 118 print 'time to fit=', t2-t1 119 #data - model - 2 - 62 A.1.2 model.py /home/mason/.simulate_x/model.py Page 1 of 19 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 import import import import import import import Mon 04 Jun 2012 03:36:47 PM PDT /home/mason/.simulate_x/model.py Page 2 of 19 54 55 56 57 58 59 60 61 62 63 64 65 66 67 numpy as np pylab as pt math time matplotlib.pyplot as plt matplotlib.ticker as tick sys import get_variables as get sys.path.append('.') #NEED TO INCLUDE CURRENT DIR IN PATH FOR IT TO FIND PARAM ETERS.PY 17 18 19 20 21 usage=\ 22 ''' 23 USAGE: simulate.py spectra spectra_for_t0 fito1 fito2 pt_O1 pt_o2 pto_3 a0file resfile res dir 24 25 simulate.py fits X-ray emissions for lines specified in parameters.py in current directory 26 and calculates peak area for specified channels corresponding to a gamma ray peak with sig nificant x-ray background. 27 28 spectra= spectral csv file 29 spectra_for_t0= spectral csv file corresponding to t0. Should be same as spectral file cur rently 30 fito1= 'yes' fits peak norms specified. 'no' does not fit peak heights 31 fito2- 'yes' fits peak widths . 'no' does not fit peak widths 32 pt_O1- 'ch' or 'e' for channel or energy 33 pt_o2- 'line' or 'bar' - for line or bar plot 34 pto_3- 'all' , 'data', 'model', 'sub' -plot data, model, subtracted spectra, or all toget her 35 a0file- output file name for model norms, peak areas 36 resfile- output file for gamma peak counts 37 resdir- directory for files to be output 38 39 NOTE: a0file, resfile, resdir are generated automatically when running a_all.bash 40 41 42 EXAMPLES: 43 simulate.py PtTCc\#008.csv PtTCc\#008.csv yes no e line model 'a0s.csv' 'peak_areas.csv' r esults/ 44 simulate.py PtCLc\#000.csv PtCLc\#000.csv yes yes ch line all 'a0s.csv' 'peak_areas.csv' r esults/ 45 simulate.py PtTCc\#000.csv PtTCc\#000.csv yes yes e line data 'a0s.csv' 'peak_areas.csv' r esults/ 46 simulate.py HgCLc\$000.csv HgCLc\$000.csv yes yes e line all 'a0s.csv' 'peak_areas.csv' re sults/ 47 simulate.py HgCLc\$000.csv HgCLc\$000.csv yes no e line all 'a0s.csv' 'peak_areas.csv' res ults/ 48 simulate.py PtCLd\#000.csv PtCLd\#000.csv yes yes e line all 'a0s.csv' 'peak_areas.csv' re sults/ 49 simulate.py PtCLd\#008.csv PtCLd\#008.csv yes no e line all 'a0s.csv' 'peak_areas.csv' res ults/ 50 51 52 ''' 53 information=\ ''' steps to simulate.py 2. Read spectrum from spectral data file 1. Read energies and intensities of X-ray peaks from a ./parameters.py, calculate X-ray model using model objects from model.py 3. If fit query 1 = 'yes', fits model to data in specified channels 4. If fit query 2= 'yes', fits spectral lines for sigma 5. Subtract model spectrum from data 6. Output model parameter values to a0_file, output gamma peak area to res_file , width b est fit 68 7. Plot spectrum 69 ''' 70 71 print 'ENTERED SIMULATE...' 72 print sys.argv 73 74 75 if len(sys.argv)<11: 76 print usage 77 print information 78 sys.exit() 79 80 ###BAD CODE BUT EXPEDIENT, THIS IS SETS UP VARIABLES NEED FOR PARMAETERS.PY 81 82 83 fileroot=sys.argv[1].strip().split('.')[0] 84 fileroot_t0=sys.argv[2].strip().split('.')[0] 85 fit_q=sys.argv[3] # 'yes', it will perform fit. 'no', it will not. 86 fit_w=sys.argv[4] 87 pt1=sys.argv[5] 88 pt2=sys.argv[6] 89 pt3=sys.argv[7] 90 a0_file=sys.argv[8] 91 res_file=sys.argv[9] 92 res_dir=sys.argv[10] 93 pt_o=[pt1, pt2, pt3] 94 print pt_o, type(pt_o) 95 96 97 98 99 x_file=res_dir+'X_squares.csv' 100 101 102 103 104 b=tick.ScalarFormatter() 105 b.set_scientific(True) 106 b.set_powerlimits((-2, 2)) 107 108 ############################################### 109 110 111 class detector: 112 def __init__(self, det_n, n_ch, ch2en, ch0): 113 #detector number, number of channels, channel to energy ratio, 114 #and first channel, as defined in the get_variables function 115 self.ch2en=ch2en 116 self.det_n=det_n 117 self.n_ch=n_ch - 1 - /home/mason/.simulate_x/model.py Page 3 of 19 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 - 2 - Mon 04 Jun 2012 03:36:47 PM PDT self.ch0=ch0 class model_spectrum(): #spectrum for models to be defined on def __init__(self, det, t_exp, dt): self.det=det self.dt=dt #time since initial run, to account for change in activity self.t_exp=t_exp #exposure time of curent run self.pt_o=pt_o self.fig=plt.figure() self.ax=self.fig.add_subplot(111, xscale='linear', yscale='linear') self.ax.ticklabel_format(style='sci', scilimits=(0, 0)) # self.w_scale=math.sqrt(3.5e-3) # self.sigma=self.w_scale*math.sqrt(self.E) # d=raw_input() def get_model_spectrum(self, filename, model_list, peak_list): #Reads energy peaks and relative intensity from file 'filename'. #n_c is the number of channels in the spectrum. #plots each individual gaussian. #returns a tuple with three arrays for the total spectrum (channel, energy, counts ) 141 142 143 144 145 146 self.model_list=model_list self.peak_list=peak_list self.C=np.zeros_like(self.CH) #NEEDS TO RESET for recalculation plot_marks=['b-', 'r-','g-', 'c-', 'm-', 'y-', 'k-', 'b--', 'r--','g--', 'c--', ' 'y--', 'k--', 'b--', 'r--','g--', 'c--', 'm--', 'y--', 'k--'] m--', 147 148 i=0 149 pt.cla() #clears matplotlib 150 for model in self.model_list: 151 p_mark=plot_marks[i] 152 # pt.plot(model.E, model.c, p_mark, label=model.name) 153 154 self.C=self.C+model.c #adds each model component to sim spe ctra 155 156 157 158 159 if pt_o[0]=='ch': 160 # print 'YES' 161 # time.sleep(1) 162 163 164 if pt_o[2]=='data' or pt_o[2]=='sub': 165 pass 166 elif pt_o[2]=='model' or pt_o[2]=='all' : 167 self.ax.plot(model.CH, model.c, label=model.name) 168 169 elif pt_o[2]=='model_s': 170 self.ax.plot(model.CH, model.c, label=model.name) 171 ''' 172 for comp in model.comps: 173 pt.plot(comp.ch, model.a*model.spectra.t_exp*model.spectra.eff [comp.xl_i: comp.xh_i]*comp.c, label=comp.name) 174 ''' 175 elif pt_o[0]=='e': 176 177 if pt_o[2]=='data' or pt_o[2]=='sub': 178 pass - 3 - Mon 04 Jun 2012 03:36:47 PM PDT /home/mason/.simulate_x/model.py Page 4 of 19 179 180 181 182 183 184 185 186 187 188 189 Mon 04 Jun 2012 03:36:47 PM PDT elif pt_o[2]=='model' or pt_o[2]=='all': self.ax.plot(model.E, model.c, label=model.name) #print 'PLOTTED' #d=raw_input() elif pt_o[2]=='model_s': nm=1./(model.spectra.eff*model.a*model.spectra.t_exp) self.ax.plot(model.E, nm*model.c, label=model.name, linewidth=2) for comp in model.comps: #pt.plot(comp.e, model.a*model.spectra.t_exp*model.spectra.eff [comp.xl_i: comp.xh_i]*comp.c, '--', label=comp.name) 190 191 self.ax.plot(comp.e, comp.c, '--', label=comp.name, linewidth= 2) 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 i+=1 def get_spectrum(self, filename): #returns the tuple (channels, counts), where the e nergies are in the 2nd column of the file and the channel counts are in the third row in t he file spectra=open(filename, 'r').readlines() channels=[] energies=[] counts=[] #channel number ch2en=[] i_ll=len(spectra)-1 i=0 for line in spectra: if len(line.strip().split(','))<3: #if the line does not have three entries , it does not have the columns I want continue if i==i_ll: #do not include the last line continue if i==2: lin=float(line.strip().split(',')[4].strip('"')) con=float(line.strip().split(',')[5].strip('"')) ch_n=float(line.strip().split(',')[0].strip('"')) energy=float(line.strip().split(',')[1].strip('"')) ch_counts=float(line.strip().split(',')[2].strip('"')) #print ch_n, energy, ch_counts # print type(ch_n) # d=raw_input() channels.append(ch_n) energies.append(energy) counts.append(ch_counts) i+=1 energies=np.array(energies) counts=np.array(counts) channels=np.array(channels) energies=np.array(energies) counts=np.array(counts) self.CH=channels self.E=self.CH*lin+con self.C=np.zeros_like(counts) self.spectrum=(channels, energies, counts) econd is energy array, third is counts array 235 236 237 - 4 - #NOTE, first entry is channel array, s 63 /home/mason/.simulate_x/model.py Page 5 of 19 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 Mon 04 Jun 2012 03:36:47 PM PDT /home/mason/.simulate_x/model.py Page 6 of 19 Mon 04 Jun 2012 03:36:47 PM PDT 259 260 class comp: 261 def __init__(self, name, spectra, roi, pars): 262 self.name=name 263 self.CH=spectra.CH 264 self.E=spectra.E 265 # print self.E 266 # q=raw_input() 267 self.C=spectra.C 268 self.roi=roi 269 self.pars=pars 270 self.spectra=spectra 271 self.xl_i=roi[0] 272 self.xh_i=roi[1] 273 # self.xl_i=int((self.xl-self.spectra.det.ch2en[0])/self.spectra.det.ch2en[ 1]) #starting index of region in X-array 274 # self.xh_i=int((self.xh-self.spectra.det.ch2en[0])/self.spectra.det.ch2en[1]) 275 a='indicies of low, high range %s %s' %(self.xl_i, self.xh_i) 276 # q=raw_input(a) 277 # print 'xl xh: the next two columns should be the same' 278 # print self.xl, self.xh 279 # print self.E[self.xl_i], self.E[self.xh_i] 280 # q=raw_input(a) 281 282 self.ch=self.CH[self.xl_i: self.xh_i] 283 self.e=self.E[self.xl_i: self.xh_i] 284 self.c=np.zeros_like(self.C)[self.xl_i: self.xh_i] 285 286 class constant(comp): 287 def __init__(self, name, spectra, roi, pars): 288 comp.__init__(self, name, spectra, roi, pars) 289 self.a0=pars[0] 290 self.a=self.a0 291 self.c=self.a*np.ones_like(self.c) 292 293 def update_spectrum(self): 294 self.c=np.zeros_like(self.c) #needs to be reset 295 self.c=self.a*np.ones_like(self.c) 296 297 298 class gaussian(comp): 299 def __init__(self, name, spectra, roi, pars): 300 comp.__init__(self, name, spectra, roi, pars) 301 self.x0=pars[0] 302 self.w_scale=pars[1] 303 304 self.sigma=self.w_scale*np.sqrt(self.x0) 305 self.A=pars[2] #count rate 306 self.a=self.A 307 self.c=np.array(self.A*np.exp(-((self.e-self.x0)**2)/(2*self.sigma**2))) 308 309 def update_spectrum(self): 310 self.c=np.zeros_like(self.c) #needs to be reset 311 self.c=np.array(self.A*np.exp(-((self.e-self.x0)**2)/(2*self.sigma**2))) 312 313 314 315 class isotope(model): 316 def __init__(self, name, spectra, roi, parent, comps, pars): 317 model.__init__(self, name, spectra, roi, comps, pars) 318 self.name=name 319 #useful for looking up the theoretical values. 320 self.hl=pars[0] #units = seconds 321 self.a0=pars[1] 322 self.comps=comps 323 self.a=self.a0 324 self.parent=parent 325 self.c=np.zeros_like(self.C) 326 self.calculate_activity(self.spectra.dt) 327 self.update_spectrum() 328 329 330 331 def calculate_activity(self, t): #update the activity for a curren t data set 332 333 self.a=self.a0*math.exp(-(math.log(2.0)/self.hl)*t) 334 335 336 def update_spectrum(self): 337 self.c=np.zeros_like(self.C) #needs to be reset 338 for comp in self.comps: #recalculate peaks 339 self.c[comp.xl_i: comp.xh_i]=self.c[comp.xl_i: comp.xh_i]+self.a*self.spectra. t_exp*self.spectra.eff[comp.xl_i: comp.xh_i]*comp.c 340 341 342 def calc_area(self): 343 pass 344 345 346 347 348 class daughter_isotope(model): 349 def __init__(self, name, spectra, roi, parent, comps, pars, br=0.0): 350 model.__init__(self, name, spectra, roi, comps, pars) 351 self.name=name 352 #useful for looking up the theoretical values. 353 self.hl=pars[0] #units = seconds 354 self.a0=pars[1] 355 self.comps=comps 356 self.a=self.a0 357 self.parent=parent 358 self.c=np.zeros_like(self.C) 359 360 self.calculate_activity(self.spectra.dt) 361 self.update_spectrum() 362 - 5 - - 6 - 255 256 257 258 class model: def __init__(self, name, spectra, roi, comps, pars): self.name=name self.spectra=spectra self.CH=spectra.CH self.E=spectra.E self.C=spectra.C self.ch=np.zeros_like(self.CH) self.e=np.zeros_like(self.E) self.c=np.zeros_like(self.C) self.roi=roi self.comps=comps self.pars=pars # self.xl_i=roi[0] # self.xh_i=roi[1] # self.xl_i=int(np.where(self.E==xl)[0][0]) #starting index of region in X-arr ay # self.xh_i=int(np.where(self.E==xh)[0][0]) # for comp in comps: # print len(self.c[comp.xl_i: comp.xh_i]) # self.c[comp.xl_i: comp.xh_i]=self.c[comp.xl_i: comp.xh_i]+self.spectra.eff[co mp.xl_i: comp.xh_i]*comp.c /home/mason/.simulate_x/model.py Page 7 of 19 363 364 365 Mon 04 Jun 2012 03:36:47 PM PDT /home/mason/.simulate_x/model.py Page 8 of 19 Mon 04 Jun 2012 03:36:47 PM PDT 374 375 376 def calc_area(self): 377 pass 378 379 def calc_chi_square(self): 380 pass 381 382 383 class daughter_isotope_future(isotope): #not sure if this is correct way to inherit 384 def __init__(self, name, spectra, roi, parent, comps, pars, br=0.0): #br=branching ratio. This is the only difference 385 self.br=br 386 self.parent=parent 387 isotope.__init__(self, name, spectra, roi, parent, comps, pars) 388 self.br=br 389 self.parent=parent 390 print 'I HAVE A PARENT', self.parent 391 392 def calculate_activity(self, t): #update the activity for a daught er isotope. I am not quite sure how to account for increase in number due to decays 393 #self.a=self.a0*math.exp(-(math.log(2.0)/self.hl)*t)+self.parent.a*self.br ###T R ETURN TO THIS TO BE MORE ACCUARTE 394 self.a=self.a0*math.exp(-(math.log(2.0)/self.hl)*t) 395 396 397 398 399 400 class shield_isotope(isotope): #isotope made from gamma rays inciden t on detector shield. Usually just copper 401 def __init__(self, name, hl, a0, d_isotopes=[], br=0.0): #br=branching ratio. This is the only difference 402 isotope.__init__(self, name, hl, a0, d_isotopes) 403 self.br=br 404 405 def calculate_activity(self, t): #update the activity for a isoto pe produced in the shielding. I am not quite sure how to account for increase in number du e to decays 406 self.a=self.a0*math.exp(-(math.log(2.0)/self.hl)*t) 407 408 409 410 411 class background(model): 412 def __init__(self, name, spectra, roi, parent, comps, pars): 413 model.__init__(self, name, spectra, roi, comps, pars) 414 self.name=name 415 #useful for looking up the theoretical values. 416 self.hl=pars[0] #units = seconds 417 self.a0=pars[1] 418 self.comps=comps 419 self.a=self.a0 420 self.parent=parent 421 # self.calculate_activity(self.spectra.dt) 422 self.update_spectrum() 423 424 def calculate_activity(self, t): #update the activity for a curren t data set 425 # m=-2.421e-06 426 # self.a=self.a-m*t 427 self.a=self.a0*math.exp(-(math.log(2.0)/self.hl)*t) 428 429 def update_spectrum(self): 430 self.c=np.zeros_like(self.C) #needs to be reset 431 for comp in self.comps: #recalculate peaks 432 self.c[comp.xl_i: comp.xh_i]=self.c[comp.xl_i: comp.xh_i]+self.a*comp.c 433 434 435 436 437 ################FITTING 438 439 440 def updated_models(iso_list, spec): 441 iso_l_n=[] 442 for iso in iso_list: 443 comps=[] 444 # print iso.name 445 for comp in iso.comps: 446 if isinstance(comp, constant)==True: 447 # print comp.name; print comp.xl_i; print comp.xh_i; print comp .pars 448 b=constant(comp.name, spec, comp.roi, [comp.a]) # BACKGROUND DOES NOT CHA NGE WITH THIS FIT 449 #spec.sub_spec[2][180] 450 451 # q=raw_input() 452 pass 453 elif isinstance(comp, gaussian)==True: 454 # print comp.name; print comp.xl_i; print comp.xh_i; print comp .pars 455 # q=raw_input() 456 comp_n=gaussian(comp.name,spec, comp.roi, [comp.x0, comp.w_scale, comp.A]) 457 comps.append(comp_n) 458 459 460 if isinstance(comp, isotope)==True: 461 mod=isotope(iso.name, spec, None, None, comps, [iso.hl, iso.a]) 462 mod=isotope(iso.name, spec, None, None, comps, [iso.hl, iso.a]) 463 if isinstance(iso, background)==True: 464 mod=background(iso.name, spec, None, None, [b], [1.0, 1.0] ) 465 # q=raw_input() 466 iso_l_n.append(mod) 467 return(iso_l_n) 468 469 470 471 472 473 474 475 476 def fit(i_name, ch, spec, iso_list): 477 step_c=10**4.4 # be careful not to make step toO fast 478 ti=time.time() - 7 - - 8 - 366 367 368 369 370 371 372 373 def calculate_activity(self, t): t data set #update the activity for a curren self.a=self.a0*math.exp(-(math.log(2.0)/self.hl)*t) def update_spectrum(self): self.c=np.zeros_like(self.C) #needs to be reset for comp in self.comps: #recalculate peaks self.c[comp.xl_i: comp.xh_i]=self.c[comp.xl_i: comp.xh_i]+self.a*self.spectra. t_exp*self.spectra.eff[comp.xl_i: comp.xh_i]*comp.c 64 /home/mason/.simulate_x/model.py Page 9 of 19 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 Mon 04 Jun 2012 03:36:47 PM PDT for iso in iso_list: if iso.name==i_name: print 'FITTING %s!!!!!!!!!'%iso.name #d=raw_input() /home/mason/.simulate_x/model.py Page 10 of 19 538 539 Mon 04 Jun 2012 03:36:47 PM PDT #spec.ax.plot(spec.spectrum[1], spec.spectrum[2], 'b-', label='data', line #for x axis, 0 for channels, 1 for energy #spec.ax.plot(spec.E, spec.C, 'r', label='X-ray fit ', linewidth=2) #0 f or channels, 1 for energy #spec.ax.plot(spec.sub_spec[1], spec.sub_spec[2], 'g', label='sub. spec', linewidth=3) #spec.ax.axis([60.0, 90.0, 0.0, 2.5e4]) ; pt.xlabel('Energy (keV)', fontsi ze=20) #pt.savefig(res_dir+'fit'+fileroot+'%s.png'%time.time()) width=2) 540 while abs(spec.sub_spec[2][ch])>=1.e-1: 541 542 #DETERMINE STEP# step=(abs(spec.sub_spec[2][ch]))*10.**-5.5*((1/iso.a)*step_c) #defaultif abs(spec.sub_spec[2][ch])<100.0: step=(abs(spec.sub_spec[2][ch]))*10.**-5.5*((1/iso.a)*step_c*5.e-1) if 'gamma' in iso.name: #print 'I AM A GAMMA RAY' d=raw_input() step=(abs(spec.sub_spec[2][ch]))*10.**-5.5*((1/iso.a)*step_c*5.e-2) if iso.a==0.0: iso.a=1e-7 #zero causes problems in step calculation 543 544 545 546 547 548 549 550 551 552 553 554 555 if iso.name=='background': step=(abs(spec.sub_spec[2][ch]))*10.**-5.5*((1/iso.a)*10**-0.0) print '%s fit channel, %s fit energy, sub spec counts, %s norm' %(iso.nam e, iso.name, iso.name) 513 print ch, spec.sub_spec[1][ch], spec.sub_spec[2][ch], iso.a 514 515 #print 'step=', step 516 #STEP value of isotope closer to desired value 517 518 if spec.sub_spec[2][ch]>0.0: 519 #print 'model is low' 520 iso.a=(1.0+step)*iso.a 521 iso.update_spectrum() 522 523 spec.get_model_spectrum('x-ray_energies.csv', iso_list, [], ) #redefi ne gold peak,recalculate model 524 spec.sub_spec=(spec.spectrum[0], spec.spectrum[1], spec.spectrum[2]-sp ec.C) #data - model 525 #print spec.sub_spec[2][ch], iso.a 526 527 elif spec.sub_spec[2][ch]<0.0: 528 #print 'model is high' 529 iso.a=(1.0-step)*iso.a 530 531 iso.update_spectrum() 532 533 spec.get_model_spectrum('x-ray_energies.csv', iso_list, []) #redefin e gold peak ,recalculate model 534 spec.sub_spec=(spec.spectrum[0], spec.spectrum[1], spec.spectrum[2]-sp ec.C) #data - model 535 #print spec.sub_spec[2][195], iso.a 536 # d=raw_input('low') 537 tf=time.time() #print 't=', tf-ti if tf-ti>40.0: print 'FIT TAKING TOO LONG, BREAK' time.sleep(1.0) break if abs(spec.sub_spec[2][ch])>=1.e8: print 'fit is diverging!!' break tf=time.time() delt=tf-ti print '%s fit channel, %s fit energy, final sub spec counts, final %s norm' %( iso.name, iso.name, iso.name) 556 print ch, spec.sub_spec[1][ch], spec.sub_spec[2][ch], iso.a 557 print '%s peak was fit to ch %s in %s seconds' %(iso.name, ch, delt), time.tim e() #MAKE THIS PRINT TO A LOG FILE 558 print 'counts in sub spec in ch %s= '%ch, spec.sub_spec[2][ch] 559 #d=raw_input() 560 561 562 563 class roi: 564 def __init__(self, xl, xh, spec): #detector number, number of channels, channel to e nergy ratio, and first channel, as defined in the get_variables function 565 self.xl=xl 566 self.xh=xh 567 self.spec=spec 568 self.E=spec.E 569 self.xl_i=int((xl-spec.det.ch2en[0])/spec.det.ch2en[1]) #starting index of regio n in X-array 570 self.xh_i=int((xh-spec.det.ch2en[0])/spec.det.ch2en[1]) 571 572 def calc_area(self): 573 pass 574 575 def chi_square(self): 576 C=self.spec.spectrum[2][self.xl:self.xh] 577 Cp=self.spec.C[self.xl:self.xh] 578 x_2=0. 579 for i in range(len(C)): 580 x_2=x_2+((C[i]-Cp[i])**2.)/float(C[i]) 581 return(x_2) 582 583 def min_x(self, iso_list, fits_list, w_low, w_scale, w_high, X_file, fileroot, res_dir ): #minimize chi-square of a region based on width scale 584 x_fil=open(X_file, 'w') 585 s=[] 586 x=[] 587 588 589 for fit_par in fits_list: 590 fit(fit_par[0], fit_par[1], self.spec, iso_list) 591 592 593 w_sc=w_low - 9 - - 10 - 503 504 505 506 507 508 509 510 511 512 # if abs(spec.sub_spec[2][ch])>1.e4: step=0.5*step #step=(abs(spec.sub_spec[2][ch]))*10.**-5.5*((1/iso.a)*step_c*5.e-1) elif abs(spec.sub_spec[2][ch])>1.e5: #this if statement construct ion works, will only enter one if statement step=0.5e-2*step #step=(abs(spec.sub_spec[2][ch]))*10.**-5.5*((1/iso.a)*step_c*5.e-2) elif abs(spec.sub_spec[2][ch])>1.e7: step=0.5e-3*step #step=(abs(spec.sub_spec[2][ch]))*10.**-5.5*((1/iso.a)*step_c*5.e-3) /home/mason/.simulate_x/model.py Page 11 of 19 594 595 596 # 597 598 599 600 601 602 603 604 605 # 606 607 608 # s 609 Mon 04 Jun 2012 03:36:47 PM PDT w0=w_sc print 'w0 fit range: %f %f' %(w_low, w_high) q=raw_input() print 'ENTERED chi square routine' while w_sc<= w_high: print w_sc, w_high iso_l_n=[] for iso in iso_list: comps=[] print iso.name for comp in iso.comps: if isinstance(comp, constant)==True: print comp.name; print comp.xl_i; print comp.xh_i; print comp.par b=constant(comp.name, self.spec, comp.roi, [comp.a]) # BACKGROUND DOES NOT CHANGE WITH THIS FIT 610 #spec.sub_spec[2][180] 611 612 # q=raw_input() 613 pass 614 elif isinstance(comp, gaussian)==True: 615 # print comp.name; print comp.xl_i; print comp.xh_i; print comp.par s 616 # q=raw_input() 617 comp_n=gaussian(comp.name, self.spec, comp.roi, [comp.x0, w_sc, co mp.A]) 618 comps.append(comp_n) 619 620 621 if isinstance(comp, isotope)==True: 622 mod=isotope(iso.name, self.spec, None, None, comps, [iso.hl, iso.a]) 623 mod=isotope(iso.name, self.spec, None, None, comps, [iso.hl, iso.a]) 624 if isinstance(iso, background)==True: 625 mod=background(iso.name, self.spec, None, None, [b], [1.0, 1.0] ) 626 # q=raw_input() 627 iso_l_n.append(mod) 628 iso_list=iso_l_n 629 630 self.spec.get_model_spectrum('x-ray_energies.csv', iso_l_n, []) #this must 631 s.append(w_sc) 632 x.append(self.chi_square()) 633 x_fil.write('%f, ' %w_sc) 634 x_fil.write('%f, \n' %self.chi_square()) 635 # pt.plot(self.spec.spectrum[1], self.spec.spectrum[2], 'b-', label ='data', linewidth=2) #for x axis, 0 for channels, 1 for energy 636 # pt.plot(self.spec.E, self.spec.C, 'r', label='X-ray fit ', linew idth=2) #0 for channels, 1 for energy 637 # pt.plot(self.spec.sub_spec[1], self.spec.sub_spec[2], 'g', label ='sub. spec', linewidth=3) 638 # pt.axis([160, 270, 0.0, 4.5e5]) ; pt.xlabel('Energy (keV)', fonts ize=20) 639 # pt.savefig(res_dir+'X_2'+fileroot+'%s.png'%w_sc) 640 #plotting change in spectrum when changin w_sc 641 w_sc=w_sc*1.0005 642 643 644 # d=raw_input() 645 646 s=np.array(s) 647 x=np.array(x) 648 print 'width scale list', s 649 print 'chi square list', x 650 #x_fil.write('%s\n' %s) - 11 - /home/mason/.simulate_x/model.py Page 12 of 19 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 # # Mon 04 Jun 2012 03:36:47 PM PDT #x_fil.write('%s\n' %x) d=raw_input() print 'minimum chi square', x.min() x0_i=int(np.where(x==x.min())[0][0]) min_w=s[x0_i] print 'minimum width scale, chi-square' print min_w, ',', x.min() q=raw_input() pt.cla() pt.plot(s, x, 'o') pt.xlabel(r'$w_{scale}$') pt.ylabel(r'$\chi^2$', fontsize=20) pt.savefig(res_dir+'X_2'+fileroot+'.pdf') b=(s, x, min_w) x_fil.close() # for iso in iso_list: print iso.name for comp in iso.comps: if isinstance(comp, constant)==True: print comp.name; print comp.xl_i; print comp.xh_i; print comp.par # s 673 continue 674 elif isinstance(comp, gaussian)==True: 675 # print comp.name; print comp.xl_i; print comp.xh_i; print comp.par s 676 # q=raw_input() 677 comp.w_scale=b[2] 678 # self.w_scale=w_scale 679 # d=raw_input('self.w_scale %f' %self.w_scale) 680 comp.sigma=comp.w_scale*np.sqrt(comp.x0) 681 comp.update_spectrum() #NEEDED, OTHER-WISE THESE CHANGES DON'T TAKE PLACE 682 iso.update_spectrum() 683 684 for iso in iso_list: #A CHECK TO SEE IF w_scale is actually being set to the be st fit for final sub_spec calculation 685 for comp in iso.comps: 686 if isinstance(comp, constant)==True: 687 # print comp.name; print comp.xl_i; print comp.xh_i; print comp .pars 688 continue 689 elif isinstance(comp, gaussian)==True: 690 # print comp.name; print comp.xl_i; print comp.xh_i; print comp .pars 691 # q=raw_input() 692 print comp.w_scale 693 694 # self.w_scale=w_scale 695 # d=raw_input('self.w_scale %f' %self.w_scale) 696 print comp.sigma 697 #d=raw_input() 698 699 700 701 self.spec.get_model_spectrum('x-ray_energies.csv', iso_list, []) #redefine gold peak ,recalculate model 702 self.spec.sub_spec=(self.spec.spectrum[0], self.spec.spectrum[1], self.spec.spectr um[2]-self.spec.C) #data - model 703 704 ''' 705 for i in range(len(self.spec.sub_spec[2])): #setting channel to zero 706 if self.spec.sub_spec[2][i]<0: 707 #print self.spec.sub_spec[2][i] - 12 - 65 /home/mason/.simulate_x/model.py Page 13 of 19 Mon 04 Jun 2012 03:36:47 PM PDT 708 self.spec.sub_spec[2][i]=0.0 709 #print self.spec.sub_spec[2][i] 710 #d=raw_input('CHANNEL SET TO ZERO?') 711 ''' 712 713 return(b) 714 715 716 717 def calc_uncert(spec, iso_list, roi): 718 #simple uncertainty calculation, with uncertainty in Peak = Gamma Area + Background 719 720 counts=0.0 721 counts+=spec.spectrum[2][roi[0]:roi[1]].sum() 722 print 'HERE IS is data uncertainty : %f' %np.sqrt(counts) 723 for iso in iso_list: 724 c=iso.c[roi[0]:roi[1]].sum() 725 counts+=c 726 727 unc=np.sqrt(counts) 728 print 'HERE IS simple UNCERTAINTY CALC : %f' %unc 729 return(unc) 730 731 732 733 def calc_uncert2(spec, iso_list, roi, w_scale): #more exact uncertainty, attempting to ac count for uncertainty in sigma and efficiency. 734 counts_t=spec.spectrum[2][roi[0]:roi[1]].sum() 735 print 'total spectrum counts=', counts_t 736 dr_eff=0.03 #relative uncertainty in efficiency 737 d_w=0.0005 #absolute uncertainy in w_scale, where Gaussian sigma= w_scale *sqrt(E) 738 counts=0.0 739 mcounts=0.0 740 counts+=spec.spectrum[2][roi[0]: roi[1]].sum() 741 d_2=0.0 742 back_c=0.0 743 for iso in iso_list: 744 print 'UNCERTAINTIES FOR', iso.name 745 if np.sqrt(iso.c[roi[0]:roi[1]].sum())==0.0: 746 pass 747 elif isinstance(iso, background)==True: 748 db=np.sqrt( iso.c[roi[0]:roi[1]].sum() ) 749 print 'back uncertainty=', db 750 d_2+=db**2 751 else: 752 753 parea=iso.c[roi[0]:roi[1]].sum() 754 mcounts+=parea 755 dra=np.sqrt ( 1./np.sqrt(parea)) 756 drn_i=np.sqrt ( 1./iso.a ) 757 drw= ( (d_w/iso.comps[0].w_scale) ) 758 dp=parea*np.sqrt( dr_eff**2 + drn_i**2 + drw**2 ) 759 print 'iso.a', iso.a 760 print dr_eff, drn_i, drw 761 print 'uncertainty factor', np.sqrt( dr_eff**2 + drn_i**2 + drw**2 ) 762 #dp=1./(np.sqrt( ((iso.c[roi[0]:roi[1]])/(spec.eff[roi[0]:roi[1]])).s um() )) 763 764 print '%s peak area='%iso.name, iso.c[roi[0]:roi[1]].sum(), 'sqrt peak area (m in uncertainty)=', np.sqrt(iso.c[roi[0]:roi[1]].sum()) 765 print '%s peak uncertainty ='%iso.name, dp 766 d_2+=dp**2 767 #counts+=c 768 ''' 769 for ch in range(roi[0], roi[1]+1): /home/mason/.simulate_x/model.py Page 14 of 19 for iso in iso_list: #A CHECK TO SEE IF w_scale is actually being set to th e best fit for final sub_spec calculation 771 if isinstance(iso, background)==True: 772 db=iso.c[ch] 773 dr_2+=db 774 else: 775 #print 'iso name, iso a', iso.name, iso.a 776 dr_p=1./np.sqrt(iso.a) 777 dr_g=d_w/(iso.comps[0].x0*iso.comps[0].w_scale**3.) 778 dr_2+=iso.c[ch]**2.*(dr_eff**2.+dr_p**2.+dr_g**2.) 779 ''' 780 unc_m=np.sqrt(d_2) 781 runc_m=unc_m/mcounts 782 print 'HERE IS model uncertainty (abs, rel)=' , unc_m, runc_m 783 unc=np.sqrt((counts)+unc_m**2) 784 print 'HERE IS THE attempt at error prop. UNCERTAINTY CALC : %f' %unc 785 #d=raw_input('check the uncertainty') 786 return(unc) 787 788 789 790 ##################RECORDING RESULTS 791 792 793 def log_a0s(t_now, c_file_name, isotope_list, a_log_file, w_bf, p_area, p_rate, roi): 794 a_log=open(a_log_file, 'a') 795 a_log.write('an_time, spectra_file,' ) 796 for iso in isotope_list: 797 a_log.write( "%s, a, total counts, 77counts, " %(iso.name)) 798 a_log.write('best_fit_w_scale, peak_area, ') 799 for iso in isotope_list: 800 for comp in iso.comps: 801 a_log.write( "%s, %s," %(iso.name, comp.name)) 802 a_log.write('\n') 803 804 a_log.write('%s,' %(t_now)) 805 a_log.write('%s,' %c_file_name) 806 for iso in isotope_list: 807 a_log.write( "%s, %f, %f, %f, " %(iso.name, iso.a, iso.c.sum(), iso.c[roi[0]: roi[ 1]].sum())) 808 a_log.write('%f,' %w_bf) 809 a_log.write( "%f," %(p_area)) 810 for iso in isotope_list: 811 for comp in iso.comps: 812 a_log.write( "%s," %(comp.roi)) 813 a_log.write("\n") 814 815 a_log.close() 816 817 818 def log_ga_peak(t_now, log_file, sp_file, t0_date, t0_time, t, t_l, t_r, area, unc, unc2, rate, w_bf ): 819 g_log=open(log_file, 'a') 820 # g_log.write('%s, %s, %s, %f, %f, %f, %f, %f, %f\n' %(log_file, sp_file, t0_date, t0_t ime, t, area, rate, w_bf, t_l, t_r) ) 821 g_log.write('an_time, spec_file, t0_date, t0_time, dt, peak_area, unc, unc2, peak_rate , bf_w_scale, live_time, run_time\n') 822 g_log.write( '%s,%s,%s,%s,%f,%f,%f,%f, %f, %f, %f,%f\n' %(t_now, sp_file, t0_date, t0 _time, t, area, unc, unc2, rate, w_bf, t_l, t_r)) 823 824 g_log.close() 825 826 827 def make_sub_spec(sub_spec_f, sub_spec): 828 csv_file=open(sub_spec_f, 'w') - 13 - /home/mason/.simulate_x/model.py Page 15 of 19 829 830 - 14 - Mon 04 Jun 2012 03:36:47 PM PDT for i in range(len(sub_spec[2])): csv_file.write('%f, %f, %f\n ' %(sub_spec[0][i], /home/mason/.simulate_x/model.py Page 16 of 19 Mon 04 Jun 2012 03:36:47 PM PDT spec') sub_spec[1][i], sub_spec[2][i]) ) 831 csv_file.close() 832 833 #########################PLOTTING 834 835 836 837 838 def make_plot( spec, p_xl, p_xh, pt_o, res_dir, fileroot, shq, c_max=1.e6): 839 840 fig = spec.fig 841 ax0 = spec.ax 842 843 if pt_o=='no': 844 pass 845 846 if pt_o[0]=='ch': 847 848 if pt_o[1]=='line': 849 850 if pt_o[2]=='data': 851 ax0.plot(spec.spectrum[0], spec.spectrum[2], 'b-', label='Data', linewidth =2) #for x axis, 0 for channels, 1 for energy 852 c_max=spec.spectrum[2][p_xl[0]:p_xh[0]].max()*1.05 853 elif pt_o[2]=='model': 854 ax0.plot(spec.CH, spec.C, 'r', label='Model ', linewidth=2) #0 for channe ls, 1 for energy 855 c_max=spec.spectrum[2][p_xl[0]:p_xh[0]].max()*1.05 856 elif pt_o[2]=='sub': 857 ax0.plot(spec.sub_spec[0], spec.sub_spec[2], 'g', label='Difference', lin ewidth=2) 858 elif pt_o[2]=='all': 859 860 ax0.plot(spec.spectrum[0], spec.spectrum[2], 'b-', label='Data', linewidth =2) #for x axis, 0 for channels, 1 for energy 861 ax0.plot(spec.CH, spec.C, 'r', label='Model', linewidth=2) #0 for channe ls, 1 for energy 862 ax0.plot(spec.sub_spec[0], spec.sub_spec[2], 'g', label='Difference', lin ewidth=2) 863 864 if spec.C.max()>spec.spectrum[2].max(): 865 c_max=spec.C.max()*1.05 866 else: 867 c_max=spec.spectrum[2][p_xl[0]:p_xh[0]].max()*1.05 868 869 870 elif pt_o[1]=='bar': 871 width=spec.spectrum[0][2]- spec.spectrum[0][1] 872 873 if pt_o[2]=='data': 874 ax0.bar(spec.spectrum[0], spec.spectrum[2], width, color='b', label='data' ) 875 elif pt_o[2]=='model': 876 ax0.bar(spec.CH, spec.C, width, color='r' , label='X-ray fit') 877 elif pt_o[2]=='sub': 878 ax0.bar(spec.sub_spec[0], spec.sub_spec[2], width, color='g', label='sub. spec') 879 elif pt_o[2]=='all': 880 881 ax0.bar(spec.spectrum[0], spec.spectrum[2], width, color='b', label='data' ) 882 ax0.bar(spec.CH, spec.C, width, color='r' , label='Model') 883 ax0.bar(spec.sub_spec[0], spec.sub_spec[2], width, color='g', label='sub. - 15 - Mon 04 Jun 2012 03:36:47 PM PDT 770 884 885 886 887 888 889 890 891 892 893 894 ax0.axis([p_xl[0], p_xh[0], spec.sub_spec[2].min(), c_max]) ; pt.xlabel('Chann els', fontsize=20) #for channels #pt.axis([0, p_xh[0], spec.sub_spec[2].min(), c_max]) ; pt.xlabel('Channels', fontsize=20) #for channels elif pt_o[0]=='e': if pt_o[1]=='line': if pt_o[2]=='data': ax0.plot(spec.spectrum[1], spec.spectrum[2], 'b-', label='Data', linewidth #for x axis, 0 for channels, 1 for energy c_max=spec.spectrum[2][p_xl[0]:p_xh[0]].max()*1.05 print spec.spectrum[2], c_max #d=raw_input() #c_max=4.e4 elif pt_o[2]=='model': ax0.plot(spec.E, spec.C, 'r', label='Model', linewidth=2) #0 for channels , 1 for energy c_max=spec.C.max()*1.05 elif pt_o[2]=='sub': ax0.plot(spec.sub_spec[1], spec.sub_spec[2], 'g', label='Difference', lin ewidth=2) elif pt_o[2]=='all': =2) 895 896 897 898 899 900 901 902 903 904 905 =2) 906 ax0.plot(spec.spectrum[1], spec.spectrum[2], 'b-', label='Data', linewidth #for x axis, 0 for channels, 1 for energy ax0.plot(spec.E, spec.C, 'r', label='Model', linewidth=2) #0 for channel s, 1 for energy 907 ax0.plot(spec.sub_spec[1], spec.sub_spec[2], 'g', label='Difference', lin ewidth=3) 908 909 910 911 912 913 914 915 916 917 918 919 920 921 if spec.C.max()>spec.spectrum[2].max(): c_max=spec.C.max()*1.05 else: #c_max=spec.C.max()*1.05 c_max=spec.spectrum[2][p_xl[0]:p_xh[0]].max()*1.05 elif pt_o[1]=='bar': width=spec.spectrum[1][2]- spec.spectrum[1][1] if pt_o[2]=='data': ax0.bar(spec.spectrum[1], spec.spectrum[2], width, color='b', label='data ') 922 923 924 925 elif pt_o[2]=='model': ax0.bar(spec.E, spec.C, width, color='r' , label='X-ray fit') elif pt_o[2]=='sub': ax0.bar(spec.sub_spec[1], spec.sub_spec[2], width, color='g', label='sub. s pec') 926 927 928 elif pt_o[2]=='all': width=spec.spectrum[1][2]- spec.spectrum[1][1] ax0.bar(spec.spectrum[1], spec.spectrum[2], width, color='b', label='data' ) 929 930 ax0.bar(spec.E, spec.C, width, color='r' , label='X-ray fit') ax0.bar(spec.sub_spec[1], spec.sub_spec[2], width, color='g', label='sub. spec') 931 932 933 934 935 #c_max=0.5 ax0.axis([p_xl[1], p_xh[1], spec.sub_spec[2].min(), c_max]) pt.xlabel('Energy (keV)', fontsize=20) - 16 - 66 /home/mason/.simulate_x/model.py Page 17 of 19 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 Mon 04 Jun 2012 03:36:47 PM PDT pt.ylabel('Counts', fontsize=20) pt.grid(True) pt.legend() plt.savefig(res_dir+fileroot+'.pdf') 993 994 995 996 997 998 999 #plot residuals elif pt_o[2]=='model': ax.bar(spec.E, spec.C, width, color='r' , label='X-ray fit') elif pt_o[2]=='sub': ax.bar(spec.sub_spec[1], spec.sub_spec[2], width, color='g', label='sub. sp ec') 1004 1005 1006 1007 1008 if pt_o=='no': pass elif pt_o[2]=='all': width=spec.spectrum[1][2]- spec.spectrum[1][1] ax.bar(spec.spectrum[1], spec.spectrum[2], width, color='b', label='data') ax.bar(spec.E, spec.C, width, color='r' , label='X-ray fit') ax.bar(spec.sub_spec[1], spec.sub_spec[2], width, color='g', label='sub. spec') if pt_o[0]=='ch': if pt_o[1]=='line': /home/mason/.simulate_x/model.py Page 19 of 19 1054 Mon 04 Jun 2012 03:36:47 PM PDT ax.bar(spec.sub_spec[0], spec.sub_spec[2], width, color='g', label='sub. s elif pt_o[2]=='all': ax.bar(spec.spectrum[0], spec.spectrum[2], width, color='b', label='data') ax.bar(spec.CH, spec.C, width, color='r' , label='Model') ax.bar(spec.sub_spec[0], spec.sub_spec[2], width, color='g', label='sub. spec') ax.axis([p_xl[0], p_xh[0], spec.sub_spec[2].min(), c_max]) ; pt.xlabel('Channe ls', fontsize=20) #for channels #pt.axis([0, p_xh[0], spec.sub_spec[2].min(), c_max]) ; pt.xlabel('Channels', fontsize=20) #for channels 1064 1065 1066 1067 1068 1069 elif pt_o[0]=='e': th=2) 1070 1071 1072 1073 1074 1075 1076 1077 if pt_o[1]=='line': ax.plot(spec.spectrum[1], spec.spectrum[2]/spec.C, 'bo', label='Data', linewid #for x axis, 0 for channels, 1 for energy c_max=(spec.spectrum[2][p_xl[0]:p_xh[0]]/spec.C[p_xl[0]:p_xh[0]]).max()*1.05 elif pt_o[1]=='bar': width=spec.spectrum[1][2]- spec.spectrum[1][1] if pt_o[2]=='data': ax.bar(spec.spectrum[1], spec.spectrum[2], width, color='b', label='data' ) 1078 1079 1080 1081 elif pt_o[2]=='model': ax.bar(spec.E, spec.C, width, color='r' , label='X-ray fit') elif pt_o[2]=='sub': ax.bar(spec.sub_spec[1], spec.sub_spec[2], width, color='g', label='sub. sp ec') 1082 1083 1084 1085 1086 elif pt_o[2]=='all': width=spec.spectrum[1][2]- spec.spectrum[1][1] ax.bar(spec.spectrum[1], spec.spectrum[2], width, color='b', label='data') ax.bar(spec.E, spec.C, width, color='r' , label='X-ray fit') ax.bar(spec.sub_spec[1], spec.sub_spec[2], width, color='g', label='sub. spec') ax.axis([p_xl[1], p_xh[1], 0.0, c_max]) ; pt.xlabel('Energy (keV)', fontsize=20) pt.ylabel('Ratio', fontsize=20) pt.grid(True) pt.legend() plt.savefig(res_dir+fileroot+'_res.pdf') ''' ''' # set some legend properties. All the code below is optional. The # defaults are usually sensible but if you need more control, this # shows you how leg = plt.gca().get_legend() ltext = leg.get_texts() # all the text.Text instance in the legend llines = leg.get_lines() # all the lines.Line2D instance in the legend frame = leg.get_frame() # the patch.Rectangle instance surrounding the legend # see text.Text, lines.Line2D, and patches.Rectangle for more info on # the settable properties of lines, text, and rectangles - 19 - 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 ax.axis([p_xl[1], p_xh[1], 0.0, c_max]) ; pt.xlabel('Energy (keV)', fontsize=20) pt.ylabel('Residual Counts', fontsize=20) pt.grid(True) pt.legend() plt.savefig(res_dir+fileroot+'_res.pdf') ''' ###PLOT RATIO ax = spec.fig.add_subplot(212, xscale='linear', yscale='linear') if pt_o=='no': pass if pt_o[0]=='ch': if pt_o[1]=='line': th=2) 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 data/model ''' ax.plot(spec.spectrum[0], spec.spectrum[2]/spec.C, 'b-', label='Data', linewid #for x axis, 0 for channels, 1 for energy if spec.C.max()>spec.spectrum[2].max(): c_max=spec.C.max()*1.05 else: c_max=spec.spectrum[2][p_xl[0]:p_xh[0]].max()*1.05 elif pt_o[1]=='bar': width=spec.spectrum[0][2]- spec.spectrum[0][1] if pt_o[2]=='data': ax.bar(spec.spectrum[0], spec.spectrum[2], width, color='b', label='data') elif pt_o[2]=='model': ax.bar(spec.CH, spec.C, width, color='r' , label='X-ray fit') elif pt_o[2]=='sub': - 18 - pec') 1055 1056 1057 1058 1059 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 elif pt_o[1]=='bar': width=spec.spectrum[1][2]- spec.spectrum[1][1] if pt_o[2]=='data': ax.bar(spec.spectrum[1], spec.spectrum[2], width, color='b', label='data' 1000 1001 1002 1003 ax = spec.fig.add_subplot(212, xscale='linear', yscale='linear') - 17 - 1063 Mon 04 Jun 2012 03:36:47 PM PDT c_max=spec.sub_spec[2].max()*1.05 ) ''' ax.plot(spec.spectrum[0], spec.spectrum[2], 'b-', label='Data', linewidth=2) #for x axis, 0 for channels, 1 for energy 960 ax.plot(spec.CH, spec.C, 'r', label='Model', linewidth=2) #0 for channels, 1 for energy 961 ax.plot(spec.sub_spec[0], spec.sub_spec[2], 'g', label='Difference', linewidt h=2) 962 963 if spec.C.max()>spec.spectrum[2].max(): 964 c_max=spec.C.max()*1.05 965 else: 966 c_max=spec.spectrum[2][p_xl[0]:p_xh[0]].max()*1.05 967 968 969 elif pt_o[1]=='bar': 970 width=spec.spectrum[0][2]- spec.spectrum[0][1] 971 972 if pt_o[2]=='data': 973 ax.bar(spec.spectrum[0], spec.spectrum[2], width, color='b', label='data') 974 elif pt_o[2]=='model': 975 ax.bar(spec.CH, spec.C, width, color='r' , label='X-ray fit') 976 elif pt_o[2]=='sub': 977 ax.bar(spec.sub_spec[0], spec.sub_spec[2], width, color='g', label='sub. s pec') 978 elif pt_o[2]=='all': 979 980 ax.bar(spec.spectrum[0], spec.spectrum[2], width, color='b', label='data') 981 ax.bar(spec.CH, spec.C, width, color='r' , label='Model') 982 ax.bar(spec.sub_spec[0], spec.sub_spec[2], width, color='g', label='sub. spec') 983 984 985 ax.axis([p_xl[0], p_xh[0], spec.sub_spec[2].min(), c_max]) ; pt.xlabel('Channe ls', fontsize=20) #for channels 986 #pt.axis([0, p_xh[0], spec.sub_spec[2].min(), c_max]) ; pt.xlabel('Channels', fontsize=20) #for channels 987 988 elif pt_o[0]=='e': 989 990 991 if pt_o[1]=='line': 992 ax.plot(spec.sub_spec[1], spec.sub_spec[2], 'g', label='Difference', linewidt h=2) 1060 1061 1062 /home/mason/.simulate_x/model.py Page 18 of 19 67 Appendix B XSPEC and ’Drive XSPEC’ details B.1 Example XSPEC Models X-ray spectra are influenced by photoelectric absorption of X-rays by material in the line of sight between the X-ray source and the detector. Photoelectric absorption is described simply as exponential attenuation as P (E) = (exp((−nH σ(E)) (B.1) where σ(E) is the photo-electric cross-section of the material in the intergalactic medium between the source and the detector and nH = n∆r, where n is the density of material and ∆r is the distance between the source and the telescope. Photon absorption has only one parameter, nH , which is the equivalent hydrogen column density [25]. Emission lines produced by K, L, and M electronic transitions in atoms present in a source (typically highlyionized Fe, O, Ne, Si, S and Mg emission lines in observations in the 0.4-10 keV band) are broadened due to the detector spectral resolution and response function. Emission lines can 68 be modeled as Gaussian functions. The X-ray emission from the accretion disk of a black hole can be modeled as M (E) = (phabs[powerlaw + kerrdisk] + B(E)) (B.2) where B(E) is the X-ray background. The X-ray background model used in AXSIO simulations of the Non-X-ray background and the diffuse X-ray background had two thermal plasma components, ’MEKAL’, and one power law component. This background model was scaled from a typical X-ray and non-X-ray background reported by the Athena science team [32]: B(E) = (A × phabs × [B × powerlaw + M EKAL + M EKAL]) (B.3) where ’phabs’ and ’powerlaw’ are represented in equations B.1 and 9.1, and ’MEKAL’ is a continuum model very similar to ’bapec’. Parameter values used for the X-ray background for AXSIO simulations are shown in Table B.1. The first parameter, ’constant’, depends upon the detector detection cell size, which for AXSIO is 10”. ’MEKAL’ is a thermal plasma model similar to ’bapec.’ Athena and ASTRO-H response functions included are publicly available and the AXSIO response was calculated by Dr. Ptak. B.2 Counting Error In counting experiments, the counts in each bin in a spectrum can be described to come from a Poisson probability distribution with a mean value corresponding to the value of a model in the given bin: PP (n; µ) = e−µ µn n! (B.4) 69 component number 1 2 3 4 5 6 component parameter number parameter constant, A phabs constant, B powerlaw powerlaw mekal mekal mekal mekal mekal mekal mekal mekal mekal mekal mekal mekal 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 factor nH factor PhoIndex norm kT nH Abundance redshift switch norm kT nH Abundance redshift switch norm units 1022 keV cm-3 keV cm-3 value 1.90000E-009 2.00000E-002 9.00000E-001 1.42000E+000 1.11000E+001 2.04000E-001 1.00000E+000 1.00000E+000 0.0 1 7.59000E+000 8.10000E-002 1.00000E+000 1.00000E+000 0.0 1 1.16000E+002 Table B.1: The background model used in AXSIO calculations. where the probability of n events is given for a mean µ. With Poisson statistics, the likelihood of data given a parameterized model is calculated with the Cash (C) statistic. The Poisson distribution becomes the Gaussian distribution in the limiting case where µ becomes large: −(x−µ)2 1 PG = √ e 2σ2 σ 2π (B.5) With Gaussian statistics, the likelihood is calculated with the S 2 statistic, which is often called χ2 [26], where 2 S = N X (Xi − Mi )2 i σi2 where σ is the variance of the Gaussian distribution describing the data in channel i. (B.6) 70 B.3 Code The script used to initiate ’Drive XSPEC’ is called ’drive xspec.py’ as shown in Section B.3.1, and functions used in ’Drive XSPEC’ are defined in ’dx comm.py’ as shown in Section B.3.2. 71 B.3.1 drive xspec.py /home/mason/.xspec/drive_xspec.py Page 1 of 1 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 Mon 04 Jun 2012 09:05:44 PM PDT #!/usr/bin/env python2.6 import sys import time from dx_comm import * usage=\ ''' usage: drive_xspec.py sim_settings.csv Assumes that smart_fit scripts, drive_xspec.py, and dx_comm.py are located in ~/.xspec drive_xspec is a routine for automating xspec simulations over all sets of user provided par ameters, including model parameter values, fakeit settings, fluxes, eqwidths, and fit setti ngs as specified in sim_settings_template.csv. ''' try: dlm=sys.argv[2] except IndexError: dlm=',' try: sfq=sys.argv[3] except IndexError: sfq='y' try: lrq=sys.argv[4] except IndexError: lrq='n' if len(sys.argv)<2: print usage sys.exit() else: m_file=sys.argv[1] date="%s"*6 %(tuple(time.localtime()[0:6])) s=setup_drive(m_file, dlm) sd=sim_driver(s[0], s[1], s[2], s[3], sfq) print 'FILE prefix=', s[1]+date if lrq=='y': sd.drive_xspec2(s[4]) else: sd.drive_xspec(s[4]) - 1 - 72 B.3.2 dx comm.py /home/mason/.xspec/dx_comm.py Page 1 of 30 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 Mon 04 Jun 2012 03:36:01 PM PDT from xspec import * from math import * import time import os import itertools import random import sys import csv #do not adjust norms; do adjust fluxs def logspace(low, high, nvalues): values=[] low=log(low) high=log(high) step=(high-low)/nvalues value=low for i in range(1, nvalues): values.append(value) value=value+step #based of numpy, numpy module wouldn't load /home/mason/.xspec/dx_comm.py Page 2 of 30 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 def linspace(low, high, nvalues): values=[] step=(high-low)/nvalues value=low for i in range(1, nvalues): values.append(value) value=value+step 88 89 90 91 92 93 94 def test(q='n', s='query'): if q=='y': if s=='query': d=raw_input('press enter to continue') else: try: time.sleep(s) except TypeError: pass else: pass 95 96 97 98 99 100 101 102 103 104 ############ 105 tq='n' #if 'y', this will show all run drive xspec in test mode, showing all the debuggi ng steps s1=0.3 #amount of time (s) for drive xspec to pause at each step s2=0.5 106 107 108 ############ #maybe make ranges arrays so they can only have one type of object #don't change the par_index, unless you are confident class sim_parameter: def __init__(self, name='', par_range=[0.1, 1.0], nsteps=1, par_index=-1, log_flag=Tru e, flux_flag=False, eqwidth_flag=False, defaults=False, link='', frozen=False): #info is extra info that can be accessed for some specific purpose 61 self.defaults=defaults 62 if defaults==True: 109 # 110 # 111 112 113 114 115 116 117 118 119 elif self.log_flag==False: self.values=self.linspace(self.par_range, self.nsteps) elif type(self.par_range[0][0])==type('str'): self.values=self.par_range else: print "values should be int, float, str, list, or tuple only" self.value=self.values[0] def logspace(self, par_range, nsteps): values=[] if nsteps==0 or len(par_range)==1: value=par_range[0] - 1 - /home/mason/.xspec/dx_comm.py Page 3 of 30 - 2 - Mon 04 Jun 2012 03:36:01 PM PDT 120 values.append(value) #to give it at least one value 121 return(values) 122 else: 123 low=par_range[0] 124 if low==0.0: 125 low=1.e-8 #math errors with ln(0) 126 low=log(low) 127 128 high=log(par_range[1]) 129 value=low 130 step=(high-low)/float(nsteps) 131 for i in range(nsteps+1): 132 values.append(e**value) 133 value=value+step 134 return(values) 135 def linspace(self, par_range, nsteps): 136 values=[] 137 if nsteps==0 or len(par_range)==1: 138 value=par_range[0] 139 values.append(value) #to give it at least one value 140 return(values) 141 else: 142 143 low=par_range[0] 144 high=par_range[1] 145 step=(high-low)/float(nsteps) 146 value=low 147 for i in range(nsteps+1): 148 values.append(value) 149 value=value+step 150 return(values) 151 def set_flux(self, old_flux, new_flux): 152 old_norm=self.value 153 print 'old flux', old_flux 154 print 'new_flux', new_flux 155 new_norm=old_norm*(new_flux/old_flux) 156 print 'new_norm', new_norm 157 self.model.__dict__[comp].norm.values=new_norm 158 print self.model.__dict__[comp].norm.values[0] 159 AllModels.calcFlux('0.5 2.0') 160 test(tq, s1) 161 162 print 'setting flux' 163 test(tq, s1) 164 165 166 167 168 class sim_component: 169 def __init__(self, name='', sim_parameters=[], file_prefix=''): s are sim_parameter objects 170 self.name=name 171 self.parameterNames=[] 172 self.sim_parameters=sim_parameters 173 # self.parameter_values=[] 174 self.file_prefix=file_prefix 175 self.comp_index=-1 176 self.flux_flag=False 177 self.eqwidth_flag=False 178 self.comptype=-1 179 #attempt to not have to name parameters 180 ''' 181 try: 182 dmod=Model(self.name) #dummy model, additve models 183 self.comptype=+1 - 3 - Mon 04 Jun 2012 03:36:01 PM PDT pass # self variables all become default elif defaults==False: self.name=name self.frozen=frozen self.par_range=par_range self.nsteps=nsteps self.log_flag=log_flag self.par_index=-1 #FOR AN INITAL VALUE FOR SIMULATION self.set_values() self.info='' self.link=link self.best_fit=0.0 self.err_low=0.0 self.err_high=0.0 # for norms if flux_flag==True: #only give it a flux flag if it is true self.values=[1e-5] #give it one value self.flux_flag=flux_flag self.eqwidth_flag=eqwidth_flag if eqwidth_flag==True: self.values=[1e-5] self.info='eqwidth'+'%s' %(self.par_index) self.eqwidth_flag=eqwidth_flag self.flux_flag=flux_flag #make sure to set it true def set_values(self): #make list of values, self.values, and intial value in s im, self.value print 'self.par_range', self.par_range print 'type', type(self.par_range) print 'type list entries', type(self.par_range[0]) print 'lf=', self.log_flag if type(self.par_range)!=type(['list']): print "self.par_range must be a list" elif type(self.par_range)==type(['list']) or type(self.par_range)==type(('tup', 'l e')): if len(self.par_range)>2: self.values=self.par_range elif type(self.par_range[0])==type(1.0) or type(self.par_range[0])==type(1): if self.log_flag==True: self.values=self.logspace(self.par_range, self.nsteps) elif self.log_flag==False: self.values=self.linspace(self.par_range, self.nsteps) elif type(self.par_range[0])==type('str'): self.values=self.par_range elif type(self.par_range[0])==type(['list']) or type(self.par_range[0])==type( ('tup', 'le')): #one value may have two items example-->('arf, rmf') if type(self.par_range[0][0])==type(1.0) or type(self.par_range[0])==type( 1): #I don't think I will ever have this situation, where par_range=[ [0.0, 3.0], [1.0, 4.0]) print "go back to sim_parameter class and figure out what to do if you have par_pange=[ [0.0, 1.0], [1.0, 2.0] ] float inside list inside list" # if self.log_flag==True: # self.values=self.logspace(self.par_range, self.nsteps) /home/mason/.xspec/dx_comm.py Page 4 of 30 184 185 186 187 188 189 190 191 192 193 194 195 196 197 #argument Mon 04 Jun 2012 03:36:01 PM PDT except Exception: try: dmod=Model(self.name+'*(pow)') #dummy model, all else self.comptype=+1 except Exception: print 'NOT AN XSPEC MODEL, MUST BE OTHER SIM SETTINGS' ''' ii=1 for sim_par in sim_parameters: ''' if self.comptype==+1: sim_par.name=dmod(ii).name #makes it so sim par name does not need to be spelled correctly ''' self.__dict__[sim_par.name]=sim_par #name becomes actual attribute of com ponent self.parameterNames.append(sim_par.name) # self.parameter_values.append(sim_par.values) ii+=1 self.nParameters=len(self.parameterNames) # for additive model components only try: self.norm self.flux_flag=False self.eqwidth_flag=False if self.norm.flux_flag==True: self.flux_flag=True if self.norm.eqwidth_flag==True: self.eqwidth_flag=True except AttributeError: pass 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 self.check_par_values() 215 216 def check_par_values(self): 217 218 print 'parameter values for', self.name 219 for par in self.sim_parameters: 220 print 'par name=', par.name 221 print 'par values=', par.values 222 print 'parameter values above will be input into simulation' 223 print 'CHECK THAT %s VALUES WERE INPUT CORRECTLY'%self.name 224 test(tq) 225 226 227 228 class file_manager: 229 def __init__(self, fileroot=''): 230 self.a=open('dummy_file', 'w') 231 self.name='files' 232 self.fileroot=fileroot 233 self.file_names=[] 234 def add(self): #probably want to do this at the end of the s imulations 235 236 for thing in self.__dict__: 237 print thing 238 if type(self.__dict__[thing])==type(self.a): #if there is a file in files, ap pend it to list 239 self.file_names.append(self.__dict__[thing].name) 240 def close_files(self): 241 self.a=open('dummy_file', 'w') 242 print type(self.a) 243 for thing in self.__dict__: 244 print thing - 4 - 73 /home/mason/.xspec/dx_comm.py Page 5 of 30 245 Mon 04 Jun 2012 03:36:01 PM PDT if type(self.__dict__[thing])==type(self.a): #if there is a file in files, cl ose it 246 247 248 249 250 251 252 self.__dict__[thing].close() def open_files(self): self.a=open('dummy_file', 'w') print type(self.a) for thing in self.__dict__: print thing if type(self.__dict__[thing])==type(self.a): #if there is a file in files, op en it 253 self.__dict__[thing]=open(self.__dict__[thing].name, 'a') 254 255 256 257 258 259 260 class sim_settings: 261 262 def __init__(self, model_expr="", telescope="", model_settings=[], other_settings=No ne, fakeit_settings=None, fit_settings=None ): #args are arguments 263 Xset.allowNewAttributes=True #will have to add to fit_models_settings after the fact, if I want to add ss1, ss2, ss3... 264 self.telescope=telescope 265 self.date="%s"*6 %(tuple(time.localtime()[0:6])) 266 self.date=self.date[:len(self.date)-1] 267 self.name="" 268 self.model=Model(model_expr) #CREATES PYXSPEC MODEL OBJECT 269 self.model_expr=model_expr #useful to keep track of later, when writing xspec fi le for smart fit 270 self.sim_id=1 271 self.model_id=1 #these numbers change during the simula tion 272 self.spec_id=1 273 self.mod_flag=False 274 self.fmod_flag=False 275 self.run=1 276 self.sim=1 277 # self.drive_id=int(floor(self.spectrum_id/20)) #for spreading out drive_s mart_fit calculations, to speed thigns up 278 self.model_settings=model_settings 279 # self.fit_models_settings=fit_models_settings #[this could be tough, save t his for later) 280 self.fakeit_settings=fakeit_settings 281 self.fit_settings=fit_settings 282 self.other_settings=other_settings 283 self.fit_model=model #how to do this? 284 self.comp_index=1 285 self.par_index=1 286 self.parameter_ranges=[] 287 self.parameter_values=[] #for simulations, this will be filled with curren t values 288 self.parameterNames=[] 289 self.componentNames=[] 290 self.nComponents=0 291 self.nParameters=0 292 self.index=1 293 print 'BUILDING SIM_SETTINGS COMP LIST' 294 for sim_comp in self.model_settings: 295 print 'sim comp name', sim_comp.name 296 # comp_obj=self.model.__dict__[comp] 297 self.__dict__[sim_comp.name]= sim_comp 298 self.__dict__[sim_comp.name].comp_index=self.comp_index 299 self.componentNames.append(sim_comp.name) 300 self.comp_index+=1 /home/mason/.xspec/dx_comm.py Page 6 of 30 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 print 'BUILDING A PAR LIST FOR %s'%self.other_settings.name for sim_par in self.other_settings.parameterNames: # # # # # # # # self.parameter_ranges.append(self.other_settings.__dict__[sim_par].values) self.parameterNames.append(self.other_settings.__dict__[sim_par].name) self.other_settings.__dict__[sim_par].par_index=self.par_index print 'par, par index' print sim_par, self.other_settings.__dict__[sim_par].par_index self.par_index+=1 test(tq, s1) self.other_settings.comp_index=self.comp_index self.componentNames.append(self.other_settings.name) self.comp_index+=1 for fit_model in self.fit_models: #CHANGE FOR FIT MODELS self.parameter_ranges.append(self.fakeit_settings.__dict__[sim_par].values) self.parameterNames.append(self.fakeit_settings.__dict__[sim_par].name) self.fakeit_settings.__dict__[sim_par].par_index=self.par_index self.par_index+=1 self.fit_settings.comp_index=self.comp_index self.componentNames.append(self.fit_settings.name) self.comp_index+=1 print 'BUILDING A PAR LIST FOR %s'%self.fakeit_settings.name for sim_par in self.fakeit_settings.parameterNames: self.parameter_ranges.append(self.fakeit_settings.__dict__[sim_par].values) self.parameterNames.append(self.fakeit_settings.__dict__[sim_par].name) self.fakeit_settings.__dict__[sim_par].par_index=self.par_index print 'par, par index' print sim_par, self.fakeit_settings.__dict__[sim_par].par_index self.par_index+=1 self.fakeit_settings.comp_index=self.comp_index self.componentNames.append(self.fakeit_settings.name) self.comp_index+=1 print 'BUILDING A PAR LIST FOR %s'%self.fit_settings.name for sim_par in self.fit_settings.parameterNames: self.parameter_ranges.append(self.fit_settings.__dict__[sim_par].values) self.parameterNames.append(self.fit_settings.__dict__[sim_par].name) self.fit_settings.__dict__[sim_par].par_index=self.par_index print 'par, par index' print sim_par, self.fit_settings.__dict__[sim_par].par_index self.par_index+=1 self.fit_settings.comp_index=self.comp_index - 5 - /home/mason/.xspec/dx_comm.py Page 7 of 30 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 Mon 04 Jun 2012 03:36:01 PM PDT print '%s comp index'%(sim_comp.name), sim_comp.comp_index print 'BUILDING A PAR LIST FOR %s'%sim_comp.name par_n=1 for sim_par in self.model.__dict__[sim_comp.name].parameterNames: #THIS MAKE S IT SO YOU DO NOT HAVE TO MAKE RANGES FOR ALL PARAMETERS. CHANGE THIS IF IT IS HELPFUL TO DO SO FOR READING VALUES FROM A SPREADSHEET print 'sim_par name=', sim_par try: self.__dict__[sim_comp.name].__dict__[sim_par] #AT TEMPT TO MAKE IT SO ONLY INTERESTING PARAMETERS CAN BE LISTED, and do same thing self.parameter_ranges.append(sim_comp.__dict__[sim_par].values) #IT LOOKS LIKE try: tryies every statement, even if one didn't work self.parameterNames.append(sim_comp.__dict__[sim_par].name) self.__dict__[sim_comp.name].__dict__[sim_par].par_index=self.par_inde x print '%s par index='%sim_par, self.__dict__[sim_comp.name].__dict__[s im_par].par_index self.par_index+=1 except KeyError: print 'parameter %s was forgotten in csv setup file'%(sim_par) sys.exit() - 6 - Mon 04 Jun 2012 03:36:01 PM PDT self.componentNames.append(self.fit_settings.name) self.comp_index+=1 #FILES TO WRITE for sim_comp in self.model_settings: for par in sim_comp.parameterNames: print self.nComponents=len(self.componentNames) self.nParameters=len(self.parameterNames) for comp in self.model.componentNames: self.name=self.name+comp #self.name=self.name[:len(self.name)-1] #cuts of _ at end self.fit_model_name=self.name #CHANGE, WHEN YOU FIGURE OUT FIT MODELS for i in range(1, self.nParameters+1): try: print 'par name', 'par index CHECKME' print self(i).name, self(i).par_index except AttributeError: print 'Attribute error, object type' print type( self(i)), dir( self(i)) def __call__(self, par_index): for sim_comp in self.componentNames: for sim_par in self.__dict__[sim_comp].parameterNames: fo=-1 if self.__dict__[sim_comp].__dict__[sim_par].par_index==par_index: fo=1 return self.__dict__[sim_comp].__dict__[sim_par] #THIS WORKS IF THE SIM_INDEX IS SETUP CORRECTLY /home/mason/.xspec/dx_comm.py Page 8 of 30 420 421 422 Mon 04 Jun 2012 03:36:01 PM PDT #file prefixes self.files.spec_root=self.files.fileroot+"_%s_%s_"%(self.model_id, self.sim)#!!!!! ! need to change name# self.files.sim_root=self.files.spec_root+"_fit_"+self.fit_model_name #!!!!!!!!!# once fit model aded, need to change self.files.run_root=self.files.sim_root+"_run%s" %str(self.run) #print 'run root', self.files.run_root print 'making spec file name for, self.name' test(tq, s1) 396 self.spec_id=1 397 self.run=1 398 self.sim=1 399 def reset_sim(self): #between runs, and before, make sure settings are what I want 400 Fit.statMethod='cstat' 401 Fit.query='on' 402 #AllData.clear() 403 #AllModels.clear() 404 def make_files(self, dr=''): 405 #if dr=='def': 406 # dr=self.date+'/' 407 self.files=file_manager(fileroot=dr+self.name) #fileroot created 408 #os.system("mkdir %s" %self.files.fileroot) #can be saved to later 409 #print self.fakeit_settings.response.value[0] 410 #this will give astro_h, axsio, etc. 411 #instrument_files=['res/astr/a.rmf', 'res/astr/b.arf', 'dumm/astr/.back'] 412 #instrument=instrument_files[0].split('/')[1] 413 #instrument gives 'astr' 414 # self.file_dir=self.sim_dir+"%s/"%(instrument) #will allow for drive smart fit t o be run for each instrument 415 # os.system("mkdir "+self.file_dir) 416 #SOME FILES NEED TO BE IN THE SAME WORKING DIRECTORY AS WHERE DRIVE XSPEC IS EXECU TED 417 self.files.add() #add files to filename list 418 419 def make_run_files(self, pre): #write model info values to csv file, must be run after model has been defined 423 424 425 426 427 428 #Opened files 429 #Files to be supplied to during drive_xspec 430 # self.files.spec_file_bkg=self.files.spec_root+"_bkg"+".fak" don't need for pyx spec 431 self.files.xspec_setup_name=self.files.run_root+"_setup.xcm" 432 #setup file is for setting up model to be fed into run_smart_fit 433 self.files.model_file=self.files.spec_root+".xcm" 434 rn=str(random.random()) 435 rn_s=rn[len(rn)-9:len(rn)] #TAKE THIS OUT IF IT MAKES FILE NAMES TOO LONG 436 self.files.spec_file=pre+self.files.spec_root+str(rn_s)+"_bkg.fak" 437 self.files.xspec_log=self.files.run_root+"_xspec_log"+".log" 438 self.files.sim_graph=self.files.run_root+".ps" 439 self.files.sim_data_file=self.files.run_root+".xcm" 440 self.files.smart_fit_log=self.files.run_root+".log" 441 442 443 def set_model(self): 444 print 'ENTERED set_model' 445 AllModels.clear() 446 #AllModels+=self.model 447 self.model=Model(self.model_expr) # 448 #AllModels.calcFlux('0.5 2.0') 449 ''' 450 for comp in self.model.componentNames: 451 if self.__dict__[comp].eqwidth_flag==True: 452 AllModels.eqwidth(self.__dict__[comp].comp_index) 453 ''' #pretty certain I DO NOT WANT TO DO THIS 454 print 'par name, value, frozen, link' 455 for i in range(1, self.model.nParameters+1): 456 self.model(i).values=self(i).value 457 self.model(i).link=self(i).link 458 self.model(i).frozen=self(i).frozen 459 test(tq, s1) 460 461 print self.model(i).name, self.model(i).values[0], self.model(i).frozen, self. model(i).link 462 test(tq, s1) 463 464 def set_flux(self): #and set value for flux 2.0 10.0 465 print 'ENTERED set_flux' 466 for comp in self.model.componentNames: 467 if self.__dict__[comp].flux_flag==True: #norm flag triggers comp flag, which makes it so that the range of the norm are flux ranges 468 #AllModels.calcFlux(self.flux.__dict__['flux0.5-2.0'].info) 469 AllModels.calcFlux('0.5 2.0') #will give flux FOR CURRENT MODEL 470 old_norm=self.model.__dict__[comp].norm.values[0] 471 print 'old norm', old_norm 472 #old_flux=self.model.flux[0] 473 old_flux=AllData(1).flux[0] #flux is stored in spectrum after a spectrum is defined 474 AllModels.show() 475 476 print 'old flux', old_flux 477 test(tq) 478 new_flux=self.other_settings.__dict__['flux0.5-2.0'].value #this - 7 - - 8 - 386 387 388 389 390 391 392 393 394 395 else: pass if fo==-1: print 'ERROR: sim_settings.__call__ did not work properly!' def reset_ids(self): self.sim_id=1 self.model_id=1 #these numbers change during the simula tion 74 /home/mason/.xspec/dx_comm.py Page 9 of 30 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 Mon 04 Jun 2012 03:36:01 PM PDT alue is a flux value, not a norm value print 'new_flux', new_flux new_norm=old_norm*(new_flux/old_flux) print 'new_norm', new_norm self.model.__dict__[comp].norm.values=new_norm print self.model.__dict__[comp].norm.values[0] AllModels.calcFlux('0.5 2.0') print 'flux should be' , new_flux, 'CHECK' test(tq) else: pass def get_flux_high(self): print 'ENTERED get_flux_high' AllModels.calcFlux('2.0 10.0') self.other_settings.__dict__['flux2.0-10.0'].value=AllData(1).flux[0] print 'flux 2.0 10.0 sim_par value was set to ', self.other_settings.__dict__['flu x2.0-10.0'].value def set_eqwidths(self): print 'ENTERED set_eqwidths' for comp in self.model.componentNames: if self.__dict__[comp].eqwidth_flag==True: #norm flag triggers co mp flag, which makes it so that the range of the norm are flux ranges print 'flux flag for %s is %s'%(comp, self.__dict__[comp].eqwidth_flag) print'comp index=', self.__dict__[comp].comp_index #print AllModels(1).componentNames test(tq, s1) AllModels.eqwidth(self.__dict__[comp].comp_index) # self.__dict__[comp].norm.set_eqwidth(old_EW, new_EW) old_norm=self.model.__dict__[comp].norm.values[0] print 'old norm', old_norm old_EW=AllData(1).eqwidth[0] #STORED IN SPECTRUM OBJECT, NEED HOW TO FIGURE OUT EXACT SPECIFICS OF TJHIOS print old_EW new_EW=self.other_settings.__dict__['eqwidth%s' %(self.__dict__[comp].comp _index)].value #EQUIVALENT WIDTH NAME HAS TO BE 'eqwidthn, where n is the the component n umber in the model that it applies to. Otherwise, the equivalent width will not be set. print new_EW new_norm=old_norm*(new_EW/old_EW) print new_norm self.model.__dict__[comp].norm.values=new_norm print 'new norm value', self.model.__dict__[comp].norm.values[0] AllModels.eqwidth(self.__dict__[comp].comp_index) print 'new EW SHOULD BE' , new_EW, 'check above' test(tq) else: pass ########################## def set_fakeit(self, nSpectra): #nSpectra is num of spectra for model to be applied to (same as definition of fakeit command) #m=Model(self.model.name, self.model.name) #self.model=m self.model.show() print('LOOK AT MODEL, CHECK ALL VALUES, CHECK THAT MODEL IS ACTIVE. FOR FAKEIT TO WORK, IT MUST BE ACTIVE') test(tq) test(tq) self.fs1=FakeitSettings() #creates fakeit settings object self.fs1.response=self.fakeit_settings.response.value self.fs1.arf=self.fakeit_settings.arf.value self.fs1.background=self.fakeit_settings.background.value self.fs1.exposure=str(self.fakeit_settings.exposure.value) #rn=str(random.random()) /home/mason/.xspec/dx_comm.py Page 10 of 30 #rn_s=rn[len(rn)-4:len(rn)] #self.files.spec_file=self.files.spec_file.split('.')[0]+str(rn_s)+".fak" os.system('rm -f %s' %(self.files.spec_file)) #to ensure file is created, remove p rior file 539 self.fs1.fileName=self.files.spec_file 540 print 'fakeit settings spectral filename=', self.fs1.fileName 541 test(tq, s1) 542 AllData.fakeit(nSpectra, [self.fs1, self.fs1]) 543 544 AllData.show() 545 print 'fake spectra created above to', self.fs1.fileName 546 print 'CHECK: fake spectra name and spectra name SHOULD MATCH' 547 if self.mod_flag==True: 548 print 'this is SPEC MODEL' 549 if self.fmod_flag==True: 550 print 'this is FIT MODEL' 551 test(tq) 552 def set_fit(self): 553 554 Fit.query='yes' 555 556 AllData(1).ignore(self.fit_settings.ignore.value) 557 AllModels(1).untie() #UNTIE MODELS FOR FIT 558 Fit.delta=0.01 559 Fit.nIterations=100 560 print 'DATA TO BE FIT' 561 AllData.show() 562 try: 563 564 Fit.perform() 565 566 except Exception: 567 pass 568 self.model.show() 569 570 def check_id(self): #see if model changed, if so, changed id number THI S IS DOES NOT WORK WELL 571 try: 572 a=self.parameter_values 573 b=self.old_parameter_values 574 np=self.model.nParameters 575 nop=self.other_settings.nParameters 576 nfkp=self.fakeit_settings.nParameters 577 nftp=self.fit_settings.nParameters 578 mv=a[0:np] 579 omv=b[0:np] 580 print mv 581 print omv 582 test(tq, s1) 583 os=a[np:np+nop] 584 oos=b[np:np+nop] 585 print os 586 print oos 587 test(tq, s1) 588 fks=a[np+nop:np+nop+nfkp] 589 ofks=b[np+nop:np+nop+nfkp] 590 print fks 591 print ofks 592 test(tq, s1) 593 fts=a[np+nop+nfkp:np+nop+nfkp+nftp] 594 ofts=b[np+nop+nfkp:np+nop+nfkp+nftp] 595 print fts 596 print ofts 597 598 - 9 - /home/mason/.xspec/dx_comm.py Page 11 of 30 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 if Mon 04 Jun 2012 03:36:01 PM PDT 536 537 538 - 10 - Mon 04 Jun 2012 03:36:01 PM PDT mv!=omv: self.model_id+=1 self.spec_id+=1 /home/mason/.xspec/dx_comm.py Page 12 of 30 Mon 04 Jun 2012 03:36:01 PM PDT 625 626 627 628 629 630 631 632 def set_fit_model_values(self): 633 pass #MAKE IT SO YOU CAN ITERATE OVER ALL PARAMETERS 634 635 def run_smart_fit(self, fileroot): 636 os.system('sh drive_smart_fit_%s.sh' %self.files.fileroot) 637 638 def parse_smart_fit(self): 639 os.system("sh parse_smart_fit_%s.sh" %self.files.fileroot) 640 641 642 643 644 645 646 class sim_driver: 647 648 def __init__(self, dchi=4.605, telescope="", model_settings=[], fmodel_settings=[], sf q='y' ): #args are arguments 649 Xset.allowNewAttributes=True #will have to add to fit_models_settings after the fact, if I want to add ss1, ss2, ss3... 650 self.dchi=dchi 651 self.telescope=telescope 652 self.date="%s"*6 %(tuple(time.localtime()[0:6])) 653 self.date=self.date[:len(self.date)-1] 654 self.name=self.telescope+'_'+self.date 655 self.sfq=sfq 656 #self.model=model 657 #self.model_expr=model_expr #useful to keep track of later, when writing xspec f ile for smart fit 658 self.sim_id=1 659 self.model_id=1 #these numbers change during the simula ion 660 self.spectrum_id=1 661 self.run=1 662 self.sim=1 663 # self.drive_id=int(floor(self.spectrum_id/20)) #for spreading out drive_s mart_fit calculations, to speed thigns up 664 self.model_settings=model_settings 665 self.fmodel_settings=fmodel_settings 666 #self.fit_model=model #how to do this? 667 self.comp_index=1 668 self.par_index=1 669 self.mod_index=1 670 self.fmod_index=1 671 self.modelNames=[] 672 self.fmodelNames=[] 673 self.spec_mod_files={} #SPEC MODEL FILE DICTIONARY, STORES SPEC MODEL FILE NAMES , FOR SECOND PART OF DRIVE XSPEC 674 self.nComponents=0 675 self.nParameters=0 676 677 for mod_s in self.model_settings: 678 # comp_obj=self.model.__dict__[comp] 679 self.__dict__[mod_s.name]= mod_s 680 self.__dict__[mod_s.name].index= self.mod_index 681 self.mod_index+=1 682 self.modelNames.append(mod_s.name) 683 684 685 for mod_s in self.fmodel_settings: 686 # comp_obj=self.model.__dict__[comp] 687 self.__dict__[mod_s.name]= mod_s 688 self.__dict__[mod_s.name].index= self.fmod_index 689 self.fmod_index+=1 690 self.fmodelNames.append(mod_s.name) 691 692 693 def __call__(self, mod_index): 694 for mod in self.modelNames: 695 if self.__dict__[mod].mod_index==mod_index: 696 return self.__dict__[mod] 697 #THIS WORKS IF THE SIM_INDEX IS SETUP CORRECTLY 698 def reset_sim(self): #between runs, and before, make sure settings are what I want 699 print 'STARTING NEW RUN' 700 test(tq) 701 Fit.statMethod='cstat' 702 Fit.query='on' 703 AllData.clear() 704 AllModels.clear() 705 706 def make_files(self, dr=''): 707 #if dr=='def': 708 # dr=self.date+'/' 709 print 'entered make files'; test(tq) 710 #os.system('rm -r %s' %dr) 711 #os.system('mkdir %s'%dr) 712 self.files=file_manager(fileroot=dr+self.name) #fileroot created 713 #os.system("mkdir %s" %self.files.fileroot) #can be saved to later 714 #print self.fakeit_settings.response.value[0] 715 #this will give astro_h, axsio, etc. 716 #instrument_files=['res/astr/a.rmf', 'res/astr/b.arf', 'dumm/astr/.back'] 717 #instrument=instrument_files[0].split('/')[1] 718 #instrument gives 'astr' 719 # self.file_dir=self.sim_dir+"%s/"%(instrument) #will allow for drive smart fit t o be run for each instrument 720 # os.system("mkdir "+self.file_dir) - 11 - - 12 - elif os!=oos: self.model_id+=1 self.spec_id+=1 elif fks!=ofks: self.spec_id+=1 elif fts!=ofts: self.sim_id+=1 print 'only fit settings changed' test(tq, s1) except AttributeError: print "this is the first simulation" def set_current_values(self): print 'ENTERED set_current_values for model=', self.name print 'model parameter values' print self.parameter_values, for i in range(self.nParameters): #ADJUST HOW THIS WORKS FOR ONLY LISTING I NTERESTING PARAMETERS print 'par index=', i print 'par name=', self(i+1).name print 'par value= ', self.parameter_values[i] #d=raw_input() self(i+1).value=self.parameter_values[i] test(tq, s1) 75 /home/mason/.xspec/dx_comm.py Page 13 of 30 721 Mon 04 Jun 2012 03:36:01 PM PDT /home/mason/.xspec/dx_comm.py Page 14 of 30 #SOME FILES NEED TO BE IN THE SAME WORKING DIRECTORY AS WHERE DRIVE XSPEC IS EXECU 781 self.files.dsfit=open(self.files.fileroot+"_drive_smart_fit.sh" , 'w') #saved in directory for specific instrument self.files.parse_smart_fit=open(self.files.fileroot+"_parse_smart_fit.sh", 'w') self.files.sim_models_table=open(self.files.fileroot+"_models_table.csv", 'w') self.files.sim_report_n=self.files.fileroot+"_simulations_report.csv" self.files.sim_report=open(self.files.fileroot+"_simulations_report.csv", 'w') if tq=='y': pass else: self.files.so = self.files.se = open("%s_dx_log.log"%self.files.fileroot , 'w' , 0) # re-open stdout without buffering sys.stdout = os.fdopen(sys.stdout.fileno(), 'w', 0) # redirect stdout and stderr to the log file opened above os.dup2(self.files.so.fileno(), sys.stdout.fileno()) os.dup2(self.files.se.fileno(), sys.stderr.fileno()) 782 783 TED 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 792 793 794 795 796 self.files.add() #add files to filename list a=\ ''' 797 798 799 800 801 802 803 804 MODEL TABLES FILE= %s SIM REPORT FILE = %s '''%(self.files.sim_models_table.name, self.files.sim_report_n) print a test(tq) 805 806 807 808 def write_sim_info(self, ms, fms): print 'entered write sim info' ; test(tq) self.files.sim_models_table.write("run_time, ") self.files.sim_report.write("run_time, ") self.files.sim_models_table.write("sim_n, run, ") self.files.sim_report.write("sim_n, run, ") self.files.sim_models_table.write("mod_id, spec_id, " ) self.files.sim_models_table.write("fmod_id, fspec_id, " ) self.files.sim_models_table.write("mod_expr, spec_model_file, " ) self.files.sim_models_table.write(" fmod_expr, fitspec_model_file, " ) self.files.sim_report.write("mod_id, spec_id, " ) self.files.sim_report.write("fmod_id, fspec_id, ") self.files.sim_report.write("mod_expr, spec_model_file, " ) self.files.sim_report.write("fmod_expr, fitspec_model_file, ") self.files.sim_report.write("statistic, dof, statMethod, method, model_tot_rate, " ) 771 772 773 774 775 776 777 778 779 780 784 785 786 787 788 789 790 791 #write models table info for se in [ms, fms]: print 'writing fakeit settings' for data_par in se.fakeit_settings.parameterNames: self.files.sim_models_table.write('%s, ' %data_par) for other_par in se.other_settings.parameterNames: self.files.sim_models_table.write('%s, ' %other_par) #COULD BE CONFUSING THAT SOME ARE FILES, SOME ARE NAMES # for par_n in range(1, se.model.nParameters+1): # se.files.sim_models_table.write("par%d_name, par%d_init_value, " % (par_n ,par_n)) 809 810 811 812 813 814 815 816 817 # spec 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 #Opened files self.files.xspec_setup=open(self.files.run_root+"_setup.xcm", 'w') #Files to be supplied to during drive_xspec self.files.spec_file_bkg=self.files.spec_root+"_bkg"+".fak" don't need for pyx self.files.xspec_setup_name=self.files.run_root+"_setup.xcm" #setup file is for setting up model to be fed into run_smart_fit self.files.model_file=self.files.spec_root+".xcm" #initial model self.files.spec_file=self.files.spec_root+"_bkg.fak" self.files.xspec_log=self.files.run_root+"_xspec_log"+".log" self.files.sim_graph=self.files.run_root+".ps" self.files.sim_data_file=self.files.run_root+".xcm" self.files.smart_fit_log=self.files.run_root+".log" self.files.smart_fit_csv=self.files.run_root+".csv" if tq=='y': pass else: self.files.runlog=self.files.run_root+'_pyxspec.log' self.files.so_r = self.files.se_r = open("%s" % self.files.runlog, 'w', 0) # re-open stdout without buffering sys.stdout = os.fdopen(sys.stdout.fileno(), 'w', 0) # redirect stdout and stderr to the log file opened above os.dup2(self.files.so_r.fileno(), sys.stdout.fileno()) - 13 - /home/mason/.xspec/dx_comm.py Page 15 of 30 836 837 Mon 04 Jun 2012 03:36:01 PM PDT # se.files.sim_report.write("par%d_name, par%d_init_value, bestfit, low, hi gh, " % (par_n, par_n) for par_n in range(1, se.model.nParameters+1): self.files.sim_models_table.write('%s%s, value, ' %(se(par_n).name, se(par _n).par_index)) for fit_par in se.fit_settings.parameterNames: self.files.sim_models_table.write('%s, ' %fit_par) self.files.sim_models_table.write('FIT_MODEL, ') #write sim report fit info for data_par in fms.fakeit_settings.parameterNames: self.files.sim_report.write('%s, ' %data_par) for other_par in fms.other_settings.parameterNames: self.files.sim_report.write('%s, ' %other_par) #COULD BE CONFUSING TH AT SOME ARE FILES, SOME ARE NAMES # for par_n in range(1, se.model.nParameters+1): # se.files.sim_models_table.write("par%d_name, par%d_init_value, " % (par_n,par _n)) # se.files.sim_report.write("par%d_name, par%d_init_value, bestfit, low, high, " % (par_n, par_n) for par_n in range(1, fms.model.nParameters+1): self.files.sim_report.write('%s%s, best, low, high, ' %(fms(par_n).name, fms(p ar_n).par_index)) for fit_par in fms.fit_settings.parameterNames: self.files.sim_report.write('%s, ' %fit_par) #se.files.close_files() #adds filenames to a list self.files.sim_models_table.write("\n") self.files.sim_report.write("\n") #for testing only at this point def make_run_files(self): #write model info values to csv file, must be run after model has been defined print 'entered make run files' ; test(tq) #file prefixes self.files.spec_root=self.files.fileroot+"_%s_%s_"%(self.model_id, self.sim)+self. model_name#!!!!!! need to change name# self.files.sim_root=self.files.spec_root+"_fit_"+self.fit_model_name #!!!!!!!!!# once fit model aded, need to change self.files.run_root=self.files.sim_root+"_run%s" %str(self.run) print 'run root', self.files.run_root print 'making run files' test(tq, s1) - 14 - Mon 04 Jun 2012 03:36:01 PM PDT /home/mason/.xspec/dx_comm.py Page 16 of 30 Mon 04 Jun 2012 03:36:01 PM PDT self.files.sim_models_table.write('\n') #make new line so that stuff that comes after this goes to next line 882 self.files.dsfit.write("run_smart_fit.sh %s 4.605\n"%self.files.sim_data_file ) 883 print "run_smart_fit.sh %s 4.605\n"%self.files.sim_data_file 884 test(tq, s1) 885 # self.files.parse_smart_fit.write('python create_results_file.py\n') 886 self.files.parse_smart_fit.write("python parse_smart_fit.py %s %s %s\n" %(self.fil es.smart_fit_log, self.files.sim_report.name, self.files.fileroot)) 887 print "python parse_smart_fit.py %s %s\n" %(self.files.smart_fit_log, self.files.s im_report.name) 888 test(tq, s1) 889 def write_results_info(self, ms, fms): print 'WRITing results INFO'; test(tq) test(tq, s1) self.files.spec_root="%s_%s_"%(self.model_id, self.sim)+self.files.fileroot#!!!!!! need to change name# 893 self.files.sim_root=self.files.spec_root+"_fit_"+self.fit_model_name #!!!!!!!!!# once fit model aded, need to change 894 self.files.run_root=self.files.sim_root+"_run%s" %str(self.run) 895 self.files.model_file=self.files.spec_root+".xcm" 896 897 self.files.sim_report.write("%s, " %(time.ctime())) 898 self.files.sim_report.write("%s, %s, " %(self.sim, self.run)) 899 for se in [ms, fms]: 900 901 self.files.sim_report.write("%s, %s, " %(se.model_id, se.spec_id)) 902 903 for se in [ms, fms]: 904 905 self.files.sim_report.write("%s, %s, " %(se.model_expr, se.files.spec_file)) 906 907 908 #NEED TO FIGURE OUT WHERE model_id, spectrum_id, model_file is kept track of 909 try: 910 self.files.sim_report.write("%f, %f, %s, %s, %f, " %(float(fms.x_2), float(fms .dof), fms.stat, Fit.method, float(fms.count_rate))) 911 except AttributeError: 912 print 'NOTE- FIT DID PRODUCE BEST FIT VALUES- check smart_fit log=%s'%self.fil es.smart_fit_log 913 ##write initial model to simulations_report 914 915 for se in [fms]: 916 917 print 'WRITING results TO RES FILE' 918 test(tq) 919 #write best fit values to sim reports file 920 for parameter in ms.fakeit_settings.parameterNames: #fakeit settings of spectral model are only important 921 self.files.sim_report.write("%s, " %(ms.fakeit_settings.__dict__[parameter ].value)) 922 print "%s, " %(ms.fakeit_settings.__dict__[parameter].value) 923 test(tq, s1) 924 925 #DON't change from fit 926 #parameters below change after fit, have to get results which where retrie ved form parse smart fit 927 for parameter in se.other_settings.parameterNames: 928 try: 929 self.files.sim_report.write("%f, " %(se.other_settings.__dict__[parame ter].best_fit)) 930 print "%f, " %(se.other_settings.__dict__[parameter].value) 931 test(tq, s1) 932 except AttributeError: 933 if 'eqwidth' in se.other_settings.__dict__[parameter].name: 934 self.files.sim_report.write("%f, " %(se.other_settings.__dict__[pa rameter].value)) 935 else: 936 print 'check smart_fit log=%s'%self.files.smart_fit_log 937 print 'NOTE-Smart_fit did not get errors for %s'%se.other_settings .__dict__[parameter].name 938 except TypeError: 939 self.files.sim_report.write("%s, " %(se.other_settings.__dict__[parame ter].best_fit)) 940 print "%s, " %(se.other_settings.__dict__[parameter].value) 941 test(tq, s1) 942 943 for par in range(1, se.model.nParameters+1): - 15 - - 16 - 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 os.dup2(self.files.se_r.fileno(), sys.stderr.fileno()) #http://stackoverflow.com/questions/616645/how-do-i-duplicate-sys-stdout-to-a-logfile-in-python def write_run_info(self, ms, fms): print 'ENTERED write_run_info'; test(tq) test(tq, s1) self.files.model_file=self.files.spec_root+".xcm" #NEED TO FIGURE OUT WHERE model_id, spectrum_id, model_file is kept track of #NEED TO FIGURE OUT WHERE model_id, spectrum_id, model_file is kept track of j=0 self.files.sim_models_table.write("%s, " %(time.ctime())) self.files.sim_models_table.write("%s, %s, " %(self.sim, self.run)) for se in [ms, fms]: self.files.sim_models_table.write("%s, %s, " %(se.model_id, se.spec_id)) for se in [ms, fms]: self.files.sim_models_table.write(" %s, %s, " %( se.model_expr, se.files.spe c_file)) 858 859 860 861 862 863 for se in [ms, fms]: for parameter in se.fakeit_settings.parameterNames: self.files.sim_models_table.write("%s, " %(se.fakeit_settings.__dict__[par ameter].value)) 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 print "%s, " %(se.fakeit_settings.__dict__[parameter].value) test(tq, s1) for parameter in se.other_settings.parameterNames: self.files.sim_models_table.write("%s, " %(se.other_settings.__dict__[para meter].value)) print "%s, " %(se.other_settings.__dict__[parameter].value) test(tq, s1) for par in range(1, se.model.nParameters+1): self.files.sim_models_table.write("%s, %f, " %(se(par).name, se(par).value )) print "%s, %s, " %(se(par).name, se(par).value) test(tq, s1) test(tq, s1) for fit_par in se.fit_settings.parameterNames: self.files.sim_models_table.write('%s, ' %str(se.fit_settings.__dict__[fit _par].value).replace(', ', ',')) #to make it so that csv file does not split name into t woi columns print '%s, ' %str(se.fit_settings.__dict__[fit_par].value).replace(', ', ' ,') test(tq, s1) self.files.sim_models_table.write('FIT_MODEL, ') 890 891 892 76 /home/mason/.xspec/dx_comm.py Page 17 of 30 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 Mon 04 Jun 2012 03:36:01 PM PDT try: self.files.sim_report.write("%s, %f, %f, %f, " %(se(par).name, se(par) .best_fit, se(par).err_low, se(par).err_high)) print "%s, %f, %f, %f " %(se(par).name, se(par).best_fit, se(par).err_ low, se(par).err_high) test(tq, s1) except AttributeError: print 'drivexspec_WARNING- check smart_fit log=%s'%self.files.smart_fi t_log print 'NOTE-Smart_fit did not get errors for %s'%se(par).name except TypeError: self.files.sim_report.write("%s, %s, %s, %s, " %(se(par).name, se(par) .best_fit, se(par).err_low, se(par).err_high)) print "%s, %s, %s, %s " %(se(par).name, se(par).best_fit, se(par).err_ low, se(par).err_high) print 'NOTE-Smart_fit did not get errors for %s'%se(par).name test(tq, s1) for fit_par in se.fit_settings.parameterNames: self.files.sim_report.write('%s, ' %str(se.fit_settings.__dict__[fit_par]. value).replace(', ', ',')) #to make it so that csv file does not split name into twoi co lumns print '%s, ' %str(se.fit_settings.__dict__[fit_par].value).replace(', ', ' ,') test(tq, s1) self.files.sim_report.write('\n') #make new line so that stuff that comes af ter this goes to next line test(tq, s1) def write_model_to_xspec_setup(self, ms): print 'ENTERED write model 2 xspec setup' ; test(tq) # I HAVE TO DO THIS AFTER make_run_files() is run, in order to ... I also have to run it after fit, in order to get the best fit model setup_info=\ """ statistic cstat method leven 200 0.01 abund angr xsect bcmc cosmo 70 0 0.73 xset delta 0.01 systematic 0 """ self.files.xspec_setup.write(setup_info) self.files.xspec_setup.write('model %s\n' %(ms.model_expr)) #NEED TO CREATE THIS print 'writing the following values to xcm file, CHECK' for par_index in range(1, ms.model.nParameters+1): self.files.xspec_setup.write("%s\n" %(ms.model(par_index).values[0])) print ms.model(par_index).values[0] for par_index in range(1, ms.model.nParameters+1): if ms(par_index).frozen==True: self.files.xspec_setup.write("freeze %d\n" %(ms(par_index).par_index)) elif ms(par_index).frozen==False: self.files.xspec_setup.write("thaw %d\n" %(ms(par_index).par_index)) else: pass self.files.xspec_setup.write('sys rm -f %s\n' %(self.files.model_file)) self.files.xspec_setup.write('save model %s\n' %(self.files.model_file)) #save or iginal model, another copy, that can be read into xspec def write_best_fit_values_to_xspec_setup(self, ms, fms): print 'ENTERED write best fit values'; test(tq) self.files.xspec_setup.write('data '+AllData(1).fileName+'\n') #Simulated data is stored in AllData(2) 4/29 #I will oonly ever say fakeit to the spectral model, not to the fit model, so th eir shouldn't be ambiguity in which spectra AllData(1) refers to /home/mason/.xspec/dx_comm.py Page 18 of 30 self.files.xspec_setup.write('ignore '+fms.fit_settings.ignore.value+'\n') self.files.xspec_setup.write('model %s\n' %(fms.model_expr)) #NEED TO CREATE THIS print 'writing the following values to xcm file, CHECK' for par_index in range(1, fms.model.nParameters+1): #after fit, save model to xcm file, to be saved in save all 1000 self.files.xspec_setup.write("%s\n" %(fms.model(par_index).values[0])) 1001 print fms.model(par_index).values[0] 1002 1003 for par_index in range(1, fms.model.nParameters+1): 1004 if fms(par_index).frozen==True: 1005 self.files.xspec_setup.write("freeze %d\n" %(fms(par_index).par_index)) 1006 elif fms(par_index).frozen==False: 1007 self.files.xspec_setup.write("thaw %d\n" %(fms(par_index).par_index)) 1008 else: 1009 pass 1010 #self.files.xspec_setup.write('fit 100 0.01\n') #IS THIS NECESSARY? WILL THIS B E A PARAMETER AT SOME POINT? 1011 self.files.xspec_setup.write('sys rm -f %s\n' %(self.files.sim_data_file)) 1012 self.files.xspec_setup.write('save all %s\n' %(self.files.sim_data_file)) 1013 self.files.xspec_setup.close() #MOVE IF THIS IS INCONVENIENT, but it needs to be closed, and it is not in the file manager, and it doesn't need to be 1014 def feed_xcm_to_xspec(self): #defines data model and records best_fit model parame ter to be read into smart_fit 1015 print 'ENTERED feed xcm' ; test(tq) #FOR SMART FIT 1016 os.system("rm -f %s" %(self.files.xspec_log)) 1017 os.system('xspec <%s> %s' %(self.files.xspec_setup.name, self.files.xspec_log)) 1018 #FIT OCCURS IN pyxspec, fit not done in xspec 1019 # def close(self, afile): 1020 # afile.close() 1021 1022 1023 def plot(self, ms): 1024 print 'ENTERED plot'; test(tq) 1025 Plot.xAxis=ms.fit_settings.xAxis.value 1026 a=ms.fit_settings.setRebin.value.split() 1027 Plot.setRebin(a[0], a[1]) 1028 Plot.device='/ps' 1029 Plot(ms.fit_settings.plot.value) 1030 Plot.device='none' 1031 os.system('mv pgplot.ps %s' %(self.files.sim_graph)) 1032 1033 def plots(self, x): #FURTHER DEVELOP FOR SPECIAL PLOTS 1034 pass 1035 ''' 1036 print 'ENTERED plot special'; test(tq) 1037 fil=open(self.files.sim_report, 'r').readlines() 1038 vals0=fil[0].split(',').strip() 1039 for i in range(len(vals0): 1040 if x in vals0[i]: 1041 j=i 1042 bests=[] 1043 lows=[] 1044 highs=[] 1045 for line in fil: 1046 vals=line.split(',').strip() 1047 if vals[0]=='run_time': 1048 continue 1049 else: 1050 best=vals[j+1] 1051 low=vals[j+2] 1052 high=vals[j+3] 1053 ''' 1054 1055 1056 - 17 - /home/mason/.xspec/dx_comm.py Page 19 of 30 1057 1058 1059 - 18 - Mon 04 Jun 2012 03:36:01 PM PDT def drive_smart_fit(self): print 'ENTERED drive smart fit'; test(tq) #do this after you have made all the models? Don't make it apart of drive_xspec 1060 os.system("sh %s" %self.files.dsfit.name) 1061 1062 def set_current_values(self, ms): 1063 print 'ENTERED entered set current values'; test(tq) 1064 for i in range(ms.nParameters): #ADJUST HOW THIS WORKS FOR ONLY LISTING INT ERESTING PARAMETERS 1065 ms(i+1).value=ms.parameter_values[i] 1066 print ms(i+1).value, "par%s value" %i 1067 test(tq, s1) 1068 1069 def set_fit_model_values(self): 1070 pass #MAKE IT SO YOU CAN ITERATE OVER ALL PARAMETERS 1071 1072 1073 def run_smart_fit(self, filename, dchi): 1074 1075 #OPTION, SMART_FIT CAN BE RUN DURING, or outside of iteration 1076 if self.sfq=='n': 1077 print 'bypassed run_smart fit'; test(tq) 1078 pass 1079 else: 1080 print 'ENTERED run_smart fit'; test(tq) 1081 os.system('run_smart_fit.sh %s %f' %(filename, dchi )) 1082 1083 ''' 1084 def drive_smart_fit_b(self, pr, fil, fileroot): 1085 #########ATTEMPT TO MAKE IT SO SMART FIT COULD BE RUN WITH SEVERAL PROCESSES AT TH E THE SAME TIME. NOT DONE 1086 1087 dsf=open(fil, 'r').readlines() 1088 print dsf 1089 d=raw_input('CHECK') 1090 n_l=len(dsf) 1091 1092 p_s=int(n_l/pr) 1093 1094 dsf_s_list=[] 1095 for i in range(pr): 1096 filename=fil.split('.') 1097 filename=filename[0]+'_%s'%i+'.'+filename[1] 1098 dsf_s=open(filename, 'w') 1099 dsf_s_list.append(dsf_s) 1100 if i==pr-1: 1101 print 'this is last process' 1102 for l_n in range(i*p_s,n_l): 1103 dsf_s.write(dsf[l_n]) 1104 dsf_s.write('\n') 1105 else: 1106 1107 for l_n in range(i*p_s, (i+1)*p_s): 1108 dsf_s.write(dsf[l_n]) 1109 dsf_s.write('\n') 1110 1111 dsfl_n=[] 1112 for i in dsf_s_list: 1113 print i.name 1114 i.close() 1115 dsf_s=open(i.name, 'r') 1116 dsfl_n.append(dsf_s) 1117 d=raw_input('CHECK ME') 1118 - 19 - Mon 04 Jun 2012 03:36:01 PM PDT 996 997 998 999 /home/mason/.xspec/dx_comm.py Page 20 of 30 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 dsfl_n=make_spf(NUM_PROCESSES, fil) children = [] start_time = time.time() for process in range(NUM_PROCESSES): pid = os.fork() if pid: children.append(pid) else: rl1(dsfl_n[process]) os._exit(0) for i, child in enumerate(children): os.waitpid(child, 0) print time.time() - t os.system('sh drive_smart_fit_%s.sh' %self.files.fileroot) ''' def parse_smart_fit(self, ms, fms): print 'ENTERED parse_smart fit'; test(tq) #will have to figure out how to make it look for just the fit parameters soon #from the drive_xspec script, # save model to sim_model file. #can access later # #d=raw_input() if self.sfq=='n': print 'GETTING FIT INFO FROM XSPEC, NOT SMART FIT' fms.x_2=Fit.statistic fms.dof=Fit.dof fms.count_rate=0.00 fms.stat=Fit.statMethod else: try: ) 1180 1181 1182 Mon 04 Jun 2012 03:36:01 PM PDT for i in dsfl_n: print i, type(i) #print i.readlines() rl1(i) d=raw_input('cHECK') #rl1(i) return(dsfl_n) #RETURNS LIST OF DRIVE SMART FIT FILES #sf_log=open(self.files.smart_fit_csv, 'r').readlines() sf_log_reader = csv.reader(open(self.files.smart_fit_csv, "rb")) for line in sf_log_reader: print line #vals=line.strip().split(',') vals=line ''' for j in range(0, len(vals)): vals[j]=vals[j].strip('"').strip().strip("'").strip('"').strip("'" #strip spaces ''' try: - 20 - 77 /home/mason/.xspec/dx_comm.py Page 21 of 30 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 Mon 04 Jun 2012 03:36:01 PM PDT parn=int(vals[1]) thaw_par=fms(parn) if thaw_par.frozen==True: pass else: if thaw_par.name in vals[2]: try: thaw_par.best_fit=float(vals[3]) thaw_par.err_low=float(vals[5]) thaw_par.err_high=float(vals[6]) thaw_par.fit=[thaw_par.best_fit, thaw_par.err_low, tha w_par.err_high] 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 print thaw_par.name +' best fit' print '[bf, low, high]' print thaw_par.fit test(tq, s1) except ValueError: print 'PROBLEM: thaw_par does not have fit values' else: print 'PROBLEM: par index, name mismatch???????????' except ValueError: pass if vals[2]=='F(0.5-2.0)': fms.__dict__['other_settings'].__dict__['flux0.5-2.0'].best_fit=fl /home/mason/.xspec/dx_comm.py Page 22 of 30 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 for par in range(1, fms.model.nParameters+1): thaw_par=fms(par) if thaw_par.name in vals[0]: if len(vals)==6: thaw_par.best_fit=float(vals[2]) thaw_par.err_low=float(vals[3][1:]) thaw_par.err_high=float(vals[5][0:len(vals[5])-1]) thaw_par.fit=[thaw_par.best_fit, thaw_par.err_low, thaw_par.er r_high] #self.files.sim_report.write('%s, ' %(fms.__dict__['other_settings '].__dict__['flux0.5-2.0'].best_fit)) 1209 if vals[2]=='F(2.0-10.0)': 1210 fms.__dict__['other_settings'].__dict__['flux2.0-10.0'].best_fit=f loat(vals[3].split()[0]) 1211 #self.files.sim_report.write('%s, ' %(fms.__dict__['other_settings '].__dict__['flux0.5-2.0'].best_fit)) 1212 1213 if vals[2]=='fit stat' : 1214 fms.x_2=float(vals[3]) 1215 1216 if vals[2]=='fit stat name' : 1217 fms.stat=str(vals[3]) 1218 1219 1220 if vals[2]=='dof' : 1221 fms.dof=float(vals[3]) 1222 1223 if vals[2]=='model total rate': 1224 fms.count_rate=float(vals[4]) 1225 1226 try: 1227 fms.x_2 1228 fms.dof 1229 fms.count_rate 1230 fms.stat 1231 except AttributeError: 1232 fms.x_2='' 1233 fms.dof='' 1234 fms.count_rate='' 1235 fms.stat='NA' 1236 except IOError: 1237 print 'SMART FIT LOG NOT CREATED' 1238 fms.x_2='' 1239 fms.dof='' 1240 fms.count_rate='' 1241 fms.stat='NA' 1242 1268 1269 1270 1271 1272 1273 print thaw_par.name +' best fit' print '[bf, low, high]' print thaw_par.fit test(tq, s1) #self.files.sim_report.write('%s, %s, %s, %s, ' %(thaw_par.name, thaw_ par.best_fit, thaw_par.err_low, thaw_par.err_high)) #already done in write2results funct ion 1274 1275 1276 1277 if vals[0]=='F(0.5-2.0': fms.__dict__['other_settings'].__dict__['flux0.5-2.0'].best_fit=float( vals[3]) 1278 #self.files.sim_report.write('%s, ' %(fms.__dict__['other_settings']._ _dict__['flux0.5-2.0'].best_fit)) 1279 if vals[0]=='F(2.0-10.0': 1280 fms.__dict__['other_settings'].__dict__['flux2.0-10.0'].best_fit=float (vals[3]) 1281 #self.files.sim_report.write('%s, ' %(fms.__dict__['other_settings']._ _dict__['flux0.5-2.0'].best_fit)) 1282 1283 if vals[0]=='Final' and vals[1]=='chisq(dof)': 1284 fms.x_2=float(vals[3].split('(')[0]) 1285 fms.dof=float(vals[3].split('(')[1].split(')')[0]) #sel f.files.sim_report.write('%s, ' %(count_rate)) 1286 if vals[0]=='Count' and vals[1]=='rates:': 1287 fms.count_rate=float(vals[2]) 1288 1289 1290 try: 1291 fms.x_2 1292 fms.dof 1293 fms.count_rate 1294 fms.stat 1295 except AttributeError: 1296 fms.x_2=-3.14159 1297 fms.dof=-3.14159 1298 fms.count_rate=-3.14159 - 21 - /home/mason/.xspec/dx_comm.py Page 23 of 30 1331 1332 1333 1334 1335 1336 1337 1338 - 22 - Mon 04 Jun 2012 03:36:01 PM PDT fms.stat='NA' except IOError: print 'SMART FIT LOG NOT CREATED' fms.x_2=-2.71 fms.dof=-2.71 fms.count_rate=-2.71 fms.stat='NA' def drive_parse_smart_fit(self, ms, fms): print 'ENTERED parse_smart fit'; test(tq) os.system("sh parse_smart_fit_%s.sh" %self.files.fileroot) #d=raw_input('press BUTTON to continue') def make_model_spectra(self, nruns): #drive_xspec #self.make_files(self.name+'_'+self.date+'/') self.make_files() for ms in self.model_settings: self.files.open_files() ms.make_files() ms.mod_flag=True; ms.fmod_flag=False self.ms=ms self.model_name=ms.name #ms.make_files(self.name+'_'+self.date+'/') ms.par_sets=itertools.product(*ms.parameter_ranges) ms.par_names_ranges=dict(zip(ms.parameterNames, ms.parameter_ranges)) ms.par_sets=itertools.product(*ms.parameter_ranges) #must be redefined as once it is read once, it is gone ms.par_names_ranges=dict(zip(ms.parameterNames, ms.parameter_ranges)) for mpar_set in ms.par_sets: ms.parameter_values=mpar_set ms.check_id() self.spec_mod_files[ms.sim_id]=[] for run in range(1, nruns+1): ms.make_run_files(self.name) #only needed for spectrum file name 1339 1340 # #THIS L self.par_names_vals=dict(zip(self.parameterNames, self.parameter_valu es)) 1341 1342 #create spectral data ms.set_model() #TRY TO THINK OF WAYS TO NOT HAVE TO CALCULATE MODEL SO MUCNH 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 #length of error line in s mart_fit output 1264 1265 1266 1267 oat(vals[3].split()[0]) 1208 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 Mon 04 Jun 2012 03:36:01 PM PDT def parse_smart_fit_log(self, ms, fms): print 'ENTERED parse_smart fit'; test(tq) #will have to figure out how to make it look for just the fit parameters soon #from the drive_xspec script, # save model to sim_model file. #can access later # #d=raw_input() try: sf_log=open(self.files.smart_fit_log, 'r').readlines() for line in sf_log: vals=line.strip().split() # print 'smart fit vals', vals # d=raw_input() ms.set_fakeit(1) ms.set_model() ms.set_flux() ms.set_eqwidths() ms.get_flux_high() ms.set_fakeit(1) self.spec_mod_files[ms.sim_id].append(ms.files.spec_file) ms.sim+=1 ms.old_parameter_values=ms.parameter_values and model id (shit) #for determining spectrum id /home/mason/.xspec/dx_comm.py Page 24 of 30 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 def drive_xspec(self, nruns): #drive_xspec 1418 1419 - 23 - Mon 04 Jun 2012 03:36:01 PM PDT #self.make_files(self.name+'_'+self.date+'/') self.make_files() for ms in self.model_settings: self.files.open_files() ms.make_files() ms.mod_flag=True; ms.fmod_flag=False self.ms=ms self.model_name=ms.name #ms.make_files(self.name+'_'+self.date+'/') ms.par_sets=itertools.product(*ms.parameter_ranges) ms.par_names_ranges=dict(zip(ms.parameterNames, ms.parameter_ranges)) for fms in self.fmodel_settings: self.files.open_files() fms.make_files() ms.mod_flag=False; fms.fmod_flag=True if fms.name==ms.name: ms.mod_flag=True self.fms=fms self.fit_model_name=fms.name print 'spec model, fit model' print self.model_name, self.fit_model_name test(tq, s1) #fms.make_files(self.name+'_'+self.date+'/') self.write_sim_info(ms, fms) ms.par_sets=itertools.product(*ms.parameter_ranges) #must be redefined as once it is read once, it is gone ms.par_names_ranges=dict(zip(ms.parameterNames, ms.parameter_ranges)) fms.par_sets=itertools.product(*fms.parameter_ranges) fms.par_names_ranges=dict(zip(fms.parameterNames, fms.parameter_ranges)) ind=0 for ps in itertools.product(*ms.parameter_ranges): ind+=1 j=0 for ps in itertools.product(*fms.parameter_ranges): j+=1 print 'NUMBER OF COMBINATIONS, SIMULATIONS SHOULD=', ind*j, 'FOR CURRENT M ODEL, FIT MODEL COMBO' test(tq) #print 'lengh ms.par_sets=', len(ms.par_sets) for mpar_set in ms.par_sets: fms.par_sets=itertools.product(*fms.parameter_ranges) ms.parameter_values=mpar_set ms.check_id() for fmpar_set in fms.par_sets: fms.parameter_values=fmpar_set fms.check_id() print fms.parameter_values test(tq, s1) ms.set_current_values() fms.set_current_values() #self.check_id(ms) for run in range(1, nruns+1): self.files.open_files() self.reset_sim() #clears data and models self.run=run self.make_run_files() ms.make_run_files(self.name) #only needed for spectrum file na me fms.make_run_files(self.name) #THIS L # self.par_names_vals=dict(zip(self.parameterNames, self.parame ter_values)) #create spectral data ms.set_model() #TRY TO THINK OF WAYS TO NOT HAVE TO CALCULAT - 24 - 78 /home/mason/.xspec/dx_comm.py Page 25 of 30 Mon 04 Jun 2012 03:36:01 PM PDT MODEL SO MUCNH 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 ms.set_fakeit(1) ms.set_model() ms.set_flux() ms.set_eqwidths() ms.get_flux_high() self.write_model_to_xspec_setup(ms) ms.set_fakeit(1) #print 'DATA SPECTRUM=', AllData(1).fileName #create fit model fms.set_model() fms.set_fakeit(1) fms.set_model() fms.set_flux() fms.set_eqwidths() fms.get_flux_high() AllModels.show() print 'BEFORE' AllData.clear() #remove fms, so there is no ambiguity of whi ch data is being fit 1438 s5=Spectrum(ms.files.spec_file) #reload correct model spectru m 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 AllData.show() AllModels.show() print 'data file name should be' , ms.files.spec_file print 'check that model BEFORE did not change' test(tq) print 'Model SPECTRUM=', AllData(1).fileName #AllData("%s 2:2 %s"%(AllData(1).fileName, AllData(2).fileName )) # Apply current model ('correct' fit model) to both spectra self.write_run_info(ms, fms) fms.set_fit() self.plot(ms) self.write_best_fit_values_to_xspec_setup(ms, fms) self.feed_xcm_to_xspec() self.run_smart_fit(self.files.sim_data_file, self.dchi) self.parse_smart_fit(ms, fms) #self.parse_smart_fit_log(ms, fms) self.write_results_info(ms, fms) self.files.close_files() self.sim+=1 ms.sim+=1 fms.sim+=1 ms.old_parameter_values=ms.parameter_values #for determining spec trum id and model id (shit) fms.old_parameter_values=fms.parameter_values #run smart fit self.files.close_files() #self.drive_smart_fit() #code below code be used if smart_fit is run externally. currently won't work. ''' #parse_smart_fit for ms in self.model_settings: ms.make_files('') for fms in self.fmodel_settings: fms.make_files('') ms.par_sets=itertools.product(*ms.parameter_ranges) #must be redefined as once it is read once, it is gone 1474 ms.par_names_ranges=dict(zip(ms.parameterNames, ms.parameter_ranges)) 1475 fms.par_sets=itertools.product(*fms.parameter_ranges) 1476 fms.par_names_ranges=dict(zip(fms.parameterNames, fms.parameter_ranges)) 1477 for mpar_set in ms.par_sets: 1478 for fmpar_set in fms.par_sets: /home/mason/.xspec/dx_comm.py Page 26 of 30 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 def drive_xspec2(self, nruns): self.make_model_spectra(nruns) #drive_xspec #self.make_files(self.name+'_'+self.date+'/') self.make_files() for ms in self.model_settings: ms.reset_ids() self.files.open_files() ms.make_files() ms.mod_flag=True; ms.fmod_flag=False self.ms=ms self.model_name=ms.name #ms.make_files(self.name+'_'+self.date+'/') ms.par_sets=itertools.product(*ms.parameter_ranges) ms.par_names_ranges=dict(zip(ms.parameterNames, ms.parameter_ranges)) for fms in self.fmodel_settings: self.files.open_files() fms.make_files() ms.mod_flag=False; fms.fmod_flag=True if fms.name==ms.name: ms.mod_flag=True self.fms=fms self.fit_model_name=fms.name print 'spec model, fit model' print self.model_name, self.fit_model_name test(tq, s1) #fms.make_files(self.name+'_'+self.date+'/') self.write_sim_info(ms, fms) ms.par_sets=itertools.product(*ms.parameter_ranges) #must be redefined as once it is read once, it is gone 1537 ms.par_names_ranges=dict(zip(ms.parameterNames, ms.parameter_ranges)) 1538 fms.par_sets=itertools.product(*fms.parameter_ranges) 1539 fms.par_names_ranges=dict(zip(fms.parameterNames, fms.parameter_ranges)) 1540 ind=0 1541 for ps in itertools.product(*ms.parameter_ranges): 1542 ind+=1 - 25 - /home/mason/.xspec/dx_comm.py Page 27 of 30 - 26 - Mon 04 Jun 2012 03:36:01 PM PDT 1543 1544 1545 1546 j=0 for ps in itertools.product(*fms.parameter_ranges): j+=1 print 'NUMBER OF COMBINATIONS, SIMULATIONS SHOULD=', ind*j, 'FOR CURRENT M ODEL, FIT MODEL COMBO' 1547 test(tq) 1548 #print 'lengh ms.par_sets=', len(ms.par_sets) 1549 1550 for mpar_set in ms.par_sets: #cheap way to make it so check id works corr ectly first time 1551 ms.old_parameter_values=mpar_set 1552 break 1553 1554 ms.par_sets=itertools.product(*ms.parameter_ranges) 1555 for mpar_set in ms.par_sets: 1556 fms.par_sets=itertools.product(*fms.parameter_ranges) 1557 ms.parameter_values=mpar_set 1558 ms.check_id() 1559 for fmpar_set in fms.par_sets: 1560 fms.parameter_values=fmpar_set 1561 fms.check_id() 1562 print fms.parameter_values 1563 test(tq, s1) 1564 ms.set_current_values() 1565 fms.set_current_values() 1566 #self.check_id(ms) 1567 for run in range(1, nruns+1): 1568 1569 self.files.open_files() 1570 self.reset_sim() #clears data and models 1571 self.run=run 1572 self.make_run_files() 1573 ms.make_run_files(self.name) #only needed for spectrum file na me 1574 fms.make_run_files(self.name) 1575 #THIS L 1576 # self.par_names_vals=dict(zip(self.parameterNames, self.parame ter_values)) 1577 #create spectral data 1578 #print 'DATA SPECTRUM=', AllData(1).fileName 1579 #create fit model 1580 fms.set_model() 1581 fms.set_fakeit(1) 1582 fms.set_model() 1583 fms.set_flux() 1584 fms.set_eqwidths() 1585 fms.get_flux_high() 1586 AllModels.show() 1587 print 'BEFORE' 1588 AllData.clear() #remove fms, so there is no ambiguity of whi ch data is being fit 1589 ms.files.spec_file=self.spec_mod_files[ms.sim_id][run-1] #THI S IS WHERE SPECTRAL DATA FILE NAME IS RETRIEVED 1590 s5=Spectrum(ms.files.spec_file) #reload correct model spectru m 1591 AllData.show() 1592 AllModels.show() 1593 print 'data file name should be' , ms.files.spec_file 1594 print 'check that model BEFORE did not change' 1595 test(tq) 1596 print 'Model SPECTRUM=', AllData(1).fileName 1597 #AllData("%s 2:2 %s"%(AllData(1).fileName, AllData(2).fileName )) # Apply current model ('correct' fit model) to both spectra 1598 self.write_run_info(ms, fms) 1599 fms.set_fit() - 27 - Mon 04 Jun 2012 03:36:01 PM PDT self.model_name=ms.name self.fit_model_name=fms.name print 'entered par set for PARSE SMART FIT ROUTINE' test(tq) ms.parameter_values=mpar_set print ms.parameter_values test(tq) ms.set_current_values() fms.parameter_values=fmpar_set self.check_id(ms) for run in range(1, nruns+1): self.run=run self.parse_smart_fit_new() self.write_results_info(ms, fms) self.files.close_files() # self.drive_smart_fit() # self.parse_smart_fit() #WRITE OUT FILES # if 'eqwidth' not in par_names_vals.keys(): # self.save_model() # self.set_fakeit() # if 'eqwidth' in par_names_vals.keys(): # self.set_eqwidth() # self.set_fakeit() #simply the pyxspec command ''' /home/mason/.xspec/dx_comm.py Page 28 of 30 Mon 04 Jun 2012 03:36:01 PM PDT 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 self.plot(ms) self.write_best_fit_values_to_xspec_setup(ms, fms) self.feed_xcm_to_xspec() self.run_smart_fit(self.files.sim_data_file, self.dchi) self.parse_smart_fit(ms, fms) #self.parse_smart_fit_log(ms, fms) self.write_results_info(ms, fms) self.files.close_files() self.sim+=1 ms.sim+=1 fms.sim+=1 ms.old_parameter_values=ms.parameter_values #for determining spec trum id and model id (shit) 1612 fms.old_parameter_values=fms.parameter_values 1613 #run smart fit 1614 self.files.close_files() 1615 #self.drive_smart_fit() 1616 1617 1618 def setup_drive(s_file, dlm): 1619 if dlm=='tab': 1620 dlm='\t' 1621 else: 1622 dlm=',' 1623 reader = csv.reader(open(s_file, "rb"), delimiter=dlm) 1624 #print reader.dialect.delimiter 1625 #print dir(reader) 1626 #sys.exit() 1627 date="%s"*6 %(tuple(time.localtime()[0:6])) 1628 dxlog='dx_setup_log_%s.log'%date 1629 if tq=='y': 1630 pass 1631 else: 1632 so = se = open("%s" %dxlog, 'w', 0) 1633 # re-open stdout without buffering 1634 sys.stdout = os.fdopen(sys.stdout.fileno(), 'w', 0) 1635 # redirect stdout and stderr to the log file opened above 1636 os.dup2(so.fileno(), sys.stdout.fileno()) 1637 os.dup2(se.fileno(), sys.stderr.fileno()) 1638 1639 1640 #reads the sim_settings.csv file to initiate drive xspec 1641 1642 sp_mod_settings=[] 1643 fit_mod_settings=[] 1644 ss_n=0 1645 mod_s=None 1646 i=0 1647 #for wline in s_file2: 1648 for line in reader: 1649 #print wline 1650 #line=wline.split(dlm) 1651 1652 print line 1653 ''' 1654 for j in range(0, len(line)): 1655 print 'before' 1656 print line[j] 1657 print type(line[j]) 1658 line[j]=line[j].strip('"').strip("'").strip('"').strip("'").strip('"').strip(" '") #strip spaces and comments from line entries 1659 #print line 1660 print 'after' 1661 print line[j] 1662 print type(line[j]) - 28 - 79 /home/mason/.xspec/dx_comm.py Page 29 of 30 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 Mon 04 Jun 2012 03:36:01 PM PDT ''' if line[0]=='simulation': tel_n=line[1] nruns=int(line[2]) dchi=float(line[3]) print 'sim name', '\t', 'nruns' print tel_n, '\t', nruns elif line[0]=='spec_model_settings': print 'BUILDING SPEC MODEL' mod_s=line[0] pars=[] comps=[] elif line[0]=='fit_model_settings': print 'BUILDING FIT MODELs' mod_s=line[0] elif line[0]=='begin_sim_settings': ss_n+=1 print 'building sim_settings ' , ss_n test(tq) pars=[] comps=[] elif line[0]=='': pass elif line[0]=='par': par_name=line[1] ffl=line[2] eqwf=line[3] frz=line[4] link=line[5] print 'ff, ef, fr, link' print ffl, eqwf, frz if ffl=='y' or ffl=='Y' or ffl=='yes' or ffl=='YES': ff=True else: ff=False if eqwf=='y' or eqwf=='Y' or eqwf=='yes' or eqwf=='YES': ef=True else: ef=False if frz=='y' or frz=='Y' or frz=='yes' or frz=='YES': fr=True else: fr=False print ff, ef, fr, link lf=line[6] logf=line[7] l0=8 print 'listflag=', lf if lf=='y' or lf=='Y' or lf=='yes' or lf=='YES': print 'list flag is True' values=[] for ii in range(l0, len(line)): if ii==l0: try: values.append(float(line[ii])) - 29 - /home/mason/.xspec/dx_comm.py Page 30 of 30 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 Mon 04 Jun 2012 03:36:01 PM PDT except ValueError: values.append(line[ii]) else: if line[ii]=='' or line[ii]=='\n': break try: values.append(float(line[ii])) except ValueError: values.append(line[ii]) par=sim_parameter(name=par_name, par_range=values, flux_flag=ff, eqwidth _flag=ef, frozen=fr, link=link) pars.append(par) else: ns=int(line[10]) low=float(line[8]) if ns==0: high=3.14159 try: high=float(line[9]) except ValueError: high=3.14159 #dummy value print 'logfl' print logf if logf=='y' or logf=='yes' or logf=='YES' or logf=='Y': logfl=True else: logfl=False print logfl par=sim_parameter(par_name, par_range=[low, high], nsteps=ns, log_flag=lo gfl, flux_flag=ff, eqwidth_flag=ef, frozen=fr, link=link) pars.append(par) elif line[0]=='comp': comp=sim_component(line[1], pars) comps.append(comp) pars=[] elif line[0]=='model_settings': mod_settings=comps pars=[] comps=[] elif line[0]=='other_settings': par=sim_parameter('flux2.0-10.0', par_range=[1.0], nsteps=0, log_flag=False, flux_flag=False, eqwidth_flag=False) pars.append(par) o_set=sim_component(line[0], pars) print 'AAAAAAAAAAAAAAAAAAAAA', print o_set.parameterNames pars=[] elif line[0]=='fakeit_settings': fk_set=sim_component(line[0], pars) for par in fk_set.sim_parameters: print 'par name=', par.name print 'par values=', par.values pars=[] elif line[0]=='fit_settings': fit_set=sim_component(line[0], pars) for par in fit_set.sim_parameters: print 'par name=', par.name print 'par values=', par.values pars=[] elif line[0]=='end_sim_settings': - 30 -