X-ray Emissions in Measurements of the Neutron Capture Cross Sections... Production of Hg and Pt

advertisement
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 -
Download